Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75620dd9ef | ||
|
|
f47c9bd928 | ||
|
|
40f4f86ffa | ||
|
|
29cb229cd3 | ||
|
|
a66e88e666 | ||
|
|
a36d266254 | ||
|
|
3697450317 | ||
|
|
3748456d22 | ||
|
|
04e759f9c5 | ||
|
|
dade6ac615 | ||
|
|
14198aee85 | ||
|
|
60d058cc7a | ||
|
|
bfdfc4728c | ||
|
|
f95fff6588 | ||
|
|
6667f1c8d8 | ||
|
|
20328895a2 | ||
|
|
7ecdf370bc | ||
|
|
ea2d67414a | ||
|
|
14d8754e34 | ||
|
|
d3c9e43437 | ||
|
|
9a4d2fce48 | ||
|
|
26597a5cac | ||
|
|
d4e232a776 | ||
|
|
52f2c19769 | ||
|
|
960472ed35 | ||
|
|
9c9029d0b6 | ||
|
|
39cd184c29 | ||
|
|
e2ee1eb30b | ||
|
|
d4ac65d0c1 | ||
|
|
7292c263ef | ||
|
|
151853df0d | ||
|
|
d9abf02894 | ||
|
|
24648e6eb3 | ||
|
|
9c0002bf1f | ||
|
|
0159b0e7ce | ||
|
|
ff88ccb1cd | ||
|
|
7ab8780c25 | ||
|
|
76ad75fc2a | ||
|
|
27b1ad108d | ||
|
|
2dc030e61d | ||
|
|
5b9f520e78 | ||
|
|
8e310fd264 | ||
|
|
6b119e60f5 | ||
|
|
b8b884d205 | ||
|
|
95de230835 | ||
|
|
c05ad2200f | ||
|
|
55775ab0d2 | ||
|
|
6456a027e5 | ||
|
|
92e4ce9b93 | ||
|
|
fa57fed2df | ||
|
|
c21a98ebe5 | ||
|
|
d7e77a3e61 | ||
|
|
020735e3a7 | ||
|
|
aaa1080a7c | ||
|
|
7fcb793cd9 | ||
|
|
28a2cd068d | ||
|
|
a380b84545 | ||
|
|
e47c096b73 | ||
|
|
99ccfa35bb | ||
|
|
609114c0a9 | ||
|
|
14d9a53162 | ||
|
|
2dd077cc53 | ||
|
|
41279a8dcc | ||
|
|
d3a28c50cf | ||
|
|
17ac18d675 | ||
|
|
3d8d7995d7 | ||
|
|
9dfc02a38c | ||
|
|
1c68f2ec73 | ||
|
|
d9aa82b025 | ||
|
|
a0434a8af5 | ||
|
|
18de17084d | ||
|
|
ffdfdfb66b | ||
|
|
4b242c3f84 | ||
|
|
8d1f17fc44 | ||
|
|
404a67d089 | ||
|
|
fac77101fb | ||
|
|
80e0426dd6 | ||
|
|
dd3c4ba015 | ||
|
|
92b645786d | ||
|
|
2cba62718f | ||
|
|
aa6a56863d | ||
|
|
501222044c | ||
|
|
d5f13c5116 | ||
|
|
4df03284a8 | ||
|
|
8cd0823978 | ||
|
|
64a98af676 | ||
|
|
7ca082887a | ||
|
|
a008cc03b7 | ||
|
|
ae5fa08abd | ||
|
|
6287954087 | ||
|
|
b978e35636 | ||
|
|
5c072d5bce | ||
|
|
1559db9d1a | ||
|
|
1cc0ad510a | ||
|
|
4d86a8f3f6 | ||
|
|
e005030995 | ||
|
|
ee691c23f4 | ||
|
|
9698657f7a | ||
|
|
79bf41ea8b | ||
|
|
41b5353338 | ||
|
|
378986841c | ||
|
|
b9a8000bbd | ||
|
|
eedb4bf944 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
# Files that are generated as part of the build process which we do not want git
|
||||
# to track.
|
||||
|
||||
/.pc
|
||||
|
||||
*.[oa]
|
||||
*.mod
|
||||
*.mod.[oc]
|
||||
|
||||
4
Makefile
4
Makefile
@@ -102,8 +102,6 @@ install-modconf:
|
||||
/sbin/update-modules ; \
|
||||
fi
|
||||
|
||||
install-xpp-firm:
|
||||
$(MAKE) -C drivers/dahdi/xpp/firmwares install
|
||||
|
||||
install-firmware:
|
||||
ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
@@ -190,8 +188,10 @@ dist-clean: clean
|
||||
firmware-download:
|
||||
@$(MAKE) -C drivers/dahdi/firmware all
|
||||
|
||||
ifneq (,$(wildcard test-script))
|
||||
test:
|
||||
./test-script $(DESTDIR)/lib/modules/$(KVERS) dahdi
|
||||
endif
|
||||
|
||||
docs: $(GENERATED_DOCS)
|
||||
|
||||
|
||||
235
README
235
README
@@ -12,43 +12,46 @@ Supported Hardware
|
||||
------------------
|
||||
Digital Cards
|
||||
~~~~~~~~~~~~~
|
||||
- wcte43x:
|
||||
* Digium TE435: PCI express quad-port T1/E1/J1
|
||||
* Digium TE436: PCI quad-port T1/E1/J1
|
||||
* Digium TE235: PCI express dual-port T1/E1/J1
|
||||
* Digium TE236: PCI dual-port T1/E1/J1
|
||||
- wcte13xp:
|
||||
* Digium TE131: PCI express single-port T1/E1/J1
|
||||
* Digium TE133: PCI express single-port T1/E1/J1 with echocan
|
||||
* Digium TE132: PCI single-port T1/E1/J1
|
||||
* Digium TE134: PCI single-port T1/E1/J1 with echocan
|
||||
- wct4xxp:
|
||||
* Digium TE205P/TE207P/TE210P/TE212P: PCI dual-port T1/E1/J1
|
||||
* Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1
|
||||
* Digium TE220: PCI-Express dual-port T1/E1/J1
|
||||
* Digium TE420: PCI-Express quad-port T1/E1/J1
|
||||
* Digium TE820: PCI-Express eight-port T1/E1/J1
|
||||
- wcte12xp:
|
||||
* Digium TE120P: PCI single-port T1/E1/J1
|
||||
* Digium TE121: PCI-Express single-port T1/E1/J1
|
||||
* Digium TE122: PCI single-port T1/E1/J1
|
||||
- wcte11xp:
|
||||
* Digium TE110P: PCI single-port T1/E1/J1
|
||||
- wct1xxp:
|
||||
* Digium T100P: PCI single-port T1
|
||||
* Digium E100P: PCI single-port E1
|
||||
- wcb4xxp:
|
||||
* Digium B410: PCI quad-port BRI
|
||||
- tor2: Tormenta quad-span T1/E1 card from the Zapata Telephony project
|
||||
* Digium B233: PCI-Express dual-port BRI with echo can
|
||||
* Digium B234: PCI dual-port dual-port BRI with echo can
|
||||
* Digium B433: PCI-Express quad-port BRI with echo can
|
||||
* Digium B434: PCI quad-port BRI with echo can
|
||||
|
||||
|
||||
Analog Cards
|
||||
~~~~~~~~~~~~
|
||||
- wcaxx:
|
||||
* Digium A8A: PCI up to 8 mixed FXS/FXO ports
|
||||
* Digium A8B: PCI express up to 8 mixed FXS/FXO ports
|
||||
* Digium A4A: PCI up to 4 mixed FXS/FXO ports
|
||||
* Digium A4B: PCI express up to 4 mixed FXS/FXO ports
|
||||
- wctdm24xxp:
|
||||
* Digium TDM2400P/AEX2400: up to 24 analog ports
|
||||
* Digium TDM800P/AEX800: up to 8 analog ports
|
||||
* Digium TDM410P/AEX410: up to 4 analog ports
|
||||
* Digium Hx8 Series: Up to 8 analog or BRI ports
|
||||
- wctdm:
|
||||
* Digium TDM400P: up to 4 analog ports
|
||||
- xpp: Xorcom Astribank: a USB connected unit of up to 32 ports
|
||||
(including the digital BRI and E1/T1 modules)
|
||||
- wcfxo: X100P, similar and clones. A simple single-port FXO card
|
||||
|
||||
|
||||
Other Drivers
|
||||
~~~~~~~~~~~~~
|
||||
- pciradio: Zapata Telephony PCI Quad Radio Interface
|
||||
- wctc4xxp: Digium hardware transcoder cards (also need dahdi_transcode)
|
||||
- dahdi_dynamic_eth: TDM over Ethernet (TDMoE) driver. Requires dahdi_dynamic
|
||||
- dahdi_dynamic_loc: Mirror a local span. Requires dahdi_dynamic
|
||||
@@ -181,204 +184,6 @@ you a clue of the versions installed:
|
||||
find /lib/modules -name dahdi.ko
|
||||
|
||||
|
||||
Installing the B410P drivers with mISDN
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
DAHDI includes the wcb4xxp driver for the B410P, however, support for the
|
||||
B410P was historically provided by mISDN. If you would like to use the mISDN
|
||||
driver with the B410P, please comment out the wcb4xxp line in /etc/dahdi/modules.
|
||||
This will prevent DAHDI from loading wcb4xxp which will conflict with the mISDN
|
||||
driver.
|
||||
|
||||
To install the mISDN driver for the B410P, please see http://www.misdn.org for
|
||||
more information, but the following sequence of steps is roughly equivalent to
|
||||
'make b410p' from previous releases.
|
||||
|
||||
wget http://www.misdn.org/downloads/releases/mISDN-1_1_8.tar.gz
|
||||
wget http://www.misdn.org/downloads/releases/mISDNuser-1_1_8.tar.gz
|
||||
tar xfz mISDN-1_1_8.tar.gz
|
||||
tar xfz mISDNuser-1_1_8.tar.gz
|
||||
pushd mISDN-1_1_8
|
||||
make install
|
||||
popd
|
||||
pushd mISDNuser-1_1_8
|
||||
make install
|
||||
popd
|
||||
/usr/sbin/misdn-init config
|
||||
|
||||
You will then also want to make sure /etc/init.d/misdn-init is started
|
||||
automatically with either 'chkconfig --add misdn-init' or 'update-rc.d
|
||||
misdn-init defaults 15 30' depending on your distribution.
|
||||
|
||||
NOTE: At the time this was written, misdn-1.1.8 is not compatible the
|
||||
2.6.25 kernel. Please use a kernel version 2.6.25 or earlier.
|
||||
|
||||
|
||||
OSLEC
|
||||
~~~~~
|
||||
http://www.rowetel.com/ucasterisk/oslec.html[OSLEC] is an
|
||||
Open Source Line Echo Canceller. It is currently in the staging subtree
|
||||
of the mainline kernel and will hopefully be fully merged at around
|
||||
version 2.6.29. The echo canceller module dahdi_echocan_oslec
|
||||
provides a DAHDI echo canceller module that uses the code from OSLEC. As
|
||||
OSLEC has not been accepted into mainline yet, its interface is not set
|
||||
in stone and thus this driver may need to change. Thus it is not
|
||||
built by default.
|
||||
|
||||
Luckily the structure of the dahdi-linux tree matches that of the kernel
|
||||
tree. Hence you can basically copy drivers/staging/echo and place it
|
||||
under driver/staging/echo . In fact, dahdi_echocan_oslec assumes that
|
||||
this is where the oslec code lies. If it is elsewhere you'll need to fix
|
||||
the #include line.
|
||||
|
||||
Thus for the moment, the simplest way to build OSLEC with dahdi is to
|
||||
copy the directory `drivers/staging/echo` from a recent kernel tree (at
|
||||
least 2.6.28-rc1) to the a subdirectory with the same name in the
|
||||
dahdi-linux tree.
|
||||
|
||||
After doing that, you'll see the following when building (running
|
||||
'make')
|
||||
|
||||
...
|
||||
CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/dahdi_echocan_oslec.o
|
||||
CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/../staging/echo/echo.o
|
||||
...
|
||||
|
||||
As this is an experimental driver, problems building and using it should
|
||||
be reported on the
|
||||
https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing
|
||||
list].
|
||||
|
||||
Alternatively you can also get the OSLEC code from the dahdi-linux-extra
|
||||
GIT repository:
|
||||
|
||||
git clone git://gitorious.org/dahdi-extra/dahdi-linux-extra.git
|
||||
cd dahdi-linux-extra
|
||||
git archive extra-2.6 drivers/staging | (cd ..; tar xf -)
|
||||
cd ..; rm -rf dahdi-linux-extra
|
||||
|
||||
|
||||
Live Install
|
||||
~~~~~~~~~~~~
|
||||
In many cases you already have DAHDI installed on your system but would
|
||||
like to try a different version. E.g. in order to check if the latest
|
||||
version fixes a bug that your current system happens to have.
|
||||
|
||||
DAHDI-linux includes a script to automate the task of installing DAHDI
|
||||
to a subtree and using it instead of the system copy. Module loading
|
||||
through modprobe cannot be used. Thus the script pre-loads the required
|
||||
modules with insmod (which requires some quesswork as for which modules
|
||||
to load). It also sets PATH and other environment variables to make all
|
||||
the commands do the right thing.
|
||||
|
||||
There is an extra mode of operation to copy all the required files to a
|
||||
remote host and run things there, for those who don't like to test code
|
||||
on thir build system.
|
||||
|
||||
Live Install: The Basics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Basic operation is through running
|
||||
|
||||
./build_tools/live_dahdi
|
||||
|
||||
from the root directory of the dahdi-linux tree. Using DAHDI requires
|
||||
dahdi-tools as well, and the script builds and installs dahdi-tools. By
|
||||
default it assumes the tree of dahdi-tools is in the directory
|
||||
'dahdi-tools' alongside the dahdi-linux tree. If you want to checkout
|
||||
the trunks from SVN, use:
|
||||
|
||||
svn checkout http://svn.asterisk.org/svn/dahdi/linux/trunk dahdi-linux
|
||||
svn checkout http://svn.asterisk.org/svn/dahdi/tools/trunk dahdi-tools
|
||||
cd dahdi-linux
|
||||
|
||||
If the tools directory resides elsewhere, you'll need to edit
|
||||
live/live.conf (see later on). The usage message of live_dahdi:
|
||||
|
||||
Usage: equivalent of:
|
||||
live_dahdi configure ./configure
|
||||
live_dahdi install make install
|
||||
live_dahdi config make config
|
||||
live_dahdi unload /etc/init.d/dahdi stop
|
||||
live_dahdi load /etc/init.d/dahdi start
|
||||
live_dahdi reload /etc/init.d/dahdi restart
|
||||
live_dahdi xpp-firm (Reset and load xpp firmware)
|
||||
live_dahdi rsync TARGET (copy filea to /tmp/live in host TARGET)
|
||||
live_dahdi exec COMMAND (Run COMMAND in 'live' environment)
|
||||
|
||||
Normally you should run:
|
||||
|
||||
./build_tools/live_dahdi configure
|
||||
./build_tools/live_dahdi install
|
||||
./build_tools/live_dahdi config
|
||||
|
||||
to build and install everything. Up until now no real change was done.
|
||||
This could actually be run by a non-root user. All files are installed
|
||||
under the subdirectory live/ .
|
||||
|
||||
Reloading the modules (and restarting Asterisk) is done by:
|
||||
|
||||
./build_tools/live_dahdi reload
|
||||
|
||||
Note: this stops Asterisk, unloads the DAHDI modules, loads the DAHDI
|
||||
modules from the live/ subdirectory, configures the system and re-starts
|
||||
Asterisk. This *can* do damage to your system. Furthermore, the DAHDI
|
||||
configuration is generated by dahdi_genconf. It can be influenced by
|
||||
a genconf_parameters file. But it may or may not be what you want.
|
||||
|
||||
If you want to run a command in the environment of the live system, use
|
||||
the command 'exec':
|
||||
|
||||
./build_tools/live_dahdi lsdahdi
|
||||
./build_tools/live_dahdi dahdi_hardware -v
|
||||
|
||||
Note however:
|
||||
|
||||
./build_tools/live_dahdi dahdi_cfg -c live/etc/dahdi/system.conf
|
||||
|
||||
Live Install Remote
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
As mentioned above, live_dahdi can also copy all the live system files
|
||||
to a remote system and run from there. This requires rsync installed on
|
||||
both system and assumes you can connect to the remove system through
|
||||
ssh.
|
||||
|
||||
tzafrir@hilbert $ ./build_tools/live_dahdi rsync root@david
|
||||
root@david's password:
|
||||
<f+++++++++ live_dahdi
|
||||
cd+++++++++ live/
|
||||
<f+++++++++ live/live.conf
|
||||
cd+++++++++ live/dev/
|
||||
cd+++++++++ live/dev/dahdi/
|
||||
cd+++++++++ live/etc/
|
||||
cd+++++++++ live/etc/asterisk/
|
||||
cd+++++++++ live/etc/dahdi/
|
||||
<f+++++++++ live/etc/dahdi/genconf_parameters
|
||||
<f+++++++++ live/etc/dahdi/init.conf
|
||||
...
|
||||
|
||||
As you can see, it copies the script itselfand the whole live/
|
||||
subdirectory. The target directory is /tmp/live on the target directory
|
||||
(changing it should probably be simple, but I never needed that).
|
||||
|
||||
Then, on the remove computer:
|
||||
|
||||
root@david:/tmp# ./live_dahdi reload
|
||||
|
||||
|
||||
Configuring a Live Install
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
The live_dahdi script reads a configuration file in 'live/live.conf' if
|
||||
it exists. This file has the format of a shell script snippet:
|
||||
|
||||
var1=value # a '#' sign begins a comment
|
||||
var2='value'
|
||||
|
||||
# comments and empty lines are ignored
|
||||
var3="value"
|
||||
|
||||
The variables below can also be overriden from the environment:
|
||||
|
||||
var1='value' ./build_tools/live_dahdi
|
||||
|
||||
===== LINUX_DIR
|
||||
The relative path to the dahdi-linux tree. The default is '.' and normally
|
||||
there's no reason to override it.
|
||||
@@ -1441,7 +1246,5 @@ http://issues.asterisk.org in the "DAHDI-linux" category.
|
||||
Links
|
||||
-----
|
||||
- http://asterisk.org/[] - The Asterisk PBX
|
||||
- http://voip-info.org/[]
|
||||
- http://voip-info.org/wiki/view/DAHDI[]
|
||||
- http://docs.tzafrir.org.il/dahdi-linux/README.html[Up-to-date HTML version
|
||||
of this file]
|
||||
|
||||
@@ -2,119 +2,18 @@
|
||||
|
||||
if [ -f ${1}/.version ]; then
|
||||
cat ${1}/.version
|
||||
elif [ -f ${1}/.svnrevision ]; then
|
||||
echo SVN-`cat ${1}/.svnbranch`-r`cat ${1}/.svnrevision`
|
||||
elif [ -d ${1}/.svn ]; then
|
||||
PARTS=`LANG=C svn info ${1} | grep URL | awk '{print $2;}' | sed -e s:^.*/svn/${2}/:: | sed -e 's:/: :g'`
|
||||
BRANCH=0
|
||||
TEAM=0
|
||||
|
||||
REV=`svnversion -c ${1} | cut -d: -f2`
|
||||
|
||||
if [ "${PARTS}" = "trunk" ]
|
||||
then
|
||||
echo SVN-'trunk'-r${REV}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for PART in $PARTS
|
||||
do
|
||||
if [ ${BRANCH} != 0 ]
|
||||
then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
break
|
||||
fi
|
||||
|
||||
if [ ${TEAM} != 0 ]
|
||||
then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "branches" ]
|
||||
then
|
||||
BRANCH=1
|
||||
RESULT="branch"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "tags" ]
|
||||
then
|
||||
BRANCH=1
|
||||
RESULT="tag"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "team" ]
|
||||
then
|
||||
TEAM=1
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
echo SVN-${RESULT##-}-r${REV}
|
||||
elif [ -d ${1}/.git ]; then
|
||||
# If the first log commit messages indicates that this is checked into
|
||||
# subversion, we'll just use the SVN- form of the revision.
|
||||
MODIFIED=""
|
||||
SVN_REV=`git log --pretty=full -1 | grep -F "git-svn-id:" | sed -e "s/.*\@\([^\s]*\)\s.*/\1/g"`
|
||||
if [ -z "$SVN_REV" ]; then
|
||||
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
|
||||
if [ $? -ne 0 ]; then
|
||||
if [ "`git ls-files -m | wc -l`" != "0" ]; then
|
||||
MODIFIED="M"
|
||||
fi
|
||||
# Some older versions of git do not support all the above
|
||||
# options.
|
||||
VERSION=GIT-`git rev-parse --short --verify HEAD`${MODIFIED}
|
||||
fi
|
||||
echo ${VERSION}
|
||||
else
|
||||
PARTS=`LANG=C git log --pretty=full | grep -F "git-svn-id:" | head -1 | awk '{print $2;}' | sed -e s:^.*/svn/$2/:: | sed -e 's:/: :g' | sed -e 's/@.*$//g'`
|
||||
BRANCH=0
|
||||
TEAM=0
|
||||
|
||||
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
|
||||
if [ $? -ne 0 ]; then
|
||||
MODIFIED=""
|
||||
if [ "`git ls-files -m | wc -l`" != "0" ]; then
|
||||
MODIFIED="M"
|
||||
fi
|
||||
|
||||
if [ "${PARTS}" = "trunk" ]; then
|
||||
echo SVN-'trunk'-r${SVN_REV}${MODIFIED}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for PART in $PARTS
|
||||
do
|
||||
if [ ${BRANCH} != 0 ]; then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
break
|
||||
fi
|
||||
|
||||
if [ ${TEAM} != 0 ]; then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "branches" ]; then
|
||||
BRANCH=1
|
||||
RESULT="branch"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "tags" ]; then
|
||||
BRANCH=1
|
||||
RESULT="tag"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "team" ]; then
|
||||
TEAM=1
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
echo SVN-${RESULT##-}-r${SVN_REV}${MODIFIED}
|
||||
# Some older versions of git do not support all the above
|
||||
# options.
|
||||
VERSION=GIT-`git rev-parse --short --verify HEAD`${MODIFIED}
|
||||
fi
|
||||
echo ${VERSION}
|
||||
else
|
||||
# Use the directory information in the absence of any other version
|
||||
# information
|
||||
|
||||
72
dahdi-modules
Executable file
72
dahdi-modules
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
|
||||
MODULES="dahdi"
|
||||
DAHDI_MODULES_FILE="/etc/dahdi/modules"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0: loads / unloads DAHDI kernel modules
|
||||
|
||||
Usage: $0 <load|unload>
|
||||
|
||||
* load: Loads all modules listed in /etc/dahdi/modules (one per line)
|
||||
* unload: Unloads the DAHDI modules (all the modules that are dependencies
|
||||
of $MODULES).
|
||||
EOF
|
||||
}
|
||||
|
||||
# recursively unload a module and its dependencies, if possible.
|
||||
# where's modprobe -r when you need it?
|
||||
# inputs: module to unload.
|
||||
# returns: the result from
|
||||
unload_module() {
|
||||
module="$1"
|
||||
line=`lsmod 2>/dev/null | grep "^$1 "`
|
||||
if [ "$line" = '' ]; then return; fi # module was not loaded
|
||||
|
||||
set -- $line
|
||||
# $1: the original module, $2: size, $3: refcount, $4: deps list
|
||||
mods=`echo $4 | tr , ' '`
|
||||
ec_modules=""
|
||||
# xpp_usb keeps the xpds below busy if an xpp hardware is
|
||||
# connected. Hence must be removed before them:
|
||||
case "$module" in xpd_*) mods="xpp_usb $mods";; esac
|
||||
|
||||
for mod in $mods; do
|
||||
case "$mod" in
|
||||
dahdi_echocan_*)
|
||||
ec_modules="$mod $ec_modules"
|
||||
;;
|
||||
*)
|
||||
# run in a subshell, so it won't step over our vars:
|
||||
(unload_module $mod)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# Now that all the other dependencies are unloaded, we can unload the
|
||||
# dahdi_echocan modules. The drivers that register spans may keep
|
||||
# references on the echocan modules before they are unloaded.
|
||||
for mod in $ec_modules; do
|
||||
(unload_module $mod)
|
||||
done
|
||||
rmmod $module
|
||||
}
|
||||
|
||||
unload_modules() {
|
||||
for module in "$@"; do
|
||||
unload_module $module
|
||||
done
|
||||
}
|
||||
|
||||
load_modules() {
|
||||
modules=`sed -e 's/#.*$//' $DAHDI_MODULES_FILE 2>/dev/null`
|
||||
for line in $modules; do
|
||||
modprobe $line
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
load) load_modules "$@";;
|
||||
unload) unload_modules $MODULES;;
|
||||
*) usage;;
|
||||
esac
|
||||
@@ -11,7 +11,6 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) += oct612x/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
|
||||
|
||||
wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o
|
||||
@@ -36,16 +35,10 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
CFLAGS_wcaxx-base.o += -DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/
|
||||
@@ -66,7 +59,7 @@ obj-m += dahdi_echocan_oslec.o
|
||||
obj-m += ../staging/echo/echo.o
|
||||
endif
|
||||
|
||||
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src)
|
||||
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src) -Wno-format-truncation
|
||||
|
||||
ifndef HOTPLUG_FIRMWARE
|
||||
ifneq (,$(filter y m,$(CONFIG_FW_LOADER)))
|
||||
@@ -158,15 +151,9 @@ ifeq ($(HPEC_PRESENT),yes)
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_HPEC) += dahdi_echocan_hpec.o
|
||||
endif
|
||||
|
||||
$(obj)/pciradio.o: $(obj)/radfw.h
|
||||
$(obj)/tor2.o: $(obj)/tor2fw.h
|
||||
|
||||
hostprogs-y := makefw
|
||||
|
||||
$(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw
|
||||
$(obj)/makefw $< tor2fw > $@
|
||||
|
||||
$(obj)/radfw.h: $(src)/pciradio.rbt $(obj)/makefw
|
||||
$(obj)/makefw $< radfw > $@
|
||||
|
||||
clean-files := radfw.h tor2fw.h
|
||||
clean-files := radfw.h
|
||||
|
||||
@@ -69,18 +69,6 @@ config DAHDI_ECHOCAN_HPEC
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_WCTDM
|
||||
tristate "Digium Wildcard TDM400P Support"
|
||||
depends on DAHDI && PCI
|
||||
default DAHDI
|
||||
---help---
|
||||
This driver provides support for the Digium Wildcard TDM400P.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wctdm.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_WCT4XXP
|
||||
tristate "Digium Wildcard dual- and quad-T1/E1/J1 Support"
|
||||
depends on DAHDI && PCI
|
||||
@@ -158,23 +146,6 @@ config DAHDI_WCTDM24XXP
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_WCTE12XP
|
||||
tristate "Digium Wildcard VoiceBus digital card Support"
|
||||
depends on DAHDI && DAHDI_VOICEBUS
|
||||
default DAHDI
|
||||
---help---
|
||||
This driver provides support for the following Digium
|
||||
Wildcard products:
|
||||
|
||||
* TE120P (PCI/PCI-X)
|
||||
* TE121 (PCI/PCI-X)
|
||||
* TE122 (PCI-E)
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wcte12xp.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_PCIRADIO
|
||||
tristate "PCI Radio Support"
|
||||
depends on DAHDI && PCI
|
||||
@@ -251,44 +222,5 @@ config DAHDI_DYNAMIC_LOC
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_TOR2
|
||||
tristate "Tormenta2 quad-port T1/E1 Support"
|
||||
depends on DAHDI && PCI
|
||||
default DAHDI
|
||||
---help---
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called tor2.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_WCFXO
|
||||
tristate "Digium Wildcard X100P Support"
|
||||
depends on DAHDI && PCI
|
||||
default DAHDI
|
||||
---help---
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wcfxo.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_WCT1XXP
|
||||
tristate "Digium Wildcard T100P Support"
|
||||
depends on DAHDI && PCI
|
||||
default DAHDI
|
||||
---help---
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wct1xxp.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config DAHDI_WCTE11XP
|
||||
tristate "Digium Wildcard TE110P Support"
|
||||
depends on DAHDI && PCI
|
||||
default DAHDI
|
||||
---help---
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wcte11xp.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
source "drivers/dahdi/xpp/Kconfig"
|
||||
|
||||
@@ -66,6 +66,11 @@
|
||||
/* Grab fasthdlc with tables */
|
||||
#define FAST_HDLC_NEED_TABLES
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
#include "ecdis.h"
|
||||
#include "dahdi.h"
|
||||
|
||||
@@ -2409,6 +2414,9 @@ static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf,
|
||||
if (unlikely(count < 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)))
|
||||
return -ENODEV;
|
||||
|
||||
for (;;) {
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (chan->eventinidx != chan->eventoutidx) {
|
||||
@@ -2526,6 +2534,9 @@ static ssize_t dahdi_chan_write(struct file *file, const char __user *usrbuf,
|
||||
if (unlikely(count < 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)))
|
||||
return -ENODEV;
|
||||
|
||||
for (;;) {
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if ((chan->curtone || chan->pdialcount) && !is_pseudo_chan(chan)) {
|
||||
@@ -5698,9 +5709,9 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
|
||||
}
|
||||
/* if changing confs, clear last added info */
|
||||
if (conf.confno != chan->confna) {
|
||||
memset(chan->conflast, 0, DAHDI_MAX_CHUNKSIZE);
|
||||
memset(chan->conflast1, 0, DAHDI_MAX_CHUNKSIZE);
|
||||
memset(chan->conflast2, 0, DAHDI_MAX_CHUNKSIZE);
|
||||
memset(chan->conflast, 0, sizeof(chan->conflast));
|
||||
memset(chan->conflast1, 0, sizeof(chan->conflast1));
|
||||
memset(chan->conflast2, 0, sizeof(chan->conflast2));
|
||||
}
|
||||
oldconf = chan->confna; /* save old conference number */
|
||||
chan->confna = conf.confno; /* set conference number */
|
||||
@@ -10058,7 +10069,7 @@ static inline unsigned long msecs_processed(const struct core_timer *const ct)
|
||||
return atomic_read(&ct->count) * DAHDI_MSECS_PER_CHUNK;
|
||||
}
|
||||
|
||||
static void coretimer_func(unsigned long param)
|
||||
static void coretimer_func(TIMER_DATA_TYPE unused)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long ms_since_start;
|
||||
@@ -10139,16 +10150,14 @@ static void coretimer_func(unsigned long param)
|
||||
|
||||
static void coretimer_init(void)
|
||||
{
|
||||
init_timer(&core_timer.timer);
|
||||
core_timer.timer.function = coretimer_func;
|
||||
timer_setup(&core_timer.timer, coretimer_func, 0);
|
||||
ktime_get_ts(&core_timer.start_interval);
|
||||
atomic_set(&core_timer.count, 0);
|
||||
atomic_set(&core_timer.shutdown, 0);
|
||||
core_timer.interval = max(msecs_to_jiffies(DAHDI_MSECS_PER_CHUNK), 1UL);
|
||||
if (core_timer.interval < (HZ/250))
|
||||
core_timer.interval = (HZ/250);
|
||||
core_timer.timer.expires = jiffies + core_timer.interval;
|
||||
add_timer(&core_timer.timer);
|
||||
mod_timer(&core_timer.timer, jiffies + core_timer.interval);
|
||||
}
|
||||
|
||||
static void coretimer_cleanup(void)
|
||||
@@ -10444,7 +10453,7 @@ static const struct file_operations dahdi_chan_fops = {
|
||||
#ifdef CONFIG_DAHDI_WATCHDOG
|
||||
static struct timer_list watchdogtimer;
|
||||
|
||||
static void watchdog_check(unsigned long ignored)
|
||||
static void watchdog_check(TIMER_DATA_TYPE ignored)
|
||||
{
|
||||
unsigned long flags;
|
||||
static int wdcheck=0;
|
||||
@@ -10485,10 +10494,7 @@ static void watchdog_check(unsigned long ignored)
|
||||
|
||||
static int __init watchdog_init(void)
|
||||
{
|
||||
init_timer(&watchdogtimer);
|
||||
watchdogtimer.expires = 0;
|
||||
watchdogtimer.data =0;
|
||||
watchdogtimer.function = watchdog_check;
|
||||
timer_setup(&watchdogtimer, watchdog_check, 0);
|
||||
/* Run every couple of jiffy or so */
|
||||
mod_timer(&watchdogtimer, jiffies + 2);
|
||||
return 0;
|
||||
|
||||
@@ -158,6 +158,7 @@ static BUS_ATTR_READER(ec_state_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute chan_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(channo),
|
||||
@@ -174,6 +175,39 @@ static struct device_attribute chan_dev_attrs[] = {
|
||||
__ATTR_RO(in_use),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(name);
|
||||
static DEVICE_ATTR_RO(channo);
|
||||
static DEVICE_ATTR_RO(chanpos);
|
||||
static DEVICE_ATTR_RO(sig);
|
||||
static DEVICE_ATTR_RO(sigcap);
|
||||
static DEVICE_ATTR_RO(alarms);
|
||||
static DEVICE_ATTR_RO(ec_factory);
|
||||
static DEVICE_ATTR_RO(ec_state);
|
||||
static DEVICE_ATTR_RO(blocksize);
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
static DEVICE_ATTR_RO(chanmute);
|
||||
#endif
|
||||
static DEVICE_ATTR_RO(in_use);
|
||||
|
||||
static struct attribute *chan_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_channo.attr,
|
||||
&dev_attr_chanpos.attr,
|
||||
&dev_attr_sig.attr,
|
||||
&dev_attr_sigcap.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_ec_factory.attr,
|
||||
&dev_attr_ec_state.attr,
|
||||
&dev_attr_blocksize.attr,
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
&dev_attr_chanmute.attr,
|
||||
#endif
|
||||
&dev_attr_in_use.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(chan_dev);
|
||||
#endif
|
||||
|
||||
static void chan_release(struct device *dev)
|
||||
{
|
||||
@@ -196,7 +230,11 @@ static int chan_match(struct device *dev, struct device_driver *driver)
|
||||
static struct bus_type chan_bus_type = {
|
||||
.name = "dahdi_channels",
|
||||
.match = chan_match,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = chan_dev_attrs,
|
||||
#else
|
||||
.dev_groups = chan_dev_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int chan_probe(struct device *dev)
|
||||
|
||||
@@ -214,6 +214,7 @@ static BUS_ATTR_READER(linecompat_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute span_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(desc),
|
||||
@@ -230,6 +231,39 @@ static struct device_attribute span_dev_attrs[] = {
|
||||
__ATTR_RO(linecompat),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(name);
|
||||
static DEVICE_ATTR_RO(desc);
|
||||
static DEVICE_ATTR_RO(spantype);
|
||||
static DEVICE_ATTR_RO(local_spanno);
|
||||
static DEVICE_ATTR_RO(alarms);
|
||||
static DEVICE_ATTR_RO(lbo);
|
||||
static DEVICE_ATTR_RO(syncsrc);
|
||||
static DEVICE_ATTR_RO(is_digital);
|
||||
static DEVICE_ATTR_RO(is_sync_master);
|
||||
static DEVICE_ATTR_RO(basechan);
|
||||
static DEVICE_ATTR_RO(channels);
|
||||
static DEVICE_ATTR_RO(lineconfig);
|
||||
static DEVICE_ATTR_RO(linecompat);
|
||||
|
||||
static struct attribute *span_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_desc.attr,
|
||||
&dev_attr_spantype.attr,
|
||||
&dev_attr_local_spanno.attr,
|
||||
&dev_attr_lbo.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_syncsrc.attr,
|
||||
&dev_attr_is_digital.attr,
|
||||
&dev_attr_is_sync_master.attr,
|
||||
&dev_attr_basechan.attr,
|
||||
&dev_attr_channels.attr,
|
||||
&dev_attr_lineconfig.attr,
|
||||
&dev_attr_linecompat.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(span_dev);
|
||||
#endif
|
||||
|
||||
static ssize_t master_span_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
@@ -270,7 +304,11 @@ static struct bus_type spans_bus_type = {
|
||||
.name = "dahdi_spans",
|
||||
.match = span_match,
|
||||
.uevent = span_uevent,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = span_dev_attrs,
|
||||
#else
|
||||
.dev_groups = span_dev_groups,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
.drv_attrs = dahdi_attrs,
|
||||
#else
|
||||
@@ -482,7 +520,7 @@ static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_manufacturer_show(struct device *dev,
|
||||
manufacturer_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -490,7 +528,7 @@ dahdi_device_manufacturer_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_type_show(struct device *dev,
|
||||
type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -498,7 +536,7 @@ dahdi_device_type_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_span_count_show(struct device *dev,
|
||||
span_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -512,7 +550,7 @@ dahdi_device_span_count_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_hardware_id_show(struct device *dev,
|
||||
hardware_id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -522,7 +560,7 @@ dahdi_device_hardware_id_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_location_show(struct device *dev,
|
||||
location_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -532,7 +570,7 @@ dahdi_device_location_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
|
||||
auto_assign_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -541,7 +579,7 @@ dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
|
||||
assign_span_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -576,7 +614,7 @@ dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
|
||||
unassign_span_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -690,25 +728,56 @@ dahdi_registration_time_show(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute dahdi_device_attrs[] = {
|
||||
__ATTR(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
|
||||
__ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
|
||||
__ATTR(span_count, S_IRUGO, dahdi_device_span_count_show, NULL),
|
||||
__ATTR(hardware_id, S_IRUGO, dahdi_device_hardware_id_show, NULL),
|
||||
__ATTR(location, S_IRUGO, dahdi_device_location_show, NULL),
|
||||
__ATTR(auto_assign, S_IWUSR, NULL, dahdi_device_auto_assign),
|
||||
__ATTR(assign_span, S_IWUSR, NULL, dahdi_device_assign_span),
|
||||
__ATTR(unassign_span, S_IWUSR, NULL, dahdi_device_unassign_span),
|
||||
__ATTR(manufacturer, S_IRUGO, manufacturer_show, NULL),
|
||||
__ATTR(type, S_IRUGO, type_show, NULL),
|
||||
__ATTR(span_count, S_IRUGO, span_count_show, NULL),
|
||||
__ATTR(hardware_id, S_IRUGO, hardware_id_show, NULL),
|
||||
__ATTR(location, S_IRUGO, location_show, NULL),
|
||||
__ATTR(auto_assign, S_IWUSR, NULL, auto_assign_store),
|
||||
__ATTR(assign_span, S_IWUSR, NULL, assign_span_store),
|
||||
__ATTR(unassign_span, S_IWUSR, NULL, unassign_span_store),
|
||||
__ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
|
||||
dahdi_spantype_store),
|
||||
__ATTR(registration_time, S_IRUGO, dahdi_registration_time_show, NULL),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(manufacturer);
|
||||
static DEVICE_ATTR_RO(type);
|
||||
static DEVICE_ATTR_RO(span_count);
|
||||
static DEVICE_ATTR_RO(hardware_id);
|
||||
static DEVICE_ATTR_RO(location);
|
||||
static DEVICE_ATTR_WO(auto_assign);
|
||||
static DEVICE_ATTR_WO(assign_span);
|
||||
static DEVICE_ATTR_WO(unassign_span);
|
||||
static DEVICE_ATTR_RW(dahdi_spantype);
|
||||
static DEVICE_ATTR_RO(dahdi_registration_time);
|
||||
static struct attribute *dahdi_device_attrs[] = {
|
||||
&dev_attr_manufacturer.attr,
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_span_count.attr,
|
||||
&dev_attr_hardware_id.attr,
|
||||
&dev_attr_location.attr,
|
||||
&dev_attr_auto_assign.attr,
|
||||
&dev_attr_assign_span.attr,
|
||||
&dev_attr_unassign_span.attr,
|
||||
&dev_attr_dahdi_spantype.attr,
|
||||
&dev_attr_dahdi_registration_time.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(dahdi_device);
|
||||
#endif
|
||||
|
||||
static struct bus_type dahdi_device_bus = {
|
||||
.name = "dahdi_devices",
|
||||
.uevent = device_uevent,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = dahdi_device_attrs,
|
||||
#else
|
||||
.dev_groups = dahdi_device_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void dahdi_sysfs_cleanup(void)
|
||||
|
||||
@@ -157,7 +157,7 @@ static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1)
|
||||
return ms;
|
||||
}
|
||||
|
||||
static void dahdi_dummy_timer(unsigned long param)
|
||||
static void dahdi_dummy_timer(struct timer_timer *unused)
|
||||
{
|
||||
unsigned long ms_since_start;
|
||||
struct timespec now;
|
||||
@@ -258,12 +258,10 @@ int init_module(void)
|
||||
hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL);
|
||||
printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n");
|
||||
#else
|
||||
init_timer(&timer);
|
||||
timer.function = dahdi_dummy_timer;
|
||||
timer_setup(&timer, dahdi_dummy_timer);
|
||||
ztd->start_interval = current_kernel_time();
|
||||
timer.expires = jiffies + JIFFIES_INTERVAL;
|
||||
atomic_set(&shutdown, 0);
|
||||
add_timer(&timer);
|
||||
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
|
||||
#endif
|
||||
|
||||
if (debug)
|
||||
|
||||
@@ -467,7 +467,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
|
||||
|
||||
/* We shouldn't have more than the two references at this point. If
|
||||
* we do, there are probably channels that are still opened. */
|
||||
if (atomic_read(&d->kref.refcount) > 2) {
|
||||
if (refcount_read(&d->kref.refcount) > 2) {
|
||||
dynamic_put(d);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -638,8 +638,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_NOTOPEN;
|
||||
d->span.ops = &dynamic_ops;
|
||||
for (x = 0; x < d->span.channels; x++) {
|
||||
sprintf(d->chans[x]->name, "DYN/%s/%s/%d",
|
||||
dds->driver, dds->addr, x+1);
|
||||
snprintf(d->chans[x]->name, sizeof(d->chans[x]->name),
|
||||
"DYN/%s/%s/%d", dds->driver, dds->addr, x+1);
|
||||
d->chans[x]->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR |
|
||||
DAHDI_SIG_FXSLS | DAHDI_SIG_FXSKS |
|
||||
DAHDI_SIG_FXSGS | DAHDI_SIG_FXOLS |
|
||||
@@ -831,7 +831,7 @@ EXPORT_SYMBOL(dahdi_dynamic_unregister_driver);
|
||||
|
||||
static struct timer_list alarmcheck;
|
||||
|
||||
static void check_for_red_alarm(unsigned long ignored)
|
||||
static void check_for_red_alarm(TIMER_DATA_TYPE unused)
|
||||
{
|
||||
int newalarm;
|
||||
int alarmchanged = 0;
|
||||
@@ -867,10 +867,7 @@ static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
|
||||
static int dahdi_dynamic_init(void)
|
||||
{
|
||||
/* Start process to check for RED ALARM */
|
||||
init_timer(&alarmcheck);
|
||||
alarmcheck.expires = 0;
|
||||
alarmcheck.data = 0;
|
||||
alarmcheck.function = check_for_red_alarm;
|
||||
timer_setup(&alarmcheck, check_for_red_alarm, 0);
|
||||
/* Check once per second */
|
||||
mod_timer(&alarmcheck, jiffies + 1 * HZ);
|
||||
#ifdef ENABLE_TASKLETS
|
||||
|
||||
@@ -681,16 +681,13 @@ static int ethmf_delay_dec(void)
|
||||
* Timer callback function to allow all spans to be added, prior to any of
|
||||
* them being used.
|
||||
*/
|
||||
static void timer_callback(unsigned long param)
|
||||
static void timer_callback(TIMER_DATA_TYPE unused)
|
||||
{
|
||||
if (ethmf_delay_dec()) {
|
||||
if (!atomic_read(&timer_deleted)) {
|
||||
timer.expires = jiffies + HZ;
|
||||
add_timer(&timer);
|
||||
}
|
||||
if (!atomic_read(&timer_deleted))
|
||||
mod_timer(&timer, jiffies + HZ);
|
||||
} else {
|
||||
printk(KERN_INFO "All TDMoE multiframe span groups are active.\n");
|
||||
del_timer(&timer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,11 +761,8 @@ static const struct file_operations ztdethmf_proc_fops = {
|
||||
|
||||
static int __init ztdethmf_init(void)
|
||||
{
|
||||
init_timer(&timer);
|
||||
timer.expires = jiffies + HZ;
|
||||
timer.function = &timer_callback;
|
||||
if (!timer_pending(&timer))
|
||||
add_timer(&timer);
|
||||
timer_setup(&timer, timer_callback, 0);
|
||||
mod_timer(&timer, jiffies + HZ);
|
||||
|
||||
dev_add_pack(&ztdethmf_ptype);
|
||||
register_netdevice_notifier(&ztdethmf_nblock);
|
||||
|
||||
@@ -148,7 +148,7 @@ static void sppp_lcp_open (struct sppp *sp);
|
||||
static void sppp_ipcp_open (struct sppp *sp);
|
||||
static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
|
||||
int len, u32 *magic);
|
||||
static void sppp_cp_timeout (unsigned long arg);
|
||||
static void sppp_cp_timeout (TIMER_DATA_TYPE timer);
|
||||
static char *sppp_lcp_type_name (u8 type);
|
||||
static char *sppp_ipcp_type_name (u8 type);
|
||||
static void sppp_print_bytes (u8 *p, u16 len);
|
||||
@@ -189,12 +189,9 @@ static void sppp_set_timeout(struct sppp *p,int s)
|
||||
{
|
||||
if (! (p->pp_flags & PP_TIMO))
|
||||
{
|
||||
init_timer(&p->pp_timer);
|
||||
p->pp_timer.function=sppp_cp_timeout;
|
||||
p->pp_timer.expires=jiffies+s*HZ;
|
||||
p->pp_timer.data=(unsigned long)p;
|
||||
p->pp_flags |= PP_TIMO;
|
||||
add_timer(&p->pp_timer);
|
||||
timer_setup(&p->pp_timer, sppp_cp_timeout, 0);
|
||||
mod_timer(&p->pp_timer, jiffies + s*HZ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
* Tormenta 2 Quad-T1 PCI Driver
|
||||
*
|
||||
* Written by Mark Spencer <markster@linux-suppot.net>
|
||||
*
|
||||
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
|
||||
* Copyright (C) 2001-2008, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#ifndef _TOR2_HW_H
|
||||
#define _TOR2_HW_H
|
||||
|
||||
/*
|
||||
* The Tormenta two consists of the following block architecture:
|
||||
*
|
||||
* [ Spartan ] --- [ DS 21Q352 ] -- Xfrms -- Span 1
|
||||
* | | | | | | |
|
||||
* Local Bus +----- Span 2
|
||||
* | | | |
|
||||
* [ PCI 9030 ] +----- Span 3
|
||||
* | | | | | |
|
||||
* PCI BUS +----- Span 4
|
||||
*
|
||||
* All communicatiosn to the framer (21Q352) are performed
|
||||
* through the PCI 9030 part using memory mapped I/O.
|
||||
*
|
||||
* The Tormenta 2 requires a 2 2k wondows memory space
|
||||
* which is mapped as follows:
|
||||
*
|
||||
* First (32 bit) space:
|
||||
*
|
||||
* 0x0000 -> 0x07FF: Memory map of Tx and Rx buffers. They are stored
|
||||
* with increasing channel number, with each span in
|
||||
* a byte of a 32-bit long word:
|
||||
* Bits 31-24: Span 1
|
||||
* Bits 23-16: Span 2
|
||||
* Bits 16- 8: Span 3
|
||||
* Bits 7- 0: Span 4
|
||||
*
|
||||
*
|
||||
* Second (8 bit) space:
|
||||
*
|
||||
* 0x0000 -> 0x00FF: Registers for Transceiver 1
|
||||
* 0x0100 -> 0x01FF: Registers for Transceiver 2
|
||||
* 0x0200 -> 0x02FF: Registers for Transceiver 3
|
||||
* 0x0300 -> 0x03FF: Registers for Transceiver 4
|
||||
*
|
||||
* 0x400 Write -> Firmware load location for Xilinx. This is the only valid
|
||||
* register until the Xilinx is programmed to decode
|
||||
* the remainder!
|
||||
*
|
||||
* 0x400 Write -> clkreg (sync source)
|
||||
* 0=free run, 1=span 1, 2=span 2, 3=span 3, 4=span 4.
|
||||
*
|
||||
* 0x400 Read -> statreg
|
||||
* bit 0 - Interrupt Enabled
|
||||
* bit 1 - Interrupt Active
|
||||
* bit 2 - Dallas Interrupt Active
|
||||
*
|
||||
* 0x401 Write -> ctlreg as follows:
|
||||
* bit 0 - Interrupt Enable
|
||||
* bit 1 - Drives "TEST1" signal ("Interrupt" outbit)
|
||||
* bit 2 - Dallas Interrupt Enable (Allows DINT signal to drive INT)
|
||||
* bit 3 - External Syncronization Enable (MASTER signal).
|
||||
* bit 4 - Select E1 Divisor Mode (0 for T1, 1 for E1).
|
||||
* bit 5 - Remote serial loopback (When set to 1, TSER is driven from RSER)
|
||||
* bit 6 - Local serial loopback (When set to 1, Rx buffers are driven from Tx buffers)
|
||||
* bit 7 - Interrupt Acknowledge (set to 1 to acknowledge interrupt)
|
||||
*
|
||||
* 0x402 Write -> LED register as follows:
|
||||
* bit 0 - Span 1 Green
|
||||
* bit 1 - Span 1 Red
|
||||
* bit 2 - Span 2 Green
|
||||
* bit 3 - Span 2 Red
|
||||
* bit 4 - Span 3 Green
|
||||
* bit 5 - Span 3 Red
|
||||
* bit 6 - Span 4 Green
|
||||
* bit 7 - Span 4 Red
|
||||
* NOTE: turning on both red and green yields yellow.
|
||||
*
|
||||
* 0x403 Write -> TEST2, writing to bit 0 drives TEST2 pin.
|
||||
*
|
||||
* 0x404 Write -> ctlreg1 as follows:
|
||||
* bit 0 - Non-REV.A Mode (Set this bit for Dallas chips later then Rev. A)
|
||||
*/
|
||||
|
||||
#ifdef NEED_PCI_IDS
|
||||
/*
|
||||
* Provide routines for identifying a tormenta card
|
||||
*/
|
||||
|
||||
#define PCI_VENDOR_ID_PLX 0x10b5
|
||||
|
||||
#ifdef __KERNEL__
|
||||
static DEFINE_PCI_DEVICE_TABLE(tor2_pci_ids) =
|
||||
#else
|
||||
#define PCI_ANY_ID -1
|
||||
static struct tor2_pci_id {
|
||||
int vendor;
|
||||
int device;
|
||||
int subvendor;
|
||||
int subdevice;
|
||||
int class;
|
||||
int classmask;
|
||||
unsigned long driver_data;
|
||||
} tor2_pci_ids[] =
|
||||
#endif /* __KERNEL__ */
|
||||
{
|
||||
{ PCI_VENDOR_ID_PLX, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX 9030" }, /* PLX 9030 Development board */
|
||||
{ PCI_VENDOR_ID_PLX, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX Development Board" }, /* PLX 9030 Development board */
|
||||
{ PCI_VENDOR_ID_PLX, 0xD00D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/PRI or E1/PRA" }, /* Tormenta 2 */
|
||||
{ PCI_VENDOR_ID_PLX, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/E1 (non-Digium clone)" }, /* Tormenta 2 clone */
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* We provide a simple routine to match the given ID's */
|
||||
static inline int tor2_pci_match(int vendorid, int deviceid, char **variant)
|
||||
{
|
||||
/* Returns 1 if this is a tormenta card or 0 if it isn't */
|
||||
int x;
|
||||
for (x = 0; x< sizeof(tor2_pci_ids) / sizeof(tor2_pci_ids[0]); x++)
|
||||
if (((tor2_pci_ids[x].vendor == PCI_ANY_ID) ||
|
||||
(tor2_pci_ids[x].vendor == vendorid)) &&
|
||||
((tor2_pci_ids[x].device == PCI_ANY_ID) ||
|
||||
(tor2_pci_ids[x].device == deviceid))) {
|
||||
*variant = (char *)tor2_pci_ids[x].driver_data;
|
||||
return 1;
|
||||
}
|
||||
if (variant)
|
||||
*variant = NULL;
|
||||
return 0;
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* NEED_PCI_IDS */
|
||||
|
||||
/*
|
||||
* PLX PCI9030 PCI Configuration Registers
|
||||
*
|
||||
* This is not an all-inclusive list, just some interesting ones
|
||||
* that we need and that are not standard.
|
||||
*
|
||||
*/
|
||||
#define PLX_PCI_VPD_ADDR 0x4e /* Set address here */
|
||||
#define PLX_PCI_VPD_DATA 0x50 /* Read/Write data here */
|
||||
|
||||
#define PLX_LOC_WP_BOUNDARY 0x4e /* Bits 6-0 here */
|
||||
#define PLX_LOC_GPIOC 0x54 /* GPIO control register */
|
||||
|
||||
/* The 4 GPIO data bits we are interested in */
|
||||
|
||||
#define LOC_GPIOC_GPIO4 0x4000 /* GPIO4 data */
|
||||
#define LOC_GPIOC_GPIO5 0x20000 /* GPIO5 data */
|
||||
#define LOC_GPIOC_GPIO6 0x100000 /* GPIO6 data */
|
||||
#define LOC_GPIOC_GPIO7 0x800000 /* GPIO7 data */
|
||||
|
||||
/* define the initialization of the GPIOC register */
|
||||
|
||||
#define LOC_GPIOC_INIT_VALUE 0x2036000 /* GPIO 4&5 in write and
|
||||
both high and GPIO 8 in write low */
|
||||
|
||||
/* The defines by what they actually do */
|
||||
|
||||
#define GPIO_WRITE LOC_GPIOC_GPIO4
|
||||
#define GPIO_PROGRAM LOC_GPIOC_GPIO5
|
||||
#define GPIO_INIT LOC_GPIOC_GPIO6
|
||||
#define GPIO_DONE LOC_GPIOC_GPIO7
|
||||
|
||||
#endif /* _TOR2_HW_H */
|
||||
|
||||
1537
drivers/dahdi/tor2.c
1537
drivers/dahdi/tor2.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1560,7 +1560,7 @@ gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap(
|
||||
if (DspStatus != 0)
|
||||
return (RmmFailure);
|
||||
|
||||
for (i = 0; i < MemoryLength_Word16; i++)
|
||||
for (i = 0; i < MemoryLength_Word16; i++)
|
||||
pDest[i] = (short int) MsgBuffer[2 + i];
|
||||
|
||||
|
||||
@@ -1636,6 +1636,8 @@ gpakWriteSysParmsStatus_t gpakWriteSystemParms(
|
||||
DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */
|
||||
DSP_WORD DspStatus; /* DSP's reply status */
|
||||
|
||||
memset(MsgBuffer, 0, sizeof(MsgBuffer));
|
||||
|
||||
/* Make sure the DSP Id is valid. */
|
||||
if (DspId >= MAX_DSP_CORES)
|
||||
return (WspInvalidDsp);
|
||||
|
||||
@@ -1000,6 +1000,7 @@ __vb_rx_demand_poll(struct voicebus *vb)
|
||||
__vb_setctl(vb, 0x0010, 0x00000000);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_VOICEBUS_TIMER
|
||||
static void
|
||||
__vb_enable_interrupts(struct voicebus *vb)
|
||||
{
|
||||
@@ -1008,6 +1009,7 @@ __vb_enable_interrupts(struct voicebus *vb)
|
||||
else
|
||||
__vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
__vb_disable_interrupts(struct voicebus *vb)
|
||||
@@ -1033,8 +1035,7 @@ static void start_packet_processing(struct voicebus *vb)
|
||||
clear_bit(VOICEBUS_STOP, &vb->flags);
|
||||
clear_bit(VOICEBUS_STOPPED, &vb->flags);
|
||||
#if defined(CONFIG_VOICEBUS_TIMER)
|
||||
vb->timer.expires = jiffies + HZ/1000;
|
||||
add_timer(&vb->timer);
|
||||
mod_timer(&vb->timer, jiffies + HZ/1000);
|
||||
#else
|
||||
/* Clear the interrupt status register. */
|
||||
__vb_setctl(vb, SR_CSR5, 0xffffffff);
|
||||
@@ -1746,18 +1747,17 @@ vb_isr(int irq, void *dev_id)
|
||||
* the timer.
|
||||
*/
|
||||
static void
|
||||
vb_timer(unsigned long data)
|
||||
vb_timer(TIMER_DATA_TYPE timer)
|
||||
{
|
||||
unsigned long start = jiffies;
|
||||
struct voicebus *vb = (struct voicebus *)data;
|
||||
struct voicebus *vb = from_timer(vb, timer, timer);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
vb_isr(0, vb, 0);
|
||||
#else
|
||||
vb_isr(0, vb);
|
||||
#endif
|
||||
if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) {
|
||||
vb->timer.expires = start + HZ/1000;
|
||||
add_timer(&vb->timer);
|
||||
mod_timer(&vb->timer, start + HZ/1000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1800,9 +1800,7 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
|
||||
INIT_LIST_HEAD(&vb->free_rx);
|
||||
|
||||
#if defined(CONFIG_VOICEBUS_TIMER)
|
||||
init_timer(&vb->timer);
|
||||
vb->timer.function = vb_timer;
|
||||
vb->timer.data = (unsigned long)vb;
|
||||
timer_setup(&vb->timer, vb_timer, 0);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
#include <dahdi/kernel.h>
|
||||
#include <dahdi/wctdm_user.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
#include "proslic.h"
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -248,8 +248,8 @@
|
||||
#define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */
|
||||
#define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */
|
||||
#define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */
|
||||
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data comes from STIO1 */
|
||||
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data comes from STIO2 */
|
||||
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data from STIO2 */
|
||||
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data from STIO1 */
|
||||
|
||||
#define V_CH_SNUM_SHIFT (1)
|
||||
#define V_CH_SNUM_MASK (31 << 1)
|
||||
@@ -367,6 +367,16 @@
|
||||
#define V_B2_RX_EN (1 << 1) /* 1=enable B2 RX */
|
||||
#define V_ST_TRI (1 << 6) /* 1=tristate S/T output buffer */
|
||||
|
||||
/* User Flash Manager */
|
||||
#define UFM_PROGRAM (1<<0)
|
||||
#define UFM_ERASE (1<<1)
|
||||
#define UFM_DRSHIFT (1<<2)
|
||||
#define UFM_DRDIN (1<<3)
|
||||
#define UFM_DRCLK (1<<4)
|
||||
#define UFM_ARSHIFT (1<<5)
|
||||
#define UFM_ARDIN (1<<6)
|
||||
#define UFM_ARCLK (1<<7)
|
||||
|
||||
#define NUM_REGS 0xff
|
||||
#define NUM_PCI 12
|
||||
|
||||
@@ -385,7 +395,8 @@
|
||||
|
||||
struct b4xxp_span {
|
||||
struct b4xxp *parent;
|
||||
int port; /* which S/T port this span belongs to */
|
||||
int port; /* virtual port */
|
||||
int phy_port; /* physical port */
|
||||
|
||||
unsigned char writechunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
|
||||
unsigned char readchunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
|
||||
@@ -426,7 +437,9 @@ enum cards_ids { /* Cards ==> Brand & Model */
|
||||
BN4S0, /* Beronet BN4S0 */
|
||||
BN8S0, /* BeroNet BN8S0 */
|
||||
BSWYX_SX2, /* Swyx 4xS0 SX2 QuadBri */
|
||||
QUADBRI_EVAL /* HFC-4S CCD Eval. Board */
|
||||
QUADBRI_EVAL, /* HFC-4S CCD Eval. Board */
|
||||
B430P, /* Digium B430P */
|
||||
B230P /* Digium B230P */
|
||||
};
|
||||
|
||||
/* This structure exists one per card */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -40,7 +41,12 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dahdi/kernel.h"
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
@@ -3695,9 +3701,9 @@ wctc4xxp_send_commands(struct wcdte *wc, struct list_head *to_send)
|
||||
}
|
||||
|
||||
static void
|
||||
wctc4xxp_watchdog(unsigned long data)
|
||||
wctc4xxp_watchdog(TIMER_DATA_TYPE timer)
|
||||
{
|
||||
struct wcdte *wc = (struct wcdte *)data;
|
||||
struct wcdte *wc = from_timer(wc, timer, watchdog);
|
||||
struct tcb *cmd, *temp;
|
||||
LIST_HEAD(cmds_to_retry);
|
||||
const int MAX_RETRIES = 5;
|
||||
@@ -4084,13 +4090,7 @@ wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto error_exit_swinit;
|
||||
}
|
||||
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
wc->watchdog.function = wctc4xxp_watchdog;
|
||||
wc->watchdog.data = (unsigned long)wc;
|
||||
init_timer(&wc->watchdog);
|
||||
# else
|
||||
setup_timer(&wc->watchdog, wctc4xxp_watchdog, (unsigned long)wc);
|
||||
# endif
|
||||
timer_setup(&wc->watchdog, wctc4xxp_watchdog, 0);
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* Load the firmware and start the DTE.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -44,6 +44,7 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -72,6 +73,10 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
|
||||
#include <dahdi/kernel.h>
|
||||
#include <dahdi/wctdm_user.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
#include "proslic.h"
|
||||
|
||||
#include "wctdm24xxp.h"
|
||||
@@ -6047,11 +6052,7 @@ static void __devexit wctdm_remove_one(struct pci_dev *pdev)
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(wctdm_pci_tbl) = {
|
||||
{ 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 },
|
||||
{ 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 },
|
||||
{ 0xd161, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex800 },
|
||||
{ 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 },
|
||||
{ 0xd161, 0x8005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm410 },
|
||||
{ 0xd161, 0x8006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex410 },
|
||||
{ 0xd161, 0x8007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcha80000 },
|
||||
{ 0xd161, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wchb80000 },
|
||||
{ 0 }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp.o
|
||||
|
||||
EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
|
||||
|
||||
wcte12xp-objs := base.o
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Digium, Inc. Wildcard TE12xP T1/E1 card Driver
|
||||
*
|
||||
* Written by Michael Spiceland <mspiceland@digium.com>
|
||||
*
|
||||
* Adapted from the wctdm24xxp and wcte11xp drivers originally
|
||||
* written by Mark Spencer <markster@digium.com>
|
||||
* Matthew Fredrickson <creslin@digium.com>
|
||||
* William Meadows <wmeadows@digium.com>
|
||||
*
|
||||
* Copyright (C) 2007-2010, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#ifndef _WCTE12XP_H
|
||||
#define _WCTE12XP_H
|
||||
|
||||
/* Comment to disable VPM support */
|
||||
#define VPM_SUPPORT 1
|
||||
|
||||
#define WC_MAX_IFACES 8
|
||||
|
||||
#ifdef VPM_SUPPORT
|
||||
#define MAX_TDM_CHAN 31
|
||||
#endif
|
||||
|
||||
#define SDI_CLK (0x00010000)
|
||||
#define SDI_DOUT (0x00020000)
|
||||
#define SDI_DREAD (0x00040000)
|
||||
#define SDI_DIN (0x00080000)
|
||||
|
||||
#define EFRAME_SIZE 108
|
||||
#define ERING_SIZE 16 /* Maximum ring size */
|
||||
#define EFRAME_GAP 20
|
||||
#define SFRAME_SIZE ((EFRAME_SIZE * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1)))
|
||||
|
||||
#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
|
||||
|
||||
#define MAX_COMMANDS 16
|
||||
|
||||
#define NUM_EC 4
|
||||
|
||||
#define __CMD_PINS (1 << 18) /* CPLD pin read */
|
||||
#define __CMD_LEDS (1 << 19) /* LED Operation */
|
||||
#define __CMD_RD (1 << 20) /* Read Operation */
|
||||
#define __CMD_WR (1 << 21) /* Write Operation */
|
||||
|
||||
#define __LED_ORANGE (1<<3)
|
||||
#define __LED_GREEN (1<<2)
|
||||
#define __LED_RED (1<<1)
|
||||
|
||||
#define SET_LED_ORANGE(a) (a | __LED_ORANGE)
|
||||
#define SET_LED_RED(a) ((a | __LED_RED) & ~__LED_GREEN)
|
||||
#define SET_LED_GREEN(a) ((a | __LED_GREEN) & ~__LED_RED)
|
||||
|
||||
#define UNSET_LED_ORANGE(a) (a & ~__LED_ORANGE)
|
||||
#define UNSET_LED_REDGREEN(a) (a | __LED_RED | __LED_GREEN)
|
||||
|
||||
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
|
||||
//TODO: make a separate macro
|
||||
|
||||
enum linemode {
|
||||
T1 = 1,
|
||||
E1,
|
||||
J1,
|
||||
};
|
||||
|
||||
struct command {
|
||||
struct list_head node;
|
||||
struct completion complete;
|
||||
u8 data;
|
||||
u8 ident;
|
||||
u8 cs_slot;
|
||||
u16 address;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct vpm150m;
|
||||
|
||||
struct t1 {
|
||||
spinlock_t reglock;
|
||||
unsigned char txident;
|
||||
unsigned char rxident;
|
||||
unsigned char statreg; /* bit 0 = vpmadt032 int */
|
||||
struct {
|
||||
unsigned int nmf:1;
|
||||
unsigned int sendingyellow:1;
|
||||
} flags;
|
||||
unsigned char txsigs[16]; /* Copy of tx sig registers */
|
||||
int alarmcount; /* How much red alarm we've seen */
|
||||
int losalarmcount;
|
||||
int aisalarmcount;
|
||||
int yelalarmcount;
|
||||
const char *variety;
|
||||
char name[80];
|
||||
unsigned long blinktimer;
|
||||
int loopupcnt;
|
||||
int loopdowncnt;
|
||||
#define INITIALIZED 1
|
||||
#define SHUTDOWN 2
|
||||
#define READY 3
|
||||
#define IOERROR 4
|
||||
unsigned long bit_flags;
|
||||
unsigned long alarmtimer;
|
||||
unsigned char ledstate;
|
||||
unsigned char vpm_check_count;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span; /* Span */
|
||||
struct dahdi_chan *chans[32]; /* Channels */
|
||||
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
|
||||
#ifdef CONFIG_VOICEBUS_ECREFERENCE
|
||||
struct dahdi_fifo *ec_reference[32];
|
||||
#else
|
||||
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
|
||||
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
|
||||
#endif
|
||||
unsigned long ctlreg;
|
||||
struct voicebus vb;
|
||||
atomic_t txints;
|
||||
struct vpmadt032 *vpmadt032;
|
||||
struct vpmoct *vpmoct;
|
||||
unsigned long vpm_check;
|
||||
struct work_struct vpm_check_work;
|
||||
|
||||
/* protected by t1.reglock */
|
||||
struct list_head pending_cmds;
|
||||
struct list_head active_cmds;
|
||||
struct timer_list timer;
|
||||
struct work_struct timer_work;
|
||||
struct workqueue_struct *wq;
|
||||
unsigned int not_ready; /* 0 when entire card is ready to go */
|
||||
};
|
||||
|
||||
#define t1_info(t1, format, arg...) \
|
||||
dev_info(&t1->vb.pdev->dev , format , ## arg)
|
||||
|
||||
#define t1_notice(t1, format, arg...) \
|
||||
dev_notice(&t1->vb.pdev->dev , format , ## arg)
|
||||
|
||||
/* Maintenance Mode Registers */
|
||||
#define LIM0 0x36
|
||||
#define LIM0_LL (1<<1)
|
||||
#define LIM1 0x37
|
||||
#define LIM1_RL (1<<1)
|
||||
#define LIM1_JATT (1<<2)
|
||||
|
||||
/* Clear Channel Registers */
|
||||
#define CCB1 0x2f
|
||||
#define CCB2 0x30
|
||||
#define CCB3 0x31
|
||||
|
||||
#endif
|
||||
@@ -1805,7 +1805,8 @@ static int t13x_software_init(struct t13x *wc, enum linemode type)
|
||||
t13x_serial_setup(wc);
|
||||
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
|
||||
for (x = 0; x < wc->span.channels; x++) {
|
||||
sprintf(wc->chans[x]->name, "%s/%d", wc->span.name, x + 1);
|
||||
snprintf(wc->chans[x]->name, sizeof(wc->chans[x]->name),
|
||||
"%s/%d", wc->span.name, x + 1);
|
||||
t13x_chan_set_sigcap(&wc->span, x);
|
||||
wc->chans[x]->pvt = wc;
|
||||
wc->chans[x]->chanpos = x + 1;
|
||||
@@ -2381,9 +2382,9 @@ static void te13x_handle_interrupt(struct wcxb *xb, u32 pending)
|
||||
}
|
||||
}
|
||||
|
||||
static void te13xp_timer(unsigned long data)
|
||||
static void te13xp_timer(TIMER_DATA_TYPE timer)
|
||||
{
|
||||
struct t13x *wc = (struct t13x *)data;
|
||||
struct t13x *wc = from_timer(wc, timer, timer);
|
||||
|
||||
if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags)))
|
||||
return;
|
||||
@@ -2582,7 +2583,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
|
||||
wc->ledstate = -1;
|
||||
spin_lock_init(&wc->reglock);
|
||||
mutex_init(&wc->lock);
|
||||
setup_timer(&wc->timer, te13xp_timer, (unsigned long)wc);
|
||||
timer_setup(&wc->timer, te13xp_timer, 0);
|
||||
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&wc->timer_work, timer_work_func, wc);
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
#include "wct4xxp/wct4xxp.h" /* For certain definitions */
|
||||
#include "wcxb.h"
|
||||
#include "wcxb_spi.h"
|
||||
@@ -1709,7 +1713,7 @@ static void t43x_configure_e1(struct t43x *wc, int span_idx, int lineconfig)
|
||||
__t43x_framer_set(wc, fidx, 0x21, 0x1c|cas);
|
||||
|
||||
/* Generate pulse mask for E1 */
|
||||
__t43x_framer_set(wc, fidx, 0x26, 0x74); /* XPM0 */
|
||||
__t43x_framer_set(wc, fidx, 0x26, 0xb5); /* XPM0 */
|
||||
__t43x_framer_set(wc, fidx, 0x27, 0x02); /* XPM1 */
|
||||
__t43x_framer_set(wc, fidx, 0x28, 0x00); /* XPM2 */
|
||||
|
||||
@@ -2532,7 +2536,8 @@ t43x_init_one_span(struct t43x *wc, struct t43x_span *ts, enum linemode type)
|
||||
|
||||
set_bit(DAHDI_FLAGBIT_RBS, &ts->span.flags);
|
||||
for (x = 0; x < ts->span.channels; x++) {
|
||||
sprintf(ts->chans[x]->name, "%s/%d", ts->span.name, x + 1);
|
||||
snprintf(ts->chans[x]->name, sizeof(ts->chans[x]->name),
|
||||
"%s/%d", ts->span.name, x + 1);
|
||||
t43x_chan_set_sigcap(&ts->span, x);
|
||||
ts->chans[x]->pvt = wc;
|
||||
ts->chans[x]->chanpos = x + 1;
|
||||
@@ -3199,9 +3204,9 @@ static void t43x_handle_interrupt(struct wcxb *xb, u32 pending)
|
||||
wc->intr_span = 0;
|
||||
}
|
||||
|
||||
static void t43x_timer(unsigned long data)
|
||||
static void t43x_timer(TIMER_DATA_TYPE timer)
|
||||
{
|
||||
struct t43x *wc = (struct t43x *)data;
|
||||
struct t43x *wc = from_timer(wc, timer, timer);
|
||||
|
||||
if (!is_initialized(wc))
|
||||
return;
|
||||
@@ -3427,7 +3432,7 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
|
||||
goto fail_exit;
|
||||
|
||||
mutex_init(&wc->lock);
|
||||
setup_timer(&wc->timer, t43x_timer, (unsigned long)wc);
|
||||
timer_setup(&wc->timer, t43x_timer, 0);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&wc->timer_work, timer_work_func, wc);
|
||||
|
||||
@@ -36,20 +36,9 @@ EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT
|
||||
obj-m += parport_debug.o
|
||||
endif
|
||||
|
||||
# Handle versioning
|
||||
XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi)
|
||||
# Just in case it was left from an older version:
|
||||
clean-files += xpp_version.h
|
||||
|
||||
$(obj)/card_fxs.o $(obj)/card_fxo.o $(obj)/card_bri.o $(obj)/card_pri.o $(obj)/xpp_usb.o $(obj)/xpp.o: $(obj)/xpp_version.h
|
||||
|
||||
$(obj)/xpp_version.h: FORCE
|
||||
@echo ' VERSION $@'
|
||||
$(Q)echo '#define XPP_VERSION $(XPP_VERSION_STR)' > $@.tmp
|
||||
$(Q)if cmp -s $@.tmp $@ ; then echo; else \
|
||||
mv $@.tmp $@ ; \
|
||||
fi
|
||||
$(Q)rm -f $@.tmp
|
||||
|
||||
# Validations:
|
||||
# - Syntactic verification of perl scripts
|
||||
# - Handle country table validation for init_card_2_*
|
||||
@@ -69,7 +58,7 @@ FXO_MODES = $(src)/../fxo_modes.h
|
||||
FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
|
||||
|
||||
hostprogs-y := print_fxo_modes
|
||||
always := $(xpp_verified) xpp_version.h
|
||||
always := $(xpp_verified)
|
||||
print_fxo_modes-objs := print_fxo_modes.o
|
||||
HOSTCFLAGS_print_fxo_modes.o += -include $(FXO_MODES)
|
||||
|
||||
|
||||
@@ -162,7 +162,6 @@ static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
static int bri_startup(struct file *file, struct dahdi_span *span);
|
||||
static int bri_shutdown(struct dahdi_span *span);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
#define PROC_BRI_INFO_FNAME "bri_info"
|
||||
|
||||
enum led_state {
|
||||
@@ -468,8 +467,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
int ret = 0;
|
||||
|
||||
src = REG_XDATA(regcmd);
|
||||
len = regcmd->bytes;
|
||||
eoframe = regcmd->eoframe;
|
||||
len = regcmd->h.bytes;
|
||||
eoframe = regcmd->h.eoframe;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */
|
||||
@@ -565,12 +564,12 @@ static void fill_multibyte(xpd_t *xpd, xpacket_t *pack,
|
||||
char *p;
|
||||
|
||||
XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
|
||||
XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
XPACKET_LEN(pack) = XFRAME_CMD_LEN(REG);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = len;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = xpd->addr.subunit;
|
||||
reg_cmd->eoframe = eoframe;
|
||||
reg_cmd->h.bytes = len;
|
||||
reg_cmd->h.is_multibyte = 1;
|
||||
reg_cmd->h.portnum = xpd->addr.subunit;
|
||||
reg_cmd->h.eoframe = eoframe;
|
||||
p = REG_XDATA(reg_cmd);
|
||||
memcpy(p, buf, len);
|
||||
if (debug)
|
||||
@@ -611,7 +610,7 @@ static int tx_dchan(xpd_t *xpd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
|
||||
int packet_len = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
int packet_len = XFRAME_CMD_LEN(REG);
|
||||
char buf[MULTIBYTE_MAX_LEN];
|
||||
int len = MULTIBYTE_MAX_LEN;
|
||||
|
||||
@@ -687,20 +686,29 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
}
|
||||
|
||||
static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels = min(3, CHANNELS_PERXPD);
|
||||
|
||||
if (subunit_ports != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
|
||||
if ((unit_descriptor->ports_per_chip < 1) ||
|
||||
(unit_descriptor->ports_per_chip > 4)) {
|
||||
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
|
||||
unit_descriptor->ports_per_chip);
|
||||
return NULL;
|
||||
}
|
||||
if ((unit_descriptor->numchips) < 1 ||
|
||||
(unit_descriptor->numchips > 2)) {
|
||||
XBUS_ERR(xbus, "Bad numchips=%d\n",
|
||||
unit_descriptor->numchips);
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct BRI_priv_data), proto_table, channels);
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
|
||||
@@ -977,7 +985,8 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
||||
0, /* data_low */
|
||||
0, /* do_datah */
|
||||
0, /* data_high */
|
||||
0 /* should_reply */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
);
|
||||
|
||||
if (IS_NT(xpd) && nt_keepalive
|
||||
@@ -1426,7 +1435,8 @@ static int write_state_register(xpd_t *xpd, __u8 value)
|
||||
value, /* data_low */
|
||||
0, /* do_datah */
|
||||
0, /* data_high */
|
||||
0 /* should_reply */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
@@ -1538,7 +1548,7 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/* Map UNIT + PORTNUM to XPD */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->portnum;
|
||||
addr.subunit = info->h.portnum;
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
if (!xpd) {
|
||||
static int rate_limit;
|
||||
@@ -1563,9 +1573,9 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
|
||||
REG_FIELD(info, data_low));
|
||||
}
|
||||
if (info->is_multibyte) {
|
||||
if (info->h.is_multibyte) {
|
||||
XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
|
||||
info->bytes, info->eoframe);
|
||||
info->h.bytes, info->h.eoframe);
|
||||
ret = rx_dchan(xpd, info);
|
||||
if (ret < 0) {
|
||||
priv->dchan_rx_drops++;
|
||||
@@ -1745,9 +1755,9 @@ static int bri_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->type != XPD_TYPE_BRI) {
|
||||
if (xpd->xpd_type != XPD_TYPE_BRI) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->type);
|
||||
xpd->xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -1764,7 +1774,7 @@ static int bri_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver bri_driver = {
|
||||
.type = XPD_TYPE_BRI,
|
||||
.xpd_type = XPD_TYPE_BRI,
|
||||
.driver = {
|
||||
.name = "bri",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1778,7 +1788,6 @@ static int __init card_bri_startup(void)
|
||||
|
||||
if ((ret = xpd_driver_register(&bri_driver.driver)) < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
xproto_register(&PROTO_TABLE(BRI));
|
||||
return 0;
|
||||
}
|
||||
@@ -1793,7 +1802,6 @@ static void __exit card_bri_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP BRI Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_BRI);
|
||||
|
||||
module_init(card_bri_startup);
|
||||
|
||||
@@ -54,20 +54,21 @@ static xproto_table_t PROTO_TABLE(ECHO);
|
||||
/*---------------- ECHO: Methods -------------------------------------------*/
|
||||
|
||||
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels = 0;
|
||||
|
||||
if (subunit_ports != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
|
||||
if (unit_descriptor->ports_per_chip != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct ECHO_priv_data), proto_table, channels);
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct ECHO_priv_data), proto_table, unit_descriptor, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
xpd->type_name = "ECHO";
|
||||
@@ -80,7 +81,7 @@ static int ECHO_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
|
||||
BUG_ON(!xpd);
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
xpd->type = XPD_TYPE_ECHO;
|
||||
xpd->xpd_type = XPD_TYPE_ECHO;
|
||||
XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name);
|
||||
ret = CALL_EC_METHOD(ec_update, xbus, xbus);
|
||||
return ret;
|
||||
@@ -112,7 +113,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/* Map UNIT + PORTNUM to XPD */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->portnum;
|
||||
addr.subunit = info->h.portnum;
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
if (!xpd) {
|
||||
static int rate_limit;
|
||||
@@ -307,9 +308,9 @@ static int echo_xpd_probe(struct device *dev)
|
||||
|
||||
ec_xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (ec_xpd->type != XPD_TYPE_ECHO) {
|
||||
if (ec_xpd->xpd_type != XPD_TYPE_ECHO) {
|
||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
ec_xpd->type);
|
||||
ec_xpd->xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||
@@ -326,7 +327,7 @@ static int echo_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver echo_driver = {
|
||||
.type = XPD_TYPE_ECHO,
|
||||
.xpd_type = XPD_TYPE_ECHO,
|
||||
.driver = {
|
||||
.name = "echo",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -341,7 +342,6 @@ static int __init card_echo_startup(void)
|
||||
ret = xpd_driver_register(&echo_driver.driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
INFO("FEATURE: WITH Octasic echo canceller\n");
|
||||
xproto_register(&PROTO_TABLE(ECHO));
|
||||
return 0;
|
||||
@@ -357,7 +357,6 @@ static void __exit card_echo_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP ECHO Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_ECHO);
|
||||
|
||||
module_init(card_echo_startup);
|
||||
|
||||
@@ -100,7 +100,7 @@ enum fxo_leds {
|
||||
#define DAA_READ 0
|
||||
#define DAA_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \
|
||||
xpp_register_request((xbus), (xpd), (port), \
|
||||
(writing), (reg), 0, 0, (dL), 0, 0, 0)
|
||||
(writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
|
||||
|
||||
/*---------------- FXO Protocol Commands ----------------------------------*/
|
||||
|
||||
@@ -115,7 +115,6 @@ static const struct file_operations proc_xpd_metering_ops;
|
||||
static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
|
||||
static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
#define PROC_FXO_INFO_FNAME "fxo_info"
|
||||
#ifdef WITH_METERING
|
||||
#define PROC_METERING_FNAME "metering_read"
|
||||
@@ -488,11 +487,13 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
}
|
||||
|
||||
static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels;
|
||||
int subunit_ports;
|
||||
|
||||
if (to_phone) {
|
||||
XBUS_NOTICE(xbus,
|
||||
@@ -501,13 +502,14 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
unit, subunit);
|
||||
return NULL;
|
||||
}
|
||||
if (subtype == 2)
|
||||
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
|
||||
if (unit_descriptor->subtype == 2)
|
||||
channels = min(2, subunit_ports);
|
||||
else
|
||||
channels = min(8, subunit_ports);
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct FXO_priv_data), proto_table, channels);
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
PHONEDEV(xpd).direction = TO_PSTN;
|
||||
@@ -618,7 +620,6 @@ static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on)
|
||||
BUG_ON(!priv);
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF");
|
||||
for_each_line(xpd, i) {
|
||||
dahdi_report_battery(xpd, i);
|
||||
MARK_OFF(priv, i, LED_GREEN);
|
||||
msleep(2);
|
||||
MARK_OFF(priv, i, LED_RED);
|
||||
@@ -627,6 +628,23 @@ static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FXO_span_assigned(xpd_t *xpd)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
struct FXO_priv_data *priv;
|
||||
int i;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
xbus = xpd->xbus;
|
||||
BUG_ON(!xbus);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
for_each_line(xpd, i)
|
||||
dahdi_report_battery(xpd, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FXO_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
||||
{
|
||||
struct FXO_priv_data *priv;
|
||||
@@ -1247,7 +1265,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
portno = info->portnum;
|
||||
portno = info->h.portnum;
|
||||
switch (REG_FIELD(info, regnum)) {
|
||||
case REG_INTERRUPT_SRC:
|
||||
got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
|
||||
@@ -1265,7 +1283,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
#endif
|
||||
}
|
||||
LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||
((info->bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
|
||||
((info->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
|
||||
REG_FIELD(info, data_low), REG_FIELD(info, data_high));
|
||||
/* Update /proc info only if reply relate to the last slic read request */
|
||||
if (REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
@@ -1312,6 +1330,7 @@ static const struct phoneops fxo_phoneops = {
|
||||
.card_ioctl = FXO_card_ioctl,
|
||||
.card_open = FXO_card_open,
|
||||
.card_state = FXO_card_state,
|
||||
.span_assigned = FXO_span_assigned,
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(FXO) = {
|
||||
@@ -1553,9 +1572,9 @@ static int fxo_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->type != XPD_TYPE_FXO) {
|
||||
if (xpd->xpd_type != XPD_TYPE_FXO) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->type);
|
||||
xpd->xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -1581,7 +1600,7 @@ static int fxo_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver fxo_driver = {
|
||||
.type = XPD_TYPE_FXO,
|
||||
.xpd_type = XPD_TYPE_FXO,
|
||||
.driver = {
|
||||
.name = "fxo",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1600,7 +1619,6 @@ static int __init card_fxo_startup(void)
|
||||
}
|
||||
if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
#ifdef WITH_METERING
|
||||
INFO("FEATURE: WITH METERING Detection\n");
|
||||
#else
|
||||
@@ -1619,7 +1637,6 @@ static void __exit card_fxo_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP FXO Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_FXO);
|
||||
|
||||
module_init(card_fxo_startup);
|
||||
|
||||
@@ -41,6 +41,7 @@ static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware");
|
||||
#ifdef POLL_DIGITAL_INPUTS
|
||||
static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
|
||||
#endif
|
||||
static DEF_PARM(uint, poll_chan_linefeed, 30000, 0644, "Poll Channel Linefeed");
|
||||
|
||||
static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644,
|
||||
"Asterisk support VMWI notification via ioctl");
|
||||
@@ -77,15 +78,21 @@ enum fxs_leds {
|
||||
#define SLIC_READ 0
|
||||
#define SLIC_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \
|
||||
xpp_register_request((xbus), (xpd), (port), \
|
||||
(writing), (reg), 0, 0, (dL), 0, 0, 0)
|
||||
(writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
|
||||
#define SLIC_INDIRECT_REQUEST(xbus, xpd, port, writing, reg, dL, dH) \
|
||||
xpp_register_request((xbus), (xpd), (port), \
|
||||
(writing), 0x1E, 1, (reg), (dL), 1, (dH), 0)
|
||||
(writing), 0x1E, 1, (reg), (dL), 1, (dH), 0, 0)
|
||||
#define EXP_REQUEST(xbus, xpd, writing, reg, dL, dH) \
|
||||
xpp_register_request((xbus), (xpd), 0, \
|
||||
(writing), (reg), 1, 0, (dL), 1, (dH), 0, 1)
|
||||
#define RAM_REQUEST(xbus, xpd, port, writing, addr, data) \
|
||||
xpp_ram_request((xbus), (xpd), (port), \
|
||||
(writing), (__u8)(addr), (__u8)((addr) >> 8), (__u8)(data), (__u8)((data) >> 8), (__u8)((data) >> 16), (__u8)((data) >> 24), 0)
|
||||
|
||||
#define VALID_PORT(port) \
|
||||
(((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST)
|
||||
|
||||
#define REG_DIGITAL_IOCTRL 0x06 /* LED and RELAY control */
|
||||
#define REG_TYPE1_DIGITAL_IOCTRL 0x06 /* LED and RELAY control */
|
||||
|
||||
/* Values of SLIC linefeed control register (0x40) */
|
||||
enum fxs_state {
|
||||
@@ -99,22 +106,54 @@ enum fxs_state {
|
||||
FXS_LINE_RING_OPEN = 0x07 /* RING open */
|
||||
};
|
||||
|
||||
enum neon_state {
|
||||
END_NEON = 0,
|
||||
INIT_NEON = 1,
|
||||
};
|
||||
|
||||
#define FXS_LINE_POL_ACTIVE \
|
||||
((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE)
|
||||
#define FXS_LINE_POL_OHTRANS \
|
||||
((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS)
|
||||
|
||||
/* FXS type 1 registers */
|
||||
#define REG_TYPE1_RINGCON 0x22 /* 34 - Ringing Oscillator Control */
|
||||
|
||||
/*
|
||||
* DTMF detection
|
||||
*/
|
||||
#define REG_DTMF_DECODE 0x18 /* 24 - DTMF Decode Status */
|
||||
#define REG_BATTERY 0x42 /* 66 - Battery Feed Control */
|
||||
#define REG_BATTERY_BATSL BIT(1) /* Battery Feed Select */
|
||||
#define REG_TYPE1_DTMF_DECODE 0x18 /* 24 - DTMF Decode Status */
|
||||
#define REG_TYPE1_BATTERY 0x42 /* 66 - Battery Feed Control */
|
||||
#define REG_TYPE1_BATTERY_BATSL BIT(1) /* Battery Feed Select */
|
||||
|
||||
/* 68 - Loop Closure/Ring Trip Detect Status */
|
||||
#define REG_LOOPCLOSURE 0x44
|
||||
#define REG_LOOPCLOSURE_ZERO 0xF8 /* Loop Closure zero bits. */
|
||||
#define REG_LOOPCLOSURE_LCR BIT(0) /* Loop Closure Detect Indicator. */
|
||||
#define REG_TYPE1_LOOPCLOSURE 0x44
|
||||
#define REG_TYPE1_LOOPCLOSURE_ZERO 0xF8 /* Loop Closure zero bits. */
|
||||
#define REG_TYPE1_LOOPCLOSURE_LCR BIT(0) /* Loop Closure Detect Indicator. */
|
||||
|
||||
/* FXS type 6 registers */
|
||||
#define REG_TYPE6_RINGCON 0x26 /* 38 - Ringing Oscillator Control */
|
||||
|
||||
/* 34 - Loop Closure/Ring Trip Detect Status */
|
||||
#define REG_TYPE6_LCRRTP 0x22
|
||||
#define REG_TYPE6_LCRRTP_ZERO 0xF0 /* Loop Closure zero bits. */
|
||||
#define REG_TYPE6_LCRRTP_LCR BIT(1) /* Loop Closure Detect Indicator. */
|
||||
|
||||
#define REG_TYPE6_TONEN 0x3E /* 62 - Hardware DTMF detection */
|
||||
#define REG_TYPE6_TONEN_DTMF_DIS BIT(2) /* DTMF Disable */
|
||||
#define REG_TYPE6_LINEFEED 0x1E /* 30 - Linefeed */
|
||||
#define REG_TYPE6_TONDTMF 0x3C /* 60 - DTMF Decode Status */
|
||||
#define REG_TYPE6_EXP_GPIOA 0x12 /* I/O Expander GPIOA */
|
||||
#define REG_TYPE6_EXP_GPIOB 0x13 /* I/O Expander GPIOB */
|
||||
#define REG_TYPE6_ENHANCE 0x2F /* 47 - Enhance */
|
||||
#define REG_TYPE6_USERSTAT 0x42 /* 66 - Userstat */
|
||||
#define REG_TYPE6_DIAG1 0x47 /* 71 - Diag1 */
|
||||
#define RAM_TYPE6_SLOPE_VLIM 634
|
||||
#define SLOPE_VLIM_DFLT 0x1E655196L
|
||||
#define SLOPE_VLIM_MWI 0x8000000L
|
||||
#define RAM_TYPE6_VBATH_EXPECT 767
|
||||
#define VBATH_EXPECT_DFLT 0x2B10A20L
|
||||
#define VBATH_EXPECT_MWI 0x6147AB2L
|
||||
|
||||
/*---------------- FXS Protocol Commands ----------------------------------*/
|
||||
|
||||
@@ -128,7 +167,6 @@ static const struct file_operations proc_xpd_metering_ops;
|
||||
#endif
|
||||
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
#define PROC_FXS_INFO_FNAME "fxs_info"
|
||||
#ifdef WITH_METERING
|
||||
#define PROC_METERING_FNAME "metering_gen"
|
||||
@@ -148,14 +186,17 @@ struct FXS_priv_data {
|
||||
xpp_line_t want_dtmf_mute; /* what dahdi want */
|
||||
xpp_line_t prev_key_down; /* DTMF down sets the bit */
|
||||
xpp_line_t neon_blinking;
|
||||
xpp_line_t neonstate;
|
||||
xpp_line_t vbat_h; /* High voltage */
|
||||
struct timeval prev_key_time[CHANNELS_PERXPD];
|
||||
int led_counter[NUM_LEDS][CHANNELS_PERXPD];
|
||||
int overheat_reset_counter[CHANNELS_PERXPD];
|
||||
int ohttimer[CHANNELS_PERXPD];
|
||||
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
|
||||
/* IDLE changing hook state */
|
||||
enum fxs_state idletxhookstate[CHANNELS_PERXPD];
|
||||
enum fxs_state lasttxhook[CHANNELS_PERXPD];
|
||||
enum fxs_state polledhook[CHANNELS_PERXPD];
|
||||
struct dahdi_vmwi_info vmwisetting[CHANNELS_PERXPD];
|
||||
};
|
||||
|
||||
@@ -181,6 +222,9 @@ struct FXS_priv_data {
|
||||
#define LED_BLINK_RING (1000/8) /* in ticks */
|
||||
|
||||
/*---------------- FXS: Static functions ----------------------------------*/
|
||||
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
unsigned int msg_waiting);
|
||||
|
||||
static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
@@ -189,6 +233,10 @@ static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
|
||||
|
||||
BUG_ON(!xbus);
|
||||
BUG_ON(!xpd);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
LINE_DBG(SIGNAL, xpd, chan, "is ignored in Si32260\n");
|
||||
return 0;
|
||||
}
|
||||
priv = xpd->priv;
|
||||
p = (unsigned long *)&priv->vbat_h;
|
||||
if (on)
|
||||
@@ -201,8 +249,8 @@ static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
|
||||
return 0;
|
||||
}
|
||||
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
|
||||
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY,
|
||||
(on) ? REG_BATTERY_BATSL : 0x00);
|
||||
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE1_BATTERY,
|
||||
(on) ? (int)REG_TYPE1_BATTERY_BATSL : 0x00);
|
||||
}
|
||||
|
||||
static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan,
|
||||
@@ -223,7 +271,20 @@ static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan,
|
||||
do_chan_power(xbus, xpd, chan, want_vbat_h);
|
||||
LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value);
|
||||
priv->lasttxhook[chan] = value;
|
||||
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
int ret;
|
||||
|
||||
/* Make sure NEON state is off for */
|
||||
if (value == FXS_LINE_POL_OHTRANS && IS_SET(priv->neon_blinking, chan))
|
||||
set_vm_led_mode(xpd->xbus, xpd, chan, 0);
|
||||
ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE6_LINEFEED, value);
|
||||
if (value == FXS_LINE_POL_ACTIVE && PHONEDEV(xpd).msg_waiting[chan])
|
||||
set_vm_led_mode(xpd->xbus, xpd, chan, PHONEDEV(xpd).msg_waiting[chan]);
|
||||
return ret;
|
||||
} else {
|
||||
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
|
||||
@@ -296,19 +357,75 @@ static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
|
||||
else
|
||||
BIT_CLR(priv->ledstate[which], chan);
|
||||
}
|
||||
LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which,
|
||||
LINE_DBG(LEDS, xpd, chan, "LED: (type=%d) which=%d -- %s\n", XPD_HW(xpd).type, which,
|
||||
(on) ? "on" : "off");
|
||||
value = BIT(2) | BIT(3);
|
||||
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
|
||||
if (on)
|
||||
value |= led_register_vals[which];
|
||||
ret =
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_DIGITAL_IOCTRL,
|
||||
value);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
int mask = 1 << chan;
|
||||
value = (on) << chan;
|
||||
XPD_DBG(LEDS, xpd, "LED(%d): 0x%0X (mask: 0x%0X)\n", chan,
|
||||
value, mask);
|
||||
if (which == LED_GREEN) { /* other leds ignored */
|
||||
ret = EXP_REQUEST(xbus, xpd, SLIC_WRITE,
|
||||
REG_TYPE6_EXP_GPIOA, value, mask);
|
||||
}
|
||||
} else {
|
||||
value = BIT(2) | BIT(3);
|
||||
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
|
||||
if (on)
|
||||
value |= led_register_vals[which];
|
||||
ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE,
|
||||
REG_TYPE1_DIGITAL_IOCTRL, value);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void set_mwi_led(xpd_t *xpd, int pos, int on)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
|
||||
if (XPD_HW(xpd).type != 6)
|
||||
return;
|
||||
if (on) {
|
||||
if (! IS_SET(priv->neonstate, pos)) {
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x00);
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x04);
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x0F);
|
||||
BIT_SET(priv->neonstate, pos);
|
||||
}
|
||||
} else {
|
||||
if (IS_SET(priv->neonstate, pos)) {
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x00);
|
||||
BIT_CLR(priv->neonstate, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void blink_mwi(xpd_t *xpd)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
unsigned int timer_count;
|
||||
int i;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
timer_count = xpd->timer_count;
|
||||
for_each_line(xpd, i) {
|
||||
unsigned int msgs = PHONEDEV(xpd).msg_waiting[i];
|
||||
/* LED duty cycle: 300ms on, 700ms off */
|
||||
unsigned int in_range = (timer_count % 1000) >= 0 && (timer_count % 1000) <= 300;
|
||||
|
||||
if (!IS_OFFHOOK(xpd, i) && msgs && in_range &&
|
||||
IS_SET(priv->neon_blinking,i) && priv->ohttimer[i] == 0)
|
||||
set_mwi_led(xpd, i, 1);
|
||||
else
|
||||
set_mwi_led(xpd, i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_fxs_leds(xpd_t *xpd)
|
||||
{
|
||||
int i;
|
||||
@@ -379,6 +496,10 @@ static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
|
||||
{
|
||||
__u8 value = (on) ? 0x94 : 0x00;
|
||||
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
XBUS_NOTICE("Metering not supported with FXS type 6");
|
||||
return 0;
|
||||
}
|
||||
LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n",
|
||||
(on) ? "ON" : "OFF");
|
||||
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23,
|
||||
@@ -446,11 +567,13 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
}
|
||||
|
||||
static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels;
|
||||
int subunit_ports;
|
||||
int regular_channels;
|
||||
struct FXS_priv_data *priv;
|
||||
int i;
|
||||
@@ -463,20 +586,21 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
unit, subunit);
|
||||
return NULL;
|
||||
}
|
||||
if (subtype == 2)
|
||||
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
|
||||
if (unit_descriptor->subtype == 2)
|
||||
regular_channels = min(6, subunit_ports);
|
||||
else
|
||||
regular_channels = min(8, subunit_ports);
|
||||
channels = regular_channels;
|
||||
/* Calculate digital inputs/outputs */
|
||||
if (unit == 0 && subtype != 4) {
|
||||
if (unit == 0 && unit_descriptor->subtype != 4 && unit_descriptor->numchips != 4) {
|
||||
channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
|
||||
d_inputs = LINES_DIGI_INP;
|
||||
d_outputs = LINES_DIGI_OUT;
|
||||
}
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct FXS_priv_data), proto_table, channels);
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct FXS_priv_data), proto_table, unit_descriptor, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
/* Initialize digital inputs/outputs */
|
||||
@@ -510,20 +634,30 @@ err:
|
||||
|
||||
static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
/*
|
||||
* Setup ring timers
|
||||
*/
|
||||
/* Software controled ringing (for CID) */
|
||||
/* Ringing Oscilator Control */
|
||||
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
|
||||
0x22, 0x00);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
|
||||
REG_TYPE6_RINGCON, 0x00);
|
||||
} else {
|
||||
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
|
||||
REG_TYPE1_RINGCON, 0x00);
|
||||
}
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
for_each_line(xpd, i) {
|
||||
if (XPD_HW(xpd).type == 6)
|
||||
/* An arbitrary value that is not FXS_LINE_OPEN */
|
||||
priv->polledhook[i] = FXS_LINE_ACTIVE;
|
||||
linefeed_control(xbus, xpd, i, FXS_LINE_POL_ACTIVE);
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "done\n");
|
||||
@@ -551,8 +685,13 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
|
||||
digital_inputs, i))
|
||||
continue;
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE,
|
||||
0);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE6_LCRRTP,
|
||||
0);
|
||||
} else {
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE1_LOOPCLOSURE,
|
||||
0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
@@ -702,6 +841,34 @@ static struct ring_reg_params ring_parameters[] = {
|
||||
REG_ENTRY(1, 0x1D, 0x00, 0x46, 0x00, 0x36, 0x00, 0x36),
|
||||
};
|
||||
|
||||
static void set_neon_state(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
enum neon_state ns)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
|
||||
LINE_DBG(SIGNAL, xpd, pos, "set NEON -> %d\n", ns);
|
||||
priv = xpd->priv;
|
||||
if (ns == INIT_NEON)
|
||||
BIT_SET(priv->neon_blinking, pos);
|
||||
else
|
||||
BIT_CLR(priv->neon_blinking, pos);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
switch (ns) {
|
||||
case INIT_NEON:
|
||||
RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_MWI << 3);
|
||||
//RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_MWI << 3);
|
||||
break;
|
||||
default:
|
||||
LINE_DBG(REGS, xpd, pos, "0x%04X: R 0x\n", RAM_TYPE6_SLOPE_VLIM);
|
||||
set_mwi_led(xpd, pos, 0); /* Cannot have NEON LED during OHT (type == 6) */
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x00);
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x10);
|
||||
RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_DFLT << 3);
|
||||
RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_DFLT << 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
enum ring_types rtype)
|
||||
{
|
||||
@@ -710,6 +877,8 @@ static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (XPD_HW(xpd).type == 6)
|
||||
return 0;
|
||||
if (rtype < RING_TYPE_NEON || rtype > RING_TYPE_NORMAL)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
|
||||
@@ -755,15 +924,16 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
if (VMWI_NEON(priv, pos) && msg_waiting) {
|
||||
/* A write to register 0x40 will now turn on/off the VM led */
|
||||
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
|
||||
BIT_SET(priv->neon_blinking, pos);
|
||||
set_neon_state(xbus, xpd, pos, INIT_NEON);
|
||||
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NEON);
|
||||
} else if (ring_trapez) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
|
||||
set_neon_state(xbus, xpd, pos, END_NEON);
|
||||
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_TRAPEZ);
|
||||
} else {
|
||||
/* A write to register 0x40 will now turn on/off the ringer */
|
||||
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
|
||||
BIT_CLR(priv->neon_blinking, pos);
|
||||
set_neon_state(xbus, xpd, pos, END_NEON);
|
||||
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NORMAL);
|
||||
}
|
||||
return (ret ? -EPROTO : 0);
|
||||
@@ -782,31 +952,43 @@ static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
|
||||
msgs = PHONEDEV(xpd).msg_waiting[pos];
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
|
||||
set_vm_led_mode(xbus, xpd, pos, msgs);
|
||||
do_chan_power(xbus, xpd, pos, msgs > 0);
|
||||
linefeed_control(xbus, xpd, pos,
|
||||
(msgs >
|
||||
0) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
|
||||
if (XPD_HW(xpd).type == 1) {
|
||||
do_chan_power(xbus, xpd, pos, msgs > 0);
|
||||
linefeed_control(xbus, xpd, pos,
|
||||
(msgs > 0) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
static int relay_out(xpd_t *xpd, int pos, bool on)
|
||||
{
|
||||
int value;
|
||||
int ret = 0;
|
||||
int value = 0;
|
||||
int which = pos;
|
||||
int relay_channels[] = { 0, 4 };
|
||||
|
||||
BUG_ON(!xpd);
|
||||
/* map logical position to output port number (0/1) */
|
||||
which -= (xpd->subtype == 2) ? 6 : 8;
|
||||
which -= (XPD_HW(xpd).subtype == 2) ? 6 : 8;
|
||||
LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which,
|
||||
(on) ? "on" : "off");
|
||||
which = which % ARRAY_SIZE(relay_channels);
|
||||
value = BIT(2) | BIT(3);
|
||||
value |=
|
||||
((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
|
||||
if (on)
|
||||
value |= led_register_vals[OUTPUT_RELAY];
|
||||
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels[which],
|
||||
SLIC_WRITE, REG_DIGITAL_IOCTRL, value);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
int relay_values_type6[] = { 0x01, 0x40 };
|
||||
which = which % ARRAY_SIZE(relay_values_type6);
|
||||
if (on)
|
||||
value |= relay_values_type6[which];
|
||||
ret = EXP_REQUEST(xpd->xbus, xpd, SLIC_WRITE,
|
||||
REG_TYPE6_EXP_GPIOB, value, relay_values_type6[which]);
|
||||
} else {
|
||||
int relay_channels_type1[] = { 0, 4 };
|
||||
which = which % ARRAY_SIZE(relay_channels_type1);
|
||||
value = BIT(2) | BIT(3);
|
||||
value |=
|
||||
((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
|
||||
if (on)
|
||||
value |= led_register_vals[OUTPUT_RELAY];
|
||||
ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels_type1[which],
|
||||
SLIC_WRITE, REG_TYPE1_DIGITAL_IOCTRL, value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int send_ring(xpd_t *xpd, lineno_t chan, bool on)
|
||||
@@ -988,6 +1170,21 @@ static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hardware_dtmf_control(xpd_t *xpd, int pos, bool on)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s: %s\n", __func__, (on) ? "on" : "off");
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
int value = (on) ? 0xE0 : REG_TYPE6_TONEN_DTMF_DIS;
|
||||
ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE,
|
||||
REG_TYPE6_TONEN, value);
|
||||
} else {
|
||||
ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, 0x17, on);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private ioctl()
|
||||
* We don't need it now, since we detect vmwi via FSK patterns
|
||||
@@ -1053,9 +1250,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||
* Detection mode changed:
|
||||
* Disable DTMF interrupts
|
||||
*/
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
||||
0x17, 0);
|
||||
}
|
||||
hardware_dtmf_control(xpd, pos, 0);
|
||||
BIT_CLR(priv->want_dtmf_events, pos);
|
||||
BIT_CLR(priv->want_dtmf_mute, pos);
|
||||
__do_mute_dtmf(xpd, pos, 0);
|
||||
@@ -1077,8 +1273,7 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||
LINE_DBG(SIGNAL, xpd, pos,
|
||||
"DAHDI_TONEDETECT: "
|
||||
"Enable Hardware DTMF\n");
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
||||
0x17, 1);
|
||||
hardware_dtmf_control(xpd, pos, 1);
|
||||
}
|
||||
BIT_SET(priv->want_dtmf_events, pos);
|
||||
} else {
|
||||
@@ -1090,8 +1285,7 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||
LINE_DBG(SIGNAL, xpd, pos,
|
||||
"DAHDI_TONEDETECT: "
|
||||
"Disable Hardware DTMF\n");
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
||||
0x17, 0);
|
||||
hardware_dtmf_control(xpd, pos, 0);
|
||||
}
|
||||
BIT_CLR(priv->want_dtmf_events, pos);
|
||||
}
|
||||
@@ -1147,11 +1341,13 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||
if (!vmwi_ioctl) {
|
||||
static bool notified;
|
||||
|
||||
if (!notified++)
|
||||
if (!notified) {
|
||||
notified = true;
|
||||
LINE_NOTICE(xpd, pos,
|
||||
"Got DAHDI_VMWI notification "
|
||||
"but vmwi_ioctl parameter is off. "
|
||||
"Ignoring.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Digital inputs/outputs don't have VM leds */
|
||||
@@ -1209,21 +1405,67 @@ static int FXS_card_close(xpd_t *xpd, lineno_t chan)
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
*
|
||||
*/
|
||||
static int input_channels[] = { 6, 7, 2, 3 }; // Slic numbers of input relays
|
||||
static int input_ports_type1[] = {
|
||||
/* slic = input_port */
|
||||
[0] = -1,
|
||||
[1] = -1,
|
||||
[2] = 2,
|
||||
[3] = 3,
|
||||
[4] = -1,
|
||||
[5] = -1,
|
||||
[6] = 0,
|
||||
[7] = 1,
|
||||
};
|
||||
|
||||
static void poll_inputs(xpd_t *xpd)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON(xpd->xbus_idx != 0); // Only unit #0 has digital inputs
|
||||
for (i = 0; i < ARRAY_SIZE(input_channels); i++) {
|
||||
__u8 pos = input_channels[i];
|
||||
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_READ, 0x06, 0);
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
EXP_REQUEST(xpd->xbus, xpd, SLIC_READ,
|
||||
REG_TYPE6_EXP_GPIOB, 0, 0);
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(input_ports_type1); i++) {
|
||||
int pos = input_ports_type1[i];
|
||||
if (pos >= 0) {
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ, 0x06, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void poll_linefeed(xpd_t *xpd)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
int i;
|
||||
|
||||
if (XPD_HW(xpd).type != 6)
|
||||
return;
|
||||
if (xpd->xpd_state != XPD_STATE_READY)
|
||||
return;
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
BUG_ON(!xpd->xbus);
|
||||
|
||||
XPD_DBG(GENERAL, xpd, "periodic poll");
|
||||
for_each_line(xpd, i) {
|
||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
|| IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
continue;
|
||||
if (priv->polledhook[i] == FXS_LINE_OPEN &&
|
||||
priv->lasttxhook[i] != FXS_LINE_OPEN) {
|
||||
LINE_NOTICE(xpd, i, "Overheat detected, resetting.");
|
||||
priv->overheat_reset_counter[i]++;
|
||||
linefeed_control(xpd->xbus, xpd, i,
|
||||
priv->lasttxhook[i]);
|
||||
}
|
||||
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ,
|
||||
REG_TYPE6_LINEFEED, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_linefeed(xpd_t *xpd)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
@@ -1369,8 +1611,12 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
|
||||
poll_inputs(xpd);
|
||||
}
|
||||
#endif
|
||||
if ((xpd->timer_count % poll_chan_linefeed) == 0)
|
||||
poll_linefeed(xpd);
|
||||
handle_fxs_leds(xpd);
|
||||
handle_linefeed(xpd);
|
||||
if (XPD_HW(xpd).type == 6)
|
||||
blink_mwi(xpd);
|
||||
/*
|
||||
* Hack alert (FIXME):
|
||||
* Asterisk did FXS_card_open() and we wanted to report
|
||||
@@ -1481,37 +1727,55 @@ HANDLER_DEF(FXS, SIG_CHANGED)
|
||||
}
|
||||
|
||||
#ifdef POLL_DIGITAL_INPUTS
|
||||
static inline void notify_digital_input(xpd_t *xpd, int input_port, int offhook)
|
||||
{
|
||||
int channo = PHONEDEV(xpd).channels - LINES_DIGI_INP + input_port;
|
||||
|
||||
/* Stop ringing. No leds for digital inputs. */
|
||||
PHONEDEV(xpd).ringing[channo] = 0;
|
||||
if (offhook && !IS_OFFHOOK(xpd, channo)) {
|
||||
LINE_DBG(SIGNAL, xpd, channo, "OFFHOOK\n");
|
||||
hookstate_changed(xpd, channo, 1);
|
||||
} else if (!offhook && IS_OFFHOOK(xpd, channo)) {
|
||||
LINE_DBG(SIGNAL, xpd, channo, "ONHOOK\n");
|
||||
hookstate_changed(xpd, channo, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
|
||||
{
|
||||
int i;
|
||||
bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
|
||||
xpp_line_t lines = BIT(info->portnum);
|
||||
|
||||
bool offhook;
|
||||
/* Sanity check */
|
||||
if (!PHONEDEV(xpd).digital_inputs) {
|
||||
XPD_NOTICE(xpd, "%s called without digital inputs. Ignored\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
/* Map SLIC number into line number */
|
||||
for (i = 0; i < ARRAY_SIZE(input_channels); i++) {
|
||||
int channo = input_channels[i];
|
||||
int newchanno;
|
||||
if (XPD_HW(xpd).type == 6) {
|
||||
static int input_values_type6[] = { 0x80, 0x20, 0x08, 0x02 }; /* I/O Expander values of input relays */
|
||||
int i;
|
||||
|
||||
if (IS_SET(lines, channo)) {
|
||||
newchanno = PHONEDEV(xpd).channels - LINES_DIGI_INP + i;
|
||||
BIT_CLR(lines, channo);
|
||||
BIT_SET(lines, newchanno);
|
||||
/* Stop ringing. No leds for digital inputs. */
|
||||
PHONEDEV(xpd).ringing[newchanno] = 0;
|
||||
if (offhook && !IS_OFFHOOK(xpd, newchanno)) {
|
||||
LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n");
|
||||
hookstate_changed(xpd, newchanno, 1);
|
||||
} else if (!offhook && IS_OFFHOOK(xpd, newchanno)) {
|
||||
LINE_DBG(SIGNAL, xpd, newchanno, "ONHOOK\n");
|
||||
hookstate_changed(xpd, newchanno, 0);
|
||||
}
|
||||
/* Map I/O Expander GPIO into line number */
|
||||
for (i = 0; i < ARRAY_SIZE(input_values_type6); i++) {
|
||||
int chanmask = input_values_type6[i];
|
||||
|
||||
offhook = (REG_FIELD(info, data_low) & chanmask) == 0;
|
||||
notify_digital_input(xpd, i, offhook);
|
||||
}
|
||||
} else {
|
||||
int channo = info->h.portnum;
|
||||
int input_port;
|
||||
offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
|
||||
if (channo < 0 || channo >= ARRAY_SIZE(input_ports_type1)) {
|
||||
XPD_ERR(xpd, "%s: got bad portnum=%d\n", __func__, channo);
|
||||
return;
|
||||
}
|
||||
input_port = input_ports_type1[channo];
|
||||
if (input_port < 0) {
|
||||
XPD_ERR(xpd, "%s: portnum=%d is not input port\n", __func__, channo);
|
||||
return;
|
||||
}
|
||||
notify_digital_input(xpd, input_port, offhook);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1580,42 +1844,87 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct FXS_priv_data *priv;
|
||||
__u8 regnum;
|
||||
bool indirect;
|
||||
__u8 regnum = 0;
|
||||
bool indirect = 0;
|
||||
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
indirect = (REG_FIELD(info, regnum) == 0x1E);
|
||||
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
|
||||
XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||
(indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
|
||||
REG_FIELD(info, data_high));
|
||||
if (!indirect && regnum == REG_DTMF_DECODE) {
|
||||
if (info->h.bytes == REG_CMD_SIZE(REG)) {
|
||||
if ((XPD_HW(xpd).type == 1) && (REG_FIELD(info, regnum) == 0x1E))
|
||||
indirect = 1;
|
||||
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
|
||||
XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||
(indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
|
||||
REG_FIELD(info, data_high));
|
||||
}
|
||||
if (info->h.bytes == REG_CMD_SIZE(RAM)) {
|
||||
uint addr;
|
||||
unsigned long val;
|
||||
XPD_DBG(REGS, xpd, "port=%d, addr_low=0x%X, addr_high=0x%X, data_0=0x%X data_1=0x%X data_2=0x%X data_3=0x%X\n",
|
||||
info->h.portnum,
|
||||
REG_FIELD_RAM(info, addr_low),
|
||||
REG_FIELD_RAM(info, addr_high),
|
||||
REG_FIELD_RAM(info, data_0),
|
||||
REG_FIELD_RAM(info, data_1),
|
||||
REG_FIELD_RAM(info, data_2),
|
||||
REG_FIELD_RAM(info, data_3));
|
||||
addr = (REG_FIELD_RAM(info, addr_high) << 8) | REG_FIELD_RAM(info, addr_low);
|
||||
val = (REG_FIELD_RAM(info, data_3) << 24) |
|
||||
(REG_FIELD_RAM(info, data_2) << 16) |
|
||||
(REG_FIELD_RAM(info, data_1) << 8) |
|
||||
REG_FIELD_RAM(info, data_0);
|
||||
} else if ((XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DTMF_DECODE) ||
|
||||
(XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_TONDTMF)) {
|
||||
__u8 val = REG_FIELD(info, data_low);
|
||||
|
||||
process_dtmf(xpd, info->portnum, val);
|
||||
process_dtmf(xpd, info->h.portnum, val);
|
||||
} else if ((XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LINEFEED)) {
|
||||
__u8 val = REG_FIELD(info, data_low);
|
||||
|
||||
LINE_DBG(SIGNAL, xpd, info->h.portnum,
|
||||
"REG_TYPE6_LINEFEED: dataL=0x%X \n", val);
|
||||
priv->polledhook[info->h.portnum] = val;
|
||||
}
|
||||
#ifdef POLL_DIGITAL_INPUTS
|
||||
/*
|
||||
* Process digital inputs polling results
|
||||
*/
|
||||
else if (!indirect && regnum == REG_DIGITAL_IOCTRL)
|
||||
else if ( (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DIGITAL_IOCTRL) ||
|
||||
(XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_EXP_GPIOB &&
|
||||
REG_FIELD(info, do_expander)))
|
||||
process_digital_inputs(xpd, info);
|
||||
#endif
|
||||
else if (!indirect && regnum == REG_LOOPCLOSURE) { /* OFFHOOK ? */
|
||||
else if (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_LOOPCLOSURE) { /* OFFHOOK ? */
|
||||
__u8 val = REG_FIELD(info, data_low);
|
||||
xpp_line_t mask = BIT(info->portnum);
|
||||
xpp_line_t mask = BIT(info->h.portnum);
|
||||
xpp_line_t offhook;
|
||||
|
||||
/*
|
||||
* Validate reply. Non-existing/disabled ports
|
||||
* will reply with 0xFF. Ignore these.
|
||||
*/
|
||||
if ((val & REG_LOOPCLOSURE_ZERO) == 0) {
|
||||
offhook = (val & REG_LOOPCLOSURE_LCR) ? mask : 0;
|
||||
LINE_DBG(SIGNAL, xpd, info->portnum,
|
||||
"REG_LOOPCLOSURE: dataL=0x%X "
|
||||
if ((val & REG_TYPE1_LOOPCLOSURE_ZERO) == 0) {
|
||||
offhook = (val & REG_TYPE1_LOOPCLOSURE_LCR) ? mask : 0;
|
||||
LINE_DBG(SIGNAL, xpd, info->h.portnum,
|
||||
"REG_TYPE1_LOOPCLOSURE: dataL=0x%X "
|
||||
"(offhook=0x%X mask=0x%X)\n",
|
||||
val, offhook, mask);
|
||||
process_hookstate(xpd, offhook, mask);
|
||||
}
|
||||
} else if (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LCRRTP) { /* OFFHOOK ? */
|
||||
__u8 val = REG_FIELD(info, data_low);
|
||||
xpp_line_t mask = BIT(info->h.portnum);
|
||||
xpp_line_t offhook;
|
||||
|
||||
/*
|
||||
* Validate reply. Non-existing/disabled ports
|
||||
* will reply with 0xFF. Ignore these.
|
||||
*/
|
||||
if ((val & REG_TYPE6_LCRRTP_ZERO) == 0) {
|
||||
offhook = (val & REG_TYPE6_LCRRTP_LCR) ? mask : 0;
|
||||
LINE_DBG(SIGNAL, xpd, info->h.portnum,
|
||||
"REG_TYPE6_LCRRTP: dataL=0x%X "
|
||||
"(offhook=0x%X mask=0x%X)\n",
|
||||
val, offhook, mask);
|
||||
process_hookstate(xpd, offhook, mask);
|
||||
@@ -1792,6 +2101,10 @@ static int proc_fxs_info_show(struct seq_file *sfile, void *not_used)
|
||||
LED_COUNTER(priv, i, led));
|
||||
}
|
||||
}
|
||||
seq_printf(sfile, "\n%-12s", "overheats:");
|
||||
for_each_line(xpd, i) {
|
||||
seq_printf(sfile, "%4d", priv->overheat_reset_counter[i]);
|
||||
}
|
||||
seq_printf(sfile, "\n");
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return 0;
|
||||
@@ -1992,9 +2305,9 @@ static int fxs_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->type != XPD_TYPE_FXS) {
|
||||
if (xpd->xpd_type != XPD_TYPE_FXS) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->type);
|
||||
xpd->xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -2020,7 +2333,7 @@ static int fxs_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver fxs_driver = {
|
||||
.type = XPD_TYPE_FXS,
|
||||
.xpd_type = XPD_TYPE_FXS,
|
||||
.driver = {
|
||||
.name = "fxs",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -2035,7 +2348,6 @@ static int __init card_fxs_startup(void)
|
||||
if ((ret = xpd_driver_register(&fxs_driver.driver)) < 0)
|
||||
return ret;
|
||||
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
#ifdef POLL_DIGITAL_INPUTS
|
||||
INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n",
|
||||
poll_digital_inputs);
|
||||
@@ -2061,7 +2373,6 @@ static void __exit card_fxs_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP FXS Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_FXS);
|
||||
|
||||
module_init(card_fxs_startup);
|
||||
|
||||
@@ -56,12 +56,12 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
* eoftx==1: Start sending us D-channel packets.
|
||||
* eoftx==0: Stop sending us D-channel packets.
|
||||
*/
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
|
||||
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = 0;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->eoframe = eoftx;
|
||||
reg_cmd->h.bytes = 0;
|
||||
reg_cmd->h.is_multibyte = 1;
|
||||
reg_cmd->h.portnum = portno;
|
||||
reg_cmd->h.eoframe = eoftx;
|
||||
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
|
||||
if (debug & DBG_REGS)
|
||||
dump_xframe(__func__, xbus, xframe, debug);
|
||||
@@ -90,13 +90,14 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
int portno;
|
||||
bool writing;
|
||||
int op; /* [W]rite, [R]ead */
|
||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
|
||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */
|
||||
bool do_subreg = 0;
|
||||
int regnum;
|
||||
int subreg;
|
||||
int data_low;
|
||||
bool do_datah;
|
||||
int data_high;
|
||||
bool do_expander = 0;
|
||||
int ret = -EBADR;
|
||||
|
||||
num_args = 2; /* port + operation */
|
||||
@@ -158,6 +159,12 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
num_args++; /* register */
|
||||
//XPD_DBG(REGS, xpd, "DIRECT\n");
|
||||
break;
|
||||
case 'X':
|
||||
do_subreg = 0;
|
||||
do_expander = 1;
|
||||
num_args++; /* register */
|
||||
//XPD_DBG(REGS, xpd, "EXPANDER\n");
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (op != 'W') {
|
||||
@@ -169,6 +176,16 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
num_args--; /* No data low */
|
||||
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
|
||||
break;
|
||||
case 'R':
|
||||
switch (op) {
|
||||
case 'W':
|
||||
num_args += 5; /* add: addr_high, data_[0-3] */
|
||||
break;
|
||||
case 'R':
|
||||
num_args += 2; /* add: addr_low, addr_high */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
|
||||
goto out;
|
||||
@@ -197,6 +214,32 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
addr_mode == 'm');
|
||||
goto out;
|
||||
}
|
||||
if (addr_mode == 'R') {
|
||||
__u8 input[6];
|
||||
int i;
|
||||
|
||||
if (num_args - 2 > 6) {
|
||||
XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2);
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < num_args - 2; i++, argno++) {
|
||||
int hexbyte= parse_hexbyte(argv[argno]);
|
||||
if (hexbyte < 0) {
|
||||
XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
input[i] = hexbyte;
|
||||
}
|
||||
ret = xpp_ram_request(xpd->xbus, xpd, portno, writing,
|
||||
input[0],
|
||||
input[1],
|
||||
input[2],
|
||||
input[3],
|
||||
input[4],
|
||||
input[5],
|
||||
1);
|
||||
goto out;
|
||||
}
|
||||
/* Normal (non-Magic) register commands */
|
||||
do_datah = 0;
|
||||
if (argno >= argc) {
|
||||
@@ -264,17 +307,17 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
#if 0
|
||||
XPD_DBG(REGS, xpd,
|
||||
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
|
||||
"dataL=%d do_datah=%d dataH=%d\n",
|
||||
"dataL=%d do_datah=%d dataH=%d do_expander=%d\n",
|
||||
portno, /* portno */
|
||||
writing, /* writing */
|
||||
regnum, do_subreg, /* use subreg */
|
||||
subreg, /* subreg */
|
||||
data_low, do_datah, /* use data_high */
|
||||
data_high);
|
||||
data_high, do_expander);
|
||||
#endif
|
||||
ret = xpp_register_request(xpd->xbus, xpd, portno,
|
||||
writing, regnum, do_subreg, subreg,
|
||||
data_low, do_datah, data_high, 1);
|
||||
data_low, do_datah, data_high, 1, do_expander);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -362,7 +405,7 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
|
||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||
__u8 data_low, bool do_datah, __u8 data_high,
|
||||
bool should_reply)
|
||||
bool should_reply, bool do_expander)
|
||||
{
|
||||
int ret = 0;
|
||||
xframe_t *xframe;
|
||||
@@ -373,23 +416,22 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
DBG(REGS, "NO XBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
|
||||
xpd->xbus_idx);
|
||||
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx);
|
||||
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
|
||||
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
|
||||
data_low, data_high);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
/* do not count the 'bytes' field */
|
||||
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
|
||||
reg_cmd->is_multibyte = 0;
|
||||
reg_cmd->h.bytes = REG_CMD_SIZE(REG);
|
||||
reg_cmd->h.is_multibyte = 0;
|
||||
if (portno == PORT_BROADCAST) {
|
||||
reg_cmd->portnum = 0;
|
||||
reg_cmd->h.portnum = 0;
|
||||
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
|
||||
} else {
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->h.portnum = portno;
|
||||
REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
|
||||
}
|
||||
reg_cmd->eoframe = 0;
|
||||
reg_cmd->h.eoframe = 0;
|
||||
REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
|
||||
REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
|
||||
REG_FIELD(reg_cmd, do_subreg) = do_subreg;
|
||||
@@ -398,11 +440,12 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
REG_FIELD(reg_cmd, do_datah) = do_datah;
|
||||
REG_FIELD(reg_cmd, data_low) = data_low;
|
||||
REG_FIELD(reg_cmd, data_high) = data_high;
|
||||
REG_FIELD(reg_cmd, do_expander) = do_expander;
|
||||
if (should_reply)
|
||||
xpd->requested_reply = *reg_cmd;
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
|
||||
reg_cmd->portnum, reg_cmd);
|
||||
reg_cmd->h.portnum, reg_cmd);
|
||||
dump_packet("REG_REQ", pack, 1);
|
||||
}
|
||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||
@@ -416,6 +459,67 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_register_request);
|
||||
|
||||
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing,
|
||||
__u8 addr_low,
|
||||
__u8 addr_high,
|
||||
__u8 data_0,
|
||||
__u8 data_1,
|
||||
__u8 data_2,
|
||||
__u8 data_3,
|
||||
bool should_reply)
|
||||
{
|
||||
int ret = 0;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
|
||||
if (!xbus) {
|
||||
DBG(REGS, "NO XBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx);
|
||||
LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n",
|
||||
(writing) ? 'W' : 'R',
|
||||
addr_low, addr_high,
|
||||
data_0, data_1, data_2, data_3);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
/* do not count the 'bytes' field */
|
||||
reg_cmd->h.bytes = REG_CMD_SIZE(RAM);
|
||||
reg_cmd->h.is_multibyte = 0;
|
||||
if (portno == PORT_BROADCAST) {
|
||||
reg_cmd->h.portnum = 0;
|
||||
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1;
|
||||
} else {
|
||||
reg_cmd->h.portnum = portno;
|
||||
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0;
|
||||
}
|
||||
reg_cmd->h.eoframe = 0;
|
||||
REG_FIELD_RAM(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
|
||||
REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1;
|
||||
REG_FIELD_RAM(reg_cmd, do_datah) = 1;
|
||||
REG_FIELD_RAM(reg_cmd, do_subreg) = 1;
|
||||
REG_FIELD_RAM(reg_cmd, addr_low) = addr_low;
|
||||
REG_FIELD_RAM(reg_cmd, addr_high) = addr_high;
|
||||
REG_FIELD_RAM(reg_cmd, data_0) = data_0;
|
||||
REG_FIELD_RAM(reg_cmd, data_1) = data_1;
|
||||
REG_FIELD_RAM(reg_cmd, data_2) = data_2;
|
||||
REG_FIELD_RAM(reg_cmd, data_3) = data_3;
|
||||
if (should_reply)
|
||||
xpd->requested_reply = *reg_cmd;
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit,
|
||||
reg_cmd->h.portnum, reg_cmd);
|
||||
dump_packet("REG_RAM", pack, 1);
|
||||
}
|
||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||
xframe->usec_towait = 1000;
|
||||
}
|
||||
ret = send_cmd_frame(xbus, xframe);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_ram_request);
|
||||
|
||||
/*
|
||||
* The XPD parameter is totaly ignored by the driver and firmware as well.
|
||||
*/
|
||||
@@ -545,21 +649,14 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
}
|
||||
card_desc->magic = CARD_DESC_MAGIC;
|
||||
INIT_LIST_HEAD(&card_desc->card_list);
|
||||
card_desc->type = this_unit->type;
|
||||
card_desc->subtype = this_unit->subtype;
|
||||
card_desc->xpd_addr = this_unit->addr;
|
||||
card_desc->numchips = this_unit->numchips;
|
||||
card_desc->ports_per_chip = this_unit->ports_per_chip;
|
||||
card_desc->port_dir = this_unit->port_dir;
|
||||
card_desc->ports =
|
||||
card_desc->numchips * card_desc->ports_per_chip;
|
||||
card_desc->unit_descriptor = *this_unit;
|
||||
XBUS_INFO(xbus,
|
||||
" CARD %d type=%d.%d ports=%d (%dx%d), "
|
||||
" CARD %d type=%d.%d ports=(%dx%d), "
|
||||
"port-dir=0x%02X\n",
|
||||
card_desc->xpd_addr.unit, card_desc->type,
|
||||
card_desc->subtype, card_desc->ports,
|
||||
card_desc->numchips, card_desc->ports_per_chip,
|
||||
card_desc->port_dir);
|
||||
this_unit->addr.unit, this_unit->type,
|
||||
this_unit->subtype,
|
||||
this_unit->numchips, this_unit->ports_per_chip,
|
||||
this_unit->port_dir);
|
||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||
worker->num_units++;
|
||||
XBUS_COUNTER(xbus, UNITS)++;
|
||||
@@ -591,7 +688,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
||||
return -EPROTO;
|
||||
}
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
|
||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
|
||||
reg);
|
||||
dump_packet("REG_REPLY", pack, 1);
|
||||
}
|
||||
@@ -706,6 +803,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
char xbuslabel[MAX_ENV_STR];
|
||||
char init_card[MAX_PATH_STR];
|
||||
__u8 direction_mask;
|
||||
__u8 hw_type = XPD_HW(xpd).type;
|
||||
int i;
|
||||
char *argv[] = {
|
||||
init_card,
|
||||
@@ -752,8 +850,9 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
|
||||
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
|
||||
xbus->transport.model_string);
|
||||
snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type);
|
||||
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
|
||||
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
|
||||
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type);
|
||||
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
|
||||
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
|
||||
direction_mask);
|
||||
@@ -762,7 +861,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
xbus->connector);
|
||||
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
|
||||
if (snprintf
|
||||
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
|
||||
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type,
|
||||
xbus->revision) > MAX_PATH_STR) {
|
||||
XPD_NOTICE(xpd,
|
||||
"Cannot initialize. pathname is longer "
|
||||
@@ -779,7 +878,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
goto err;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
|
||||
init_card, xpd->type, xbus->revision);
|
||||
init_card, xpd->xpd_type, xbus->revision);
|
||||
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
|
||||
/*
|
||||
* Carefully report results
|
||||
|
||||
@@ -74,9 +74,18 @@ DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
|
||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||
__u8 data_low, bool do_datah, __u8 data_high,
|
||||
bool should_reply);
|
||||
bool should_reply, bool do_expander);
|
||||
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
bool eoftx, __u8 *buf, unsigned len);
|
||||
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing,
|
||||
__u8 addr_low,
|
||||
__u8 addr_high,
|
||||
__u8 data_0,
|
||||
__u8 data_1,
|
||||
__u8 data_2,
|
||||
__u8 data_3,
|
||||
bool should_reply);
|
||||
extern xproto_table_t PROTO_TABLE(GLOBAL);
|
||||
int run_initialize_registers(xpd_t *xpd);
|
||||
int parse_chip_command(xpd_t *xpd, char *cmdline);
|
||||
|
||||
@@ -85,8 +85,6 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig);
|
||||
static void send_idlebits(xpd_t *xpd, bool saveold);
|
||||
static int apply_pri_protocol(xpd_t *xpd);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
|
||||
enum pri_protocol {
|
||||
PRI_PROTO_0 = 0,
|
||||
PRI_PROTO_E1 = 1,
|
||||
@@ -390,7 +388,8 @@ static int query_subunit(xpd_t *xpd, __u8 regnum)
|
||||
0, /* data_L */
|
||||
0, /* do_datah */
|
||||
0, /* data_H */
|
||||
0 /* should_reply */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -406,7 +405,8 @@ static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
|
||||
val, /* data_L */
|
||||
0, /* do_datah */
|
||||
0, /* data_H */
|
||||
0 /* should_reply */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -421,7 +421,8 @@ static int pri_write_reg(xpd_t *xpd, int regnum, __u8 val)
|
||||
val, /* data_L */
|
||||
0, /* do_datah */
|
||||
0, /* data_H */
|
||||
0 /* should_reply */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -707,7 +708,7 @@ static void set_clocking(xpd_t *xpd)
|
||||
/* Now set it */
|
||||
if (best_xpd
|
||||
&& ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) {
|
||||
__u8 reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI };
|
||||
__u8 reg_pc_init[] = { VAL_PC_SYPR, VAL_PC_GPI, VAL_PC_GPI };
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) {
|
||||
__u8 reg_pc = reg_pc_init[i];
|
||||
@@ -1255,21 +1256,29 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
}
|
||||
|
||||
static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
struct PRI_priv_data *priv;
|
||||
int channels = min(31, CHANNELS_PERXPD); /* worst case */
|
||||
|
||||
if (subunit_ports != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
|
||||
if ((unit_descriptor->ports_per_chip < 1) ||
|
||||
(unit_descriptor->ports_per_chip > 4)) {
|
||||
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
|
||||
unit_descriptor->ports_per_chip);
|
||||
return NULL;
|
||||
}
|
||||
if (unit_descriptor->numchips != 1) {
|
||||
XBUS_ERR(xbus, "Bad numchips=%d\n",
|
||||
unit_descriptor->numchips);
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct PRI_priv_data), proto_table, channels);
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct PRI_priv_data), proto_table, unit_descriptor, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
priv = xpd->priv;
|
||||
@@ -1289,7 +1298,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
|
||||
BUG_ON(!xpd);
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
xpd->type = XPD_TYPE_PRI;
|
||||
xpd->xpd_type = XPD_TYPE_PRI;
|
||||
priv = xpd->priv;
|
||||
if (priv->pri_protocol == PRI_PROTO_0) {
|
||||
/*
|
||||
@@ -2255,7 +2264,7 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/* Map UNIT + PORTNUM to XPD */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->portnum;
|
||||
addr.subunit = info->h.portnum;
|
||||
regnum = REG_FIELD(info, regnum);
|
||||
data_low = REG_FIELD(info, data_low);
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
@@ -2269,9 +2278,9 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if (info->is_multibyte) {
|
||||
if (info->h.is_multibyte) {
|
||||
XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
|
||||
info->bytes, info->eoframe);
|
||||
info->h.bytes, info->h.eoframe);
|
||||
goto end;
|
||||
}
|
||||
if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg))
|
||||
@@ -2637,9 +2646,9 @@ static int pri_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->type != XPD_TYPE_PRI) {
|
||||
if (xpd->xpd_type != XPD_TYPE_PRI) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->type);
|
||||
xpd->xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -2722,7 +2731,7 @@ static int pri_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver pri_driver = {
|
||||
.type = XPD_TYPE_PRI,
|
||||
.xpd_type = XPD_TYPE_PRI,
|
||||
.driver = {
|
||||
.name = "pri",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -2736,7 +2745,6 @@ static int __init card_pri_startup(void)
|
||||
|
||||
if ((ret = xpd_driver_register(&pri_driver.driver)) < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
#ifdef DAHDI_AUDIO_NOTIFY
|
||||
INFO("FEATURE: WITH DAHDI_AUDIO_NOTIFY\n");
|
||||
#else
|
||||
@@ -2756,7 +2764,6 @@ static void __exit card_pri_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP PRI Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_PRI);
|
||||
|
||||
module_init(card_pri_startup);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1
drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex
Symbolic link
1
drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex
Symbolic link
@@ -0,0 +1 @@
|
||||
FPGA_1161.201.hex
|
||||
@@ -4,11 +4,12 @@
|
||||
USB_FW = USB_FW.hex USB_FW.201.hex USB_RECOV.hex
|
||||
FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex \
|
||||
FPGA_1161.201.hex FPGA_1161.202.hex
|
||||
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
|
||||
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex \
|
||||
PIC_TYPE_6.hex
|
||||
OCT_FW = $(wildcard OCT6104E-256D.ima)
|
||||
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
|
||||
PROTO_VER = 30
|
||||
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5)
|
||||
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5 6)
|
||||
SCRIPTS = $(SCRIPTS_BASE:%=../%)
|
||||
TARGET = $(DESTDIR)/usr/share/dahdi
|
||||
|
||||
|
||||
460
drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex
Normal file
460
drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex
Normal file
@@ -0,0 +1,460 @@
|
||||
#
|
||||
# $Id: PIC_TYPE_6.hex 11526 2016-04-05 13:30:04Z dima $
|
||||
#
|
||||
:03000000A1CA5042
|
||||
:03000100C41C41DB
|
||||
:0300020069969963
|
||||
:03000300D50D50C8
|
||||
:030004000390392D
|
||||
:0300050067967982
|
||||
:03000600A05A05F8
|
||||
:03000700C40C40E6
|
||||
:030008006996995D
|
||||
:03000900D50D50C2
|
||||
:03000A0003903927
|
||||
:03000B007797796B
|
||||
:03000C00A0BA0B8C
|
||||
:03000D0080080068
|
||||
:03000E00F01F01DF
|
||||
:03000F00022022AA
|
||||
:03001000C05C05CC
|
||||
:0300110002402486
|
||||
:03001200C00C001F
|
||||
:03001300021021B7
|
||||
:030014003613613F
|
||||
:03001500202202A4
|
||||
:03001600E01E01E8
|
||||
:03001700121121A2
|
||||
:030018003223226E
|
||||
:030019002E42E490
|
||||
:03001A00A14A14E4
|
||||
:03001B008008005A
|
||||
:03001C00C0010B15
|
||||
:03001D0019A038EF
|
||||
:03001E00743C57D8
|
||||
:03001F00A24D40AF
|
||||
:03002000C01034D9
|
||||
:030021001CCC42B2
|
||||
:03002200E07D017D
|
||||
:0300230002C021F7
|
||||
:03002400C07C138A
|
||||
:0300250018C024DC
|
||||
:03002600643C0433
|
||||
:03002700A4C0373B
|
||||
:0300280020C201F2
|
||||
:03002900743032FE
|
||||
:03002A00AC3204F1
|
||||
:03002B0021A031E0
|
||||
:03002C0090E2025D
|
||||
:03002D00C20030DE
|
||||
:03002E00D40901F1
|
||||
:03002F00121C00A0
|
||||
:03003000C1E037F5
|
||||
:03003100024C423C
|
||||
:03003200C00021EA
|
||||
:03003300022202A4
|
||||
:03003400201FFF8B
|
||||
:0300350003015074
|
||||
:030036009016B968
|
||||
:0300370020410263
|
||||
:03003800030022A0
|
||||
:03003900901C0414
|
||||
:03003A002020374C
|
||||
:03003B00030201BC
|
||||
:03003C00901032EF
|
||||
:03003D00C11204E9
|
||||
:03003E0019003175
|
||||
:03003F0064320226
|
||||
:03004000A4503099
|
||||
:03004100C22901D0
|
||||
:03004200190C0096
|
||||
:03004300743037DF
|
||||
:03004400A48C0782
|
||||
:03004500209D40BB
|
||||
:0300460012503421
|
||||
:03004700A4B8005A
|
||||
:03004800209214EF
|
||||
:03004900FFFE7047
|
||||
:03004A0016530842
|
||||
:03004B00AC3308CB
|
||||
:03004C0021A308E5
|
||||
:03004D0090E30835
|
||||
:03004E00C20027C6
|
||||
:03004F00D40800D2
|
||||
:03005000121C007F
|
||||
:03005100209039C3
|
||||
:030052001450380F
|
||||
:0300530064303FD7
|
||||
:03005400AC3C07BA
|
||||
:03005500C22D4079
|
||||
:0300560002403431
|
||||
:03005700C00C08D2
|
||||
:030058000220384B
|
||||
:0300590020121959
|
||||
:03005A00030E078B
|
||||
:03005B00901020E2
|
||||
:03005C00204360DE
|
||||
:03005D000303603A
|
||||
:03005E009013609C
|
||||
:03005F00202360FB
|
||||
:03006000030C107E
|
||||
:03006100901038C4
|
||||
:03006200C02219A0
|
||||
:03006300150E0770
|
||||
:03006400643120E4
|
||||
:03006500A69C183E
|
||||
:03006600209038AF
|
||||
:0300670013E21988
|
||||
:03006800A6CE0F12
|
||||
:03006900209022C2
|
||||
:03006A00FFFC0098
|
||||
:03006B0017E03863
|
||||
:03006C0021E2008E
|
||||
:03006D00035E0728
|
||||
:03006E00C13CFF93
|
||||
:03006F000240311B
|
||||
:03007000C00C18A9
|
||||
:03007100022A72EE
|
||||
:0300720020103C1F
|
||||
:0300730003003057
|
||||
:03007400901E0FCC
|
||||
:0300750020403CEC
|
||||
:03007600030C0276
|
||||
:03007700901039AD
|
||||
:03007800202C0039
|
||||
:0300790003003948
|
||||
:03007A00901C0FC8
|
||||
:03007B002100223F
|
||||
:03007C00027C8083
|
||||
:03007D00C3C024D9
|
||||
:03007E00024C0829
|
||||
:03007F00C00104B9
|
||||
:0300800002203922
|
||||
:03008100201C0040
|
||||
:030082000300393F
|
||||
:03008300901C00CE
|
||||
:0300840020403ADF
|
||||
:0300850003002B4A
|
||||
:03008600901020B7
|
||||
:03008700202C0327
|
||||
:0300880003002C46
|
||||
:03008900901C4088
|
||||
:03008A0021003919
|
||||
:03008B0003B7D9DF
|
||||
:03008C00787A8BF4
|
||||
:03008D00A91C406B
|
||||
:03008E0020903986
|
||||
:03008F0013F6D98C
|
||||
:03009000A99A9496
|
||||
:030091002096F9BD
|
||||
:0300920015FBB4A7
|
||||
:03009300643A8F3D
|
||||
:03009400AC367314
|
||||
:030095006BBA9CA7
|
||||
:03009600AC39483A
|
||||
:03009700209207AD
|
||||
:030098001BF90E43
|
||||
:03009900C50C2073
|
||||
:03009A00039121AE
|
||||
:03009B00799AC48B
|
||||
:03009C00A9BC57A5
|
||||
:03009D0020B0345C
|
||||
:03009E00D00C4241
|
||||
:03009F00038021BA
|
||||
:0300A000219C019F
|
||||
:0300A100E07121EA
|
||||
:0300A200348C009B
|
||||
:0300A30034802284
|
||||
:0300A400348C0495
|
||||
:0300A5003480376D
|
||||
:0300A60003020151
|
||||
:0300A70021A03263
|
||||
:0300A8003482158A
|
||||
:0300A9003480316F
|
||||
:0300AA003482029B
|
||||
:0300AB003480306E
|
||||
:0300AC00D0590127
|
||||
:0300AD00031C0031
|
||||
:0300AE00C0003758
|
||||
:0300AF000326D352
|
||||
:0300B000033ADB35
|
||||
:0300B100C70CFF7A
|
||||
:0300B2000391981F
|
||||
:0300B300C5015034
|
||||
:0300B4000391179E
|
||||
:0300B500C3C022A3
|
||||
:0300B600030C42F6
|
||||
:0300B700C0002165
|
||||
:0300B800031C0422
|
||||
:0300B90021B0373C
|
||||
:0300BA000322011D
|
||||
:0300BB00C0003250
|
||||
:0300BC00033215F7
|
||||
:0300BD00C7003148
|
||||
:0300BE00039202A8
|
||||
:0300BF00C5003049
|
||||
:0300C000039901A0
|
||||
:0300C100C40C006C
|
||||
:0300C20003903771
|
||||
:0300C300369ADB8F
|
||||
:0300C400C01C80DD
|
||||
:0300C5001FA6F380
|
||||
:0300C60021C12134
|
||||
:0300C70009A6B3D4
|
||||
:0300C800743B077F
|
||||
:0300C900A1C7D3F9
|
||||
:0300CA0003AAD0B6
|
||||
:0300CB00C02C4006
|
||||
:0300CC00FFF12120
|
||||
:0300CD0016BC005E
|
||||
:0300CE00C020222D
|
||||
:0300CF0023EAD24F
|
||||
:0300D00074321770
|
||||
:0300D10012B02248
|
||||
:0300D20020B20158
|
||||
:0300D30003803077
|
||||
:0300D400C449011B
|
||||
:0300D5000392157E
|
||||
:0300D600C4003033
|
||||
:0300D70003990189
|
||||
:0300D800C0020261
|
||||
:0300D900023030C2
|
||||
:0300DA00A8D901A1
|
||||
:0300DB00ADBC07B2
|
||||
:0300DC00000D40D4
|
||||
:0300DD00000034EC
|
||||
:0300DE000002100D
|
||||
:0300DF00000024FA
|
||||
:0300E0000007D343
|
||||
:0300E100000BAF62
|
||||
:0300E200000C50BF
|
||||
:0300E300000039E1
|
||||
:0300E40000079979
|
||||
:0300E500000AE42A
|
||||
:0300E60000021203
|
||||
:0300E700000030E6
|
||||
:0300E800000214FF
|
||||
:0300E900000031E3
|
||||
:0300EA00000213FE
|
||||
:0300EB00000032E0
|
||||
:0300EC00000C08FD
|
||||
:0300ED00000037D9
|
||||
:0300EE00000218F5
|
||||
:0300EF00000036D8
|
||||
:0300F000000217F4
|
||||
:0300F100000033D9
|
||||
:0300F200000C00FF
|
||||
:0300F300000037D3
|
||||
:0300F400000C708D
|
||||
:0300F500000039CF
|
||||
:0300F600000C50AB
|
||||
:0300F700000039CD
|
||||
:0300F800000215EE
|
||||
:0300F900000030D4
|
||||
:0300FA00000C00F7
|
||||
:0300FB00000031D1
|
||||
:0300FC00000C00F5
|
||||
:0300FD00000033CD
|
||||
:0300FE00000204F9
|
||||
:0300FF00000032CC
|
||||
:03010000000C7080
|
||||
:03010100000039C2
|
||||
:03010200000C509E
|
||||
:03010300000039C0
|
||||
:03010400000C40AC
|
||||
:03010500000039BE
|
||||
:03010600000BAF3C
|
||||
:03010700000C05E4
|
||||
:03010800000024D0
|
||||
:03010900000216DB
|
||||
:03010A00000022D0
|
||||
:03010B00000C07DE
|
||||
:03010C000001628D
|
||||
:03010D00000C08DB
|
||||
:03010E00000122CB
|
||||
:03010F0000036288
|
||||
:03011000000703E2
|
||||
:03011100000B0FD1
|
||||
:03011200000CE0FE
|
||||
:0301130000016286
|
||||
:03011400000201E5
|
||||
:03011500000030B7
|
||||
:03011600000901DC
|
||||
:03011700000204DF
|
||||
:03011800000030B4
|
||||
:03011900000901D9
|
||||
:03011A00000202DE
|
||||
:03011B00000030B1
|
||||
:03011C00000901D6
|
||||
:03011D000007D305
|
||||
:03011E00000B4192
|
||||
:03011F00000C0AC7
|
||||
:03012000000024B8
|
||||
:03012100000215C4
|
||||
:03012200000022B8
|
||||
:03012300000201D6
|
||||
:03012400000030A8
|
||||
:03012500000901CD
|
||||
:03012600000204D0
|
||||
:03012700000030A5
|
||||
:03012800000901CA
|
||||
:03012900000202CF
|
||||
:03012A00000030A2
|
||||
:03012B00000901C7
|
||||
:03012C00000C0ABA
|
||||
:03012D00000027A8
|
||||
:03012E00000C4082
|
||||
:03012F00000121AB
|
||||
:03013000000C04BC
|
||||
:03013100000024A7
|
||||
:03013200000C00BE
|
||||
:03013300000022A7
|
||||
:03013400000201C5
|
||||
:0301350000003097
|
||||
:03013600000901BC
|
||||
:03013700000204BF
|
||||
:0301380000003094
|
||||
:03013900000901B9
|
||||
:03013A00000202BE
|
||||
:03013B0000003091
|
||||
:03013C00000901B6
|
||||
:03013D000002E7D6
|
||||
:03013E00000710A7
|
||||
:03013F00000B4171
|
||||
:03014000000B347D
|
||||
:03014100000C08A7
|
||||
:0301420000003783
|
||||
:03014300000C09A4
|
||||
:0301440000002494
|
||||
:030145000002189D
|
||||
:0301460000002294
|
||||
:03014700000201B2
|
||||
:0301480000003084
|
||||
:03014900000901A9
|
||||
:03014A00000204AC
|
||||
:03014B0000003081
|
||||
:03014C00000901A6
|
||||
:03014D00000202AB
|
||||
:03014E000000307E
|
||||
:03014F00000901A3
|
||||
:030150000002109A
|
||||
:0301510000002784
|
||||
:03015200000C0896
|
||||
:0301530000002485
|
||||
:030154000002178F
|
||||
:0301550000002285
|
||||
:03015600000C009A
|
||||
:030157000000376E
|
||||
:03015800000201A1
|
||||
:0301590000003073
|
||||
:03015A0000090198
|
||||
:03015B000002049B
|
||||
:03015C0000003070
|
||||
:03015D0000090195
|
||||
:03015E000002029A
|
||||
:03015F000000306D
|
||||
:0301600000090192
|
||||
:030161000007D3C1
|
||||
:03016200000B751A
|
||||
:03016300000C503D
|
||||
:030164000000395F
|
||||
:03016500000799F7
|
||||
:03016600000B6526
|
||||
:0301670000021281
|
||||
:0301680000003064
|
||||
:030169000002147D
|
||||
:03016A0000003161
|
||||
:03016B000002137C
|
||||
:03016C000000325E
|
||||
:03016D0000020786
|
||||
:03016E0000003658
|
||||
:03016F000002107B
|
||||
:0301700000003359
|
||||
:03017100000C700F
|
||||
:0301720000003951
|
||||
:03017300000C502D
|
||||
:030174000000394F
|
||||
:03017500000C0774
|
||||
:0301760000002462
|
||||
:030177000002186B
|
||||
:0301780000002262
|
||||
:0301790000020180
|
||||
:03017A0000003052
|
||||
:03017B0000090177
|
||||
:03017C000002047A
|
||||
:03017D000000304F
|
||||
:03017E0000090174
|
||||
:03017F0000020279
|
||||
:030180000000304C
|
||||
:0301810000090171
|
||||
:0301820000021068
|
||||
:0301830000002752
|
||||
:03018400000C0666
|
||||
:0301850000002453
|
||||
:030186000002175D
|
||||
:0301870000002253
|
||||
:0301880000020171
|
||||
:0301890000003043
|
||||
:03018A0000090168
|
||||
:03018B000002046B
|
||||
:03018C0000003040
|
||||
:03018D0000090165
|
||||
:03018E000002026A
|
||||
:03018F000000303D
|
||||
:0301900000090162
|
||||
:030191000007D391
|
||||
:03019200000BA2BD
|
||||
:0301930000021552
|
||||
:0301940000003038
|
||||
:030195000002164F
|
||||
:0301960000003135
|
||||
:030197000002075C
|
||||
:0301980000003331
|
||||
:0301990000021051
|
||||
:03019A0000003230
|
||||
:03019B00000C70E5
|
||||
:03019C0000003927
|
||||
:03019D00000C5003
|
||||
:03019E0000003925
|
||||
:03019F00000C4011
|
||||
:0301A00000003923
|
||||
:0301A100000BAFA1
|
||||
:0301A200000C0A44
|
||||
:0301A30000002435
|
||||
:0301A40000021541
|
||||
:0301A50000002235
|
||||
:0301A60000020153
|
||||
:0301A70000003025
|
||||
:0301A8000009014A
|
||||
:0301A9000002044D
|
||||
:0301AA0000003022
|
||||
:0301AB0000090147
|
||||
:0301AC000002024C
|
||||
:0301AD000000301F
|
||||
:0301AE0000090144
|
||||
:0301AF00000C0041
|
||||
:0301B00000003913
|
||||
:0301B100000C003F
|
||||
:0301B200000C003E
|
||||
:0301B300000A8DB2
|
||||
:0301B400000C0735
|
||||
:0301B50000002F18
|
||||
:0301B600000C0436
|
||||
:0301B70000002223
|
||||
:0301B800000C0038
|
||||
:0301B90000091C1E
|
||||
:0301BA00000C1026
|
||||
:0301BB000000221F
|
||||
:0301BC00000C082C
|
||||
:0301BD0000091C1A
|
||||
:0301BE00000C0032
|
||||
:0301BF0000003A03
|
||||
:0301C000000C012F
|
||||
:0301C10000002912
|
||||
:0301C200000C002E
|
||||
:0301C30000002F0A
|
||||
:0301C400000C200C
|
||||
:0301C50000002314
|
||||
:0301C600000A002C
|
||||
:0301C700000BC763
|
||||
:00000001FF
|
||||
File diff suppressed because it is too large
Load Diff
@@ -94,7 +94,7 @@ if (-t STDERR) {
|
||||
}
|
||||
}
|
||||
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
|
||||
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
|
||||
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/20.}) {
|
||||
$eeprom_release_201 = 1;
|
||||
}
|
||||
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
|
||||
|
||||
1170
drivers/dahdi/xpp/init_card_6_30
Executable file
1170
drivers/dahdi/xpp/init_card_6_30
Executable file
File diff suppressed because it is too large
Load Diff
@@ -103,7 +103,6 @@ void __exit parallel_dbg_cleanup(void)
|
||||
MODULE_DESCRIPTION("Use parallel port to debug drivers");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("$Id:");
|
||||
|
||||
module_init(parallel_dbg_init);
|
||||
module_exit(parallel_dbg_cleanup);
|
||||
|
||||
@@ -244,7 +244,7 @@ int refcount_xbus(xbus_t *xbus)
|
||||
{
|
||||
struct kref *kref = &xbus->kref;
|
||||
|
||||
return atomic_read(&kref->refcount);
|
||||
return refcount_read(&kref->refcount);
|
||||
}
|
||||
|
||||
/*------------------------- Frame Handling ------------------------*/
|
||||
@@ -687,10 +687,56 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
|
||||
__u8 numchips, __u8 ports_per_chip, __u8 ports,
|
||||
__u8 port_dir)
|
||||
static xpd_type_t xpd_hw2xpd_type(const struct unit_descriptor *unit_descriptor)
|
||||
{
|
||||
xpd_type_t xpd_type;
|
||||
|
||||
switch (unit_descriptor->type) {
|
||||
case 1:
|
||||
case 6:
|
||||
xpd_type = XPD_TYPE_FXS;
|
||||
break;
|
||||
case 2:
|
||||
xpd_type = XPD_TYPE_FXO;
|
||||
break;
|
||||
case 3:
|
||||
xpd_type = XPD_TYPE_BRI;
|
||||
break;
|
||||
case 4:
|
||||
xpd_type = XPD_TYPE_PRI;
|
||||
break;
|
||||
case 5:
|
||||
xpd_type = XPD_TYPE_ECHO;
|
||||
break;
|
||||
case 7:
|
||||
xpd_type = XPD_TYPE_NOMODULE;
|
||||
break;
|
||||
default:
|
||||
NOTICE("WARNING: xpd hw type is: %d\n", unit_descriptor->type);
|
||||
xpd_type = XPD_TYPE_NOMODULE;
|
||||
break;
|
||||
}
|
||||
return xpd_type;
|
||||
}
|
||||
|
||||
int subunits_of_xpd(const struct unit_descriptor* unit_descriptor,
|
||||
const xproto_table_t *proto_table) {
|
||||
int ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
|
||||
|
||||
return
|
||||
(ports + proto_table->ports_per_subunit - 1)
|
||||
/ proto_table->ports_per_subunit;
|
||||
}
|
||||
|
||||
static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
|
||||
{
|
||||
int unit = unit_descriptor->addr.unit;
|
||||
xpd_type_t xpd_type;
|
||||
__u8 hw_type;
|
||||
__u8 numchips;
|
||||
__u8 ports_per_chip;
|
||||
__u8 ports;
|
||||
__u8 port_dir;
|
||||
const xproto_table_t *proto_table;
|
||||
int i;
|
||||
int subunits;
|
||||
@@ -698,12 +744,19 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
|
||||
int remaining_ports;
|
||||
const struct echoops *echoops;
|
||||
|
||||
proto_table = xproto_get(type);
|
||||
/* Translate parameters from "unit_descriptor" */
|
||||
hw_type = unit_descriptor->type;
|
||||
numchips = unit_descriptor->numchips;
|
||||
ports_per_chip = unit_descriptor->ports_per_chip;
|
||||
port_dir = unit_descriptor->port_dir;
|
||||
ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
|
||||
xpd_type = xpd_hw2xpd_type(unit_descriptor);
|
||||
proto_table = xproto_get(xpd_type);
|
||||
if (!proto_table) {
|
||||
XBUS_NOTICE(xbus,
|
||||
"CARD %d: missing protocol table for type %d. "
|
||||
"CARD %d: missing protocol table for xpd_type %d. "
|
||||
"Ignored.\n",
|
||||
unit, type);
|
||||
unit, xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
echoops = proto_table->echoops;
|
||||
@@ -711,26 +764,24 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
|
||||
XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit);
|
||||
if (ECHOOPS(xbus)) {
|
||||
XBUS_NOTICE(xbus,
|
||||
"CARD %d: tryies to define echoops (type %d) "
|
||||
"CARD %d: tryies to define echoops (xpd_type %d) "
|
||||
"but we already have one. Ignored.\n",
|
||||
unit, type);
|
||||
unit, xpd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
xbus->echo_state.echoops = echoops;
|
||||
xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
|
||||
}
|
||||
remaining_ports = ports;
|
||||
subunits =
|
||||
(ports + proto_table->ports_per_subunit -
|
||||
1) / proto_table->ports_per_subunit;
|
||||
subunits = subunits_of_xpd(unit_descriptor, proto_table);
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"CARD %d type=%d.%d ports=%d (%dx%d), "
|
||||
"CARD %d xpd_type=%d/hw_type=%d ports=%d (%dx%d), "
|
||||
"%d subunits, port-dir=0x%02X\n",
|
||||
unit, type, subtype, ports, numchips, ports_per_chip, subunits,
|
||||
unit, xpd_type, hw_type, ports, numchips, ports_per_chip, subunits,
|
||||
port_dir);
|
||||
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
|
||||
if (xpd_type == XPD_TYPE_PRI || xpd_type == XPD_TYPE_BRI)
|
||||
xbus->quirks.has_digital_span = 1;
|
||||
if (type == XPD_TYPE_FXO)
|
||||
if (xpd_type == XPD_TYPE_FXO)
|
||||
xbus->quirks.has_fxo = 1;
|
||||
xbus->worker.num_units += subunits - 1;
|
||||
for (i = 0; i < subunits; i++) {
|
||||
@@ -754,11 +805,10 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
|
||||
goto out;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"Creating XPD=%d%d type=%d.%d (%d ports)\n", unit, i,
|
||||
type, subtype, subunit_ports);
|
||||
"Creating XPD=%d%d xpd_type=%d.%d hw_type=%d (%d ports)\n", unit, i,
|
||||
xpd_type, unit_descriptor->subtype, hw_type, subunit_ports);
|
||||
ret =
|
||||
create_xpd(xbus, proto_table, unit, i, type, subtype,
|
||||
subunits, subunit_ports, port_dir);
|
||||
create_xpd(xbus, proto_table, unit_descriptor, unit, i, xpd_type);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit,
|
||||
i, ret);
|
||||
@@ -1130,11 +1180,7 @@ void xbus_populate(void *data)
|
||||
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
|
||||
/* Release/Reacquire locks around blocking calls */
|
||||
spin_unlock_irqrestore(&xbus->worker.worker_lock, flags);
|
||||
ret =
|
||||
new_card(xbus, card_desc->xpd_addr.unit, card_desc->type,
|
||||
card_desc->subtype, card_desc->numchips,
|
||||
card_desc->ports_per_chip, card_desc->ports,
|
||||
card_desc->port_dir);
|
||||
ret = new_card(xbus, &card_desc->unit_descriptor);
|
||||
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
|
||||
KZFREE(card_desc);
|
||||
if (ret)
|
||||
@@ -1566,7 +1612,6 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
|
||||
transport_init(xbus, ops, max_send_size, transport_device, priv);
|
||||
spin_lock_init(&xbus->lock);
|
||||
init_waitqueue_head(&xbus->command_queue_empty);
|
||||
init_timer(&xbus->command_timer);
|
||||
atomic_set(&xbus->pcm_rx_counter, 0);
|
||||
xbus->min_tx_sync = INT_MAX;
|
||||
xbus->min_rx_sync = INT_MAX;
|
||||
|
||||
@@ -338,6 +338,8 @@ int waitfor_xpds(xbus_t *xbus, char *buf);
|
||||
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
|
||||
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
|
||||
|
||||
int subunits_of_xpd(const struct unit_descriptor* unit_descriptor,
|
||||
const xproto_table_t *proto_table);
|
||||
/* sysfs */
|
||||
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
|
||||
void xpd_device_unregister(xpd_t *xpd);
|
||||
|
||||
@@ -353,9 +353,9 @@ static void xpp_set_syncer(xbus_t *xbus, bool on)
|
||||
(syncer) ? syncer->busname : "NO-SYNC");
|
||||
}
|
||||
|
||||
static void xbus_command_timer(unsigned long param)
|
||||
static void xbus_command_timer(TIMER_DATA_TYPE timer)
|
||||
{
|
||||
xbus_t *xbus = (xbus_t *)param;
|
||||
xbus_t *xbus = from_timer(xbus, timer, command_timer);
|
||||
struct timeval now;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
@@ -371,10 +371,9 @@ void xbus_set_command_timer(xbus_t *xbus, bool on)
|
||||
if (on) {
|
||||
if (!timer_pending(&xbus->command_timer)) {
|
||||
XBUS_DBG(SYNC, xbus, "add_timer\n");
|
||||
xbus->command_timer.function = xbus_command_timer;
|
||||
xbus->command_timer.data = (unsigned long)xbus;
|
||||
xbus->command_timer.expires = jiffies + 1;
|
||||
add_timer(&xbus->command_timer);
|
||||
timer_setup(&xbus->command_timer,
|
||||
xbus_command_timer, 0);
|
||||
mod_timer(&xbus->command_timer, jiffies + 1);
|
||||
}
|
||||
} else if (timer_pending(&xbus->command_timer)) {
|
||||
XBUS_DBG(SYNC, xbus, "del_timer\n");
|
||||
|
||||
@@ -339,6 +339,7 @@ static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute xbus_dev_attrs[] = {
|
||||
__ATTR_RO(connector),
|
||||
__ATTR_RO(label),
|
||||
@@ -358,6 +359,39 @@ static struct device_attribute xbus_dev_attrs[] = {
|
||||
dahdi_registration_store),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(connector);
|
||||
static DEVICE_ATTR_RO(label);
|
||||
static DEVICE_ATTR_RO(status);
|
||||
static DEVICE_ATTR_RO(timing);
|
||||
static DEVICE_ATTR_RO(refcount_xbus);
|
||||
static DEVICE_ATTR_RO(waitfor_xpds);
|
||||
static DEVICE_ATTR_RO(driftinfo);
|
||||
static DEVICE_ATTR_WO(cls);
|
||||
static DEVICE_ATTR_RW(xbus_state);
|
||||
#ifdef SAMPLE_TICKS
|
||||
static DEVICE_ATTR_RO(samples);
|
||||
#endif
|
||||
static DEVICE_ATTR_RW(dahdi_registration);
|
||||
|
||||
static struct attribute *xbus_dev_attrs[] = {
|
||||
&dev_attr_connector.attr,
|
||||
&dev_attr_label.attr,
|
||||
&dev_attr_status.attr,
|
||||
&dev_attr_timing.attr,
|
||||
&dev_attr_refcount_xbus.attr,
|
||||
&dev_attr_waitfor_xpds.attr,
|
||||
&dev_attr_driftinfo.attr,
|
||||
&dev_attr_cls.attr,
|
||||
&dev_attr_xbus_state.attr,
|
||||
#ifdef SAMPLE_TICKS
|
||||
&dev_attr_samples.attr,
|
||||
#endif
|
||||
&dev_attr_dahdi_registration.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xbus_dev);
|
||||
#endif
|
||||
|
||||
static int astribank_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
@@ -457,7 +491,11 @@ static struct bus_type toplevel_bus_type = {
|
||||
.name = "astribanks",
|
||||
.match = astribank_match,
|
||||
.uevent = astribank_uevent,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = xbus_dev_attrs,
|
||||
#else
|
||||
.dev_groups = xbus_dev_groups,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
.drv_attrs = xpp_attrs,
|
||||
#else
|
||||
@@ -518,13 +556,25 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||
REG_FIELD(regs, data_high));
|
||||
} else
|
||||
datah_str[0] = '\0';
|
||||
if (REG_FIELD(regs, do_subreg)) {
|
||||
if (regs->h.bytes == REG_CMD_SIZE(RAM)) {
|
||||
len +=
|
||||
sprintf(buf + len, "#CH\tOP\tAL\tAH\tD0\tD1\tD2\tD3\n");
|
||||
len +=
|
||||
sprintf(buf + len, "%2d\tRR\t%02X\t%02X\t%02X\t%02X\t%02X\t%02X\n",
|
||||
regs->h.portnum,
|
||||
REG_FIELD_RAM(regs, addr_low),
|
||||
REG_FIELD_RAM(regs, addr_high),
|
||||
REG_FIELD_RAM(regs, data_0),
|
||||
REG_FIELD_RAM(regs, data_1),
|
||||
REG_FIELD_RAM(regs, data_2),
|
||||
REG_FIELD_RAM(regs, data_3));
|
||||
} else if (REG_FIELD(regs, do_subreg)) {
|
||||
len +=
|
||||
sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
|
||||
(do_datah) ? "\tDH" : "");
|
||||
len +=
|
||||
sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
|
||||
regs->portnum, REG_FIELD(regs, regnum),
|
||||
regs->h.portnum, REG_FIELD(regs, regnum),
|
||||
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
|
||||
datah_str);
|
||||
} else {
|
||||
@@ -532,7 +582,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
||||
(do_datah) ? "\tDH" : "");
|
||||
len +=
|
||||
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
|
||||
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->h.portnum,
|
||||
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
|
||||
datah_str);
|
||||
}
|
||||
@@ -676,6 +726,19 @@ static DEVICE_ATTR_READER(type_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(hwid_show, dev, buf)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
int len = 0;
|
||||
|
||||
BUG_ON(!dev);
|
||||
xpd = dev_to_xpd(dev);
|
||||
if (!xpd)
|
||||
return -ENODEV;
|
||||
len += sprintf(buf, "%d.%d\n", XPD_HW(xpd).type, XPD_HW(xpd).subtype);
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(offhook_show, dev, buf)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
@@ -731,34 +794,63 @@ static int xpd_match(struct device *dev, struct device_driver *driver)
|
||||
|
||||
xpd_driver = driver_to_xpd_driver(driver);
|
||||
xpd = dev_to_xpd(dev);
|
||||
if (xpd_driver->type != xpd->type) {
|
||||
if (xpd_driver->xpd_type != xpd->xpd_type) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"SYSFS match fail: xpd->type = %d, "
|
||||
"xpd_driver->type = %d\n",
|
||||
xpd->type, xpd_driver->type);
|
||||
"SYSFS match fail: xpd->xpd_type = %d, "
|
||||
"xpd_driver->xpd_type = %d\n",
|
||||
xpd->xpd_type, xpd_driver->xpd_type);
|
||||
return 0;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
|
||||
xpd->type, dev_name(dev), driver->name);
|
||||
"SYSFS MATCH: xpd_type=%d dev->bus_id = %s, driver->name = %s\n",
|
||||
xpd->xpd_type, dev_name(dev), driver->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute xpd_dev_attrs[] = {
|
||||
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
|
||||
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
|
||||
__ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
|
||||
__ATTR_RO(type),
|
||||
__ATTR_RO(hwid),
|
||||
__ATTR_RO(offhook),
|
||||
__ATTR_RO(timing_priority),
|
||||
__ATTR_RO(refcount_xpd),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RW(chipregs);
|
||||
static DEVICE_ATTR_RW(blink);
|
||||
static DEVICE_ATTR_RW(span);
|
||||
static DEVICE_ATTR_RO(type);
|
||||
static DEVICE_ATTR_RO(hwid);
|
||||
static DEVICE_ATTR_RO(offhook);
|
||||
static DEVICE_ATTR_RO(timing_priority);
|
||||
static DEVICE_ATTR_RO(refcount_xpd);
|
||||
|
||||
static struct attribute *xpd_dev_attrs[] = {
|
||||
&dev_attr_chipregs.attr,
|
||||
&dev_attr_blink.attr,
|
||||
&dev_attr_span.attr,
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_hwid.attr,
|
||||
&dev_attr_offhook.attr,
|
||||
&dev_attr_timing_priority.attr,
|
||||
&dev_attr_refcount_xpd.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xpd_dev);
|
||||
#endif
|
||||
|
||||
static struct bus_type xpd_type = {
|
||||
.name = "xpds",
|
||||
.match = xpd_match,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = xpd_dev_attrs,
|
||||
#else
|
||||
.dev_groups = xpd_dev_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
int xpd_driver_register(struct device_driver *driver)
|
||||
@@ -974,7 +1066,7 @@ void xbus_sysfs_remove(xbus_t *xbus)
|
||||
return;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n",
|
||||
atomic_read(&astribank->kobj.kref.refcount));
|
||||
refcount_read(&astribank->kobj.kref.refcount));
|
||||
BUG_ON(dev_get_drvdata(astribank) != xbus);
|
||||
device_unregister(astribank);
|
||||
dev_set_drvdata(astribank, NULL);
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xpp_version.h"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -78,14 +78,7 @@
|
||||
struct card_desc_struct {
|
||||
struct list_head card_list;
|
||||
u32 magic;
|
||||
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
|
||||
__u8 subtype;
|
||||
struct xpd_addr xpd_addr;
|
||||
__u8 numchips;
|
||||
__u8 ports_per_chip;
|
||||
__u8 ports;
|
||||
__u8 port_dir;
|
||||
struct xpd_addr ec_addr; /* echo canceler address */
|
||||
struct unit_descriptor unit_descriptor;
|
||||
};
|
||||
|
||||
typedef enum xpd_direction {
|
||||
@@ -174,11 +167,12 @@ struct phonedev {
|
||||
struct xpd {
|
||||
char xpdname[XPD_NAMELEN];
|
||||
struct phonedev phonedev;
|
||||
struct unit_descriptor unit_descriptor;
|
||||
#define XPD_HW(xpd) ((xpd)->unit_descriptor)
|
||||
|
||||
const struct xops *xops;
|
||||
xpd_type_t type;
|
||||
xpd_type_t xpd_type;
|
||||
const char *type_name;
|
||||
__u8 subtype;
|
||||
int subunits; /* all siblings */
|
||||
enum xpd_state xpd_state;
|
||||
struct device xpd_dev;
|
||||
@@ -217,7 +211,7 @@ struct xpd {
|
||||
|
||||
#define for_each_line(xpd, i) \
|
||||
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
||||
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
|
||||
#define IS_BRI(xpd) ((xpd)->xpd_type == XPD_TYPE_BRI)
|
||||
#define TICK_TOLERANCE 500 /* usec */
|
||||
|
||||
#ifdef DEBUG_SYNC_PARPORT
|
||||
@@ -237,7 +231,7 @@ static inline void *my_kzalloc(size_t size, gfp_t flags)
|
||||
}
|
||||
|
||||
struct xpd_driver {
|
||||
xpd_type_t type;
|
||||
xpd_type_t xpd_type;
|
||||
|
||||
struct device_driver driver;
|
||||
#define driver_to_xpd_driver(driver) \
|
||||
|
||||
@@ -124,7 +124,7 @@ int refcount_xpd(xpd_t *xpd)
|
||||
{
|
||||
struct kref *kref = &xpd->kref;
|
||||
|
||||
return atomic_read(&kref->refcount);
|
||||
return refcount_read(&kref->refcount);
|
||||
}
|
||||
|
||||
xpd_t *get_xpd(const char *msg, xpd_t *xpd)
|
||||
@@ -216,33 +216,43 @@ EXPORT_SYMBOL(xpd_free);
|
||||
* Synchronous part of XPD detection.
|
||||
* Called from new_card()
|
||||
*/
|
||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
|
||||
int subunit, __u8 type, __u8 subtype, int subunits,
|
||||
int subunit_ports, __u8 port_dir)
|
||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
int unit,
|
||||
int subunit, __u8 type)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
bool to_phone;
|
||||
|
||||
BUG_ON(type == XPD_TYPE_NOMODULE);
|
||||
to_phone = BIT(subunit) & port_dir;
|
||||
to_phone = BIT(subunit) & unit_descriptor->port_dir;
|
||||
BUG_ON(!xbus);
|
||||
xpd = xpd_byaddr(xbus, unit, subunit);
|
||||
if (xpd) {
|
||||
XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit);
|
||||
return 0;
|
||||
}
|
||||
if (subunit_ports <= 0 || subunit_ports > CHANNELS_PERXPD) {
|
||||
INFO("%s: [%d.%d] type=%d subtype=%d numchips=%d ports_per_chip=%d ports_dir=%d\n",
|
||||
__func__,
|
||||
unit_descriptor->addr.unit,
|
||||
unit_descriptor->addr.subunit,
|
||||
unit_descriptor->type,
|
||||
unit_descriptor->subtype,
|
||||
unit_descriptor->numchips,
|
||||
unit_descriptor->ports_per_chip,
|
||||
unit_descriptor->port_dir);
|
||||
if (unit_descriptor->ports_per_chip <= 0 || unit_descriptor->ports_per_chip > CHANNELS_PERXPD) {
|
||||
XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n",
|
||||
subunit_ports, unit, subunit);
|
||||
unit_descriptor->ports_per_chip, unit, subunit);
|
||||
return 0;
|
||||
}
|
||||
xpd =
|
||||
proto_table->xops->card_new(xbus, unit, subunit, proto_table,
|
||||
subtype, subunits, subunit_ports,
|
||||
unit_descriptor,
|
||||
to_phone);
|
||||
if (!xpd) {
|
||||
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
|
||||
unit, subunit, proto_table->type, subtype,
|
||||
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d) failed. Ignored.\n",
|
||||
unit, subunit, proto_table->type,
|
||||
to_phone);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -279,7 +289,8 @@ static int xpd_read_proc_show(struct seq_file *sfile, void *data)
|
||||
seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit,
|
||||
xpd->addr.subunit);
|
||||
seq_printf(sfile, "Subunits: %d\n", xpd->subunits);
|
||||
seq_printf(sfile, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
|
||||
seq_printf(sfile, "Type: %d.%d\n", xpd->xpd_type, XPD_HW(xpd).subtype);
|
||||
seq_printf(sfile, "Hardware type: %d.%d\nn", XPD_HW(xpd).type, XPD_HW(xpd).subtype);
|
||||
seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
|
||||
seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n",
|
||||
PHONEDEV(xpd).wanted_pcm_mask);
|
||||
@@ -529,8 +540,10 @@ err:
|
||||
*
|
||||
*/
|
||||
__must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
|
||||
int subtype, int subunits, size_t privsize,
|
||||
const xproto_table_t *proto_table, int channels)
|
||||
size_t privsize,
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
int channels)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
size_t alloc_size = sizeof(xpd_t) + privsize;
|
||||
@@ -554,12 +567,12 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
|
||||
xpd->priv = (__u8 *)xpd + sizeof(xpd_t);
|
||||
spin_lock_init(&xpd->lock);
|
||||
xpd->card_present = 0;
|
||||
xpd->type = proto_table->type;
|
||||
xpd->xpd_type = proto_table->type;
|
||||
xpd->xproto = proto_table;
|
||||
xpd->unit_descriptor = *unit_descriptor;
|
||||
xpd->xops = proto_table->xops;
|
||||
xpd->xpd_state = XPD_STATE_START;
|
||||
xpd->subtype = subtype;
|
||||
xpd->subunits = subunits;
|
||||
xpd->subunits = subunits_of_xpd(unit_descriptor, proto_table);
|
||||
kref_init(&xpd->kref);
|
||||
|
||||
/* For USB-1 disable some channels */
|
||||
@@ -949,13 +962,13 @@ const char *xpp_echocan_name(const struct dahdi_chan *chan)
|
||||
* quirks and limitations
|
||||
*/
|
||||
if (xbus->quirks.has_fxo) {
|
||||
if (xbus->quirks.has_digital_span && xpd->type == XPD_TYPE_FXO) {
|
||||
if (xbus->quirks.has_digital_span && xpd->xpd_type == XPD_TYPE_FXO) {
|
||||
LINE_NOTICE(xpd, pos,
|
||||
"quirk: give up HWEC on FXO: "
|
||||
"AB has digital span\n");
|
||||
return NULL;
|
||||
} else if (xbus->sync_mode != SYNC_MODE_AB
|
||||
&& xpd->type == XPD_TYPE_FXS) {
|
||||
&& xpd->xpd_type == XPD_TYPE_FXS) {
|
||||
LINE_NOTICE(xpd, pos,
|
||||
"quirk: give up HWEC on FXS: "
|
||||
"AB has FXO and is sync slave\n");
|
||||
@@ -1007,6 +1020,8 @@ void xpp_span_assigned(struct dahdi_span *span)
|
||||
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
|
||||
dahdi_alarm_notify(&phonedev->span);
|
||||
}
|
||||
if (PHONE_METHOD(span_assigned, xpd))
|
||||
CALL_PHONE_METHOD(span_assigned, xpd);
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_span_assigned);
|
||||
|
||||
@@ -1183,8 +1198,7 @@ static int __init xpp_dahdi_init(void)
|
||||
int ret = 0;
|
||||
void *top = NULL;
|
||||
|
||||
INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION, MAX_XPDS,
|
||||
MAX_UNIT, MAX_SUBUNIT);
|
||||
INFO("MAX_XPDS=%d (%d*%d)\n", MAX_XPDS, MAX_UNIT, MAX_SUBUNIT);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
|
||||
if (!xpp_proc_toplevel) {
|
||||
@@ -1220,7 +1234,6 @@ static void __exit xpp_dahdi_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP Dahdi Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
|
||||
module_init(xpp_dahdi_init);
|
||||
module_exit(xpp_dahdi_cleanup);
|
||||
|
||||
@@ -30,11 +30,13 @@ int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
|
||||
int xpd_dahdi_postregister(xpd_t *xpd);
|
||||
void xpd_dahdi_preunregister(xpd_t *xpd);
|
||||
void xpd_dahdi_postunregister(xpd_t *xpd);
|
||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
|
||||
int subunit, __u8 type, __u8 subtype, int subunits,
|
||||
int subunit_ports, __u8 port_dir);
|
||||
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
|
||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
int unit,
|
||||
int subunit, __u8 type);
|
||||
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
|
||||
size_t privsize, const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
int channels);
|
||||
void xpd_free(xpd_t *xpd);
|
||||
void xpd_remove(xpd_t *xpd);
|
||||
|
||||
@@ -49,7 +49,9 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||
static DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces");
|
||||
static DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)");
|
||||
static DEF_PARM(uint, drop_pcm_after, 6, 0644,
|
||||
"Number of consecutive tx_sluggish to drop a PCM frame");
|
||||
"Number of consecutive tx_sluggish to start dropping PCM");
|
||||
static DEF_PARM(uint, sluggish_pcm_keepalive, 50, 0644,
|
||||
"During sluggish -- Keep-alive PCM (1 every #)");
|
||||
|
||||
#include "dahdi_debug.h"
|
||||
|
||||
@@ -117,6 +119,8 @@ enum {
|
||||
XUSB_N_TX_FRAMES,
|
||||
XUSB_N_RX_ERRORS,
|
||||
XUSB_N_TX_ERRORS,
|
||||
XUSB_N_RX_DROPS,
|
||||
XUSB_N_TX_DROPS,
|
||||
XUSB_N_RCV_ZERO_LEN,
|
||||
};
|
||||
|
||||
@@ -127,8 +131,14 @@ enum {
|
||||
static struct xusb_counters {
|
||||
char *name;
|
||||
} xusb_counters[] = {
|
||||
C_(RX_FRAMES), C_(TX_FRAMES), C_(RX_ERRORS), C_(TX_ERRORS),
|
||||
C_(RCV_ZERO_LEN),};
|
||||
C_(RX_FRAMES),
|
||||
C_(TX_FRAMES),
|
||||
C_(RX_ERRORS),
|
||||
C_(TX_ERRORS),
|
||||
C_(RX_DROPS),
|
||||
C_(TX_DROPS),
|
||||
C_(RCV_ZERO_LEN),
|
||||
};
|
||||
|
||||
#undef C_
|
||||
|
||||
@@ -194,8 +204,7 @@ struct xusb {
|
||||
unsigned int max_tx_delay;
|
||||
uint usb_tx_delay[NUM_BUCKETS];
|
||||
uint sluggish_debounce;
|
||||
bool drop_next_pcm; /* due to sluggishness */
|
||||
atomic_t pcm_tx_drops;
|
||||
bool drop_pcm; /* due to sluggishness */
|
||||
atomic_t usb_sluggish_count;
|
||||
|
||||
const char *manufacturer;
|
||||
@@ -400,12 +409,23 @@ static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe)
|
||||
BUG_ON(!xframe);
|
||||
xusb = xusb_of(xbus);
|
||||
BUG_ON(!xusb);
|
||||
if (xusb->drop_next_pcm) {
|
||||
FREE_SEND_XFRAME(xbus, xframe); /* return to pool */
|
||||
xusb->drop_next_pcm = 0;
|
||||
return -EIO;
|
||||
if (xusb->drop_pcm) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1000) == 0)
|
||||
XUSB_ERR(xusb, "Sluggish USB: drop tx-pcm (%d)\n",
|
||||
rate_limit);
|
||||
/* Let trickle of TX-PCM, so Astribank will not reset */
|
||||
if (sluggish_pcm_keepalive &&
|
||||
((rate_limit % sluggish_pcm_keepalive) != 0)) {
|
||||
XUSB_COUNTER(xusb, TX_DROPS)++;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return do_send_xframe(xbus, xframe);
|
||||
err:
|
||||
FREE_SEND_XFRAME(xbus, xframe); /* return to pool */
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -674,7 +694,6 @@ static int xusb_probe(struct usb_interface *interface,
|
||||
sema_init(&xusb->sem, 1);
|
||||
atomic_set(&xusb->pending_writes, 0);
|
||||
atomic_set(&xusb->pending_reads, 0);
|
||||
atomic_set(&xusb->pcm_tx_drops, 0);
|
||||
atomic_set(&xusb->usb_sluggish_count, 0);
|
||||
xusb->udev = udev;
|
||||
xusb->interface = interface;
|
||||
@@ -871,6 +890,8 @@ static void xpp_send_callback(USB_PASS_CB(urb))
|
||||
do_gettimeofday(&now);
|
||||
xusb->last_tx = xframe->tv_submitted;
|
||||
usec = usec_diff(&now, &xframe->tv_submitted);
|
||||
if (usec < 0)
|
||||
usec = 0; /* System clock jumped */
|
||||
if (usec > xusb->max_tx_delay)
|
||||
xusb->max_tx_delay = usec;
|
||||
i = usec / USEC_BUCKET;
|
||||
@@ -878,7 +899,6 @@ static void xpp_send_callback(USB_PASS_CB(urb))
|
||||
i = NUM_BUCKETS - 1;
|
||||
xusb->usb_tx_delay[i]++;
|
||||
if (unlikely(usec > tx_sluggish)) {
|
||||
atomic_inc(&xusb->usb_sluggish_count);
|
||||
if (xusb->sluggish_debounce++ > drop_pcm_after) {
|
||||
static int rate_limit;
|
||||
|
||||
@@ -888,12 +908,14 @@ static void xpp_send_callback(USB_PASS_CB(urb))
|
||||
"Sluggish USB. Dropping next PCM frame "
|
||||
"(pending_writes=%d)\n",
|
||||
writes);
|
||||
atomic_inc(&xusb->pcm_tx_drops);
|
||||
xusb->drop_next_pcm = 1;
|
||||
atomic_inc(&xusb->usb_sluggish_count);
|
||||
xusb->drop_pcm = 1;
|
||||
xusb->sluggish_debounce = 0;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
xusb->sluggish_debounce = 0;
|
||||
xusb->drop_pcm = 0;
|
||||
}
|
||||
/* sync/async unlink faults aren't errors */
|
||||
if (urb->status
|
||||
&& !(urb->status == -ENOENT || urb->status == -ECONNRESET)) {
|
||||
@@ -956,6 +978,26 @@ static void xpp_receive_callback(USB_PASS_CB(urb))
|
||||
// if (debug)
|
||||
// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe, debug);
|
||||
XUSB_COUNTER(xusb, RX_FRAMES)++;
|
||||
if (xusb->drop_pcm) {
|
||||
/* some protocol analysis */
|
||||
static int rate_limit;
|
||||
xpacket_t *pack = (xpacket_t *)(xframe->packets);
|
||||
bool is_pcm = XPACKET_IS_PCM(pack);
|
||||
|
||||
if (is_pcm) {
|
||||
if ((rate_limit++ % 1000) == 0)
|
||||
XUSB_ERR(xusb,
|
||||
"Sluggish USB: drop rx-pcm (%d)\n",
|
||||
rate_limit);
|
||||
/* Let trickle of RX-PCM, so Astribank will not reset */
|
||||
if (sluggish_pcm_keepalive &&
|
||||
((rate_limit % sluggish_pcm_keepalive)
|
||||
!= 0)) {
|
||||
XUSB_COUNTER(xusb, RX_DROPS)++;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Send UP */
|
||||
xbus_receive_xframe(xbus, xframe);
|
||||
end:
|
||||
@@ -982,7 +1024,6 @@ static int __init xpp_usb_init(void)
|
||||
int ret;
|
||||
//xusb_t *xusb;
|
||||
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
xusb_cache =
|
||||
kmem_cache_create("xusb_cache", sizeof(xframe_t) + XFRAME_DATASIZE,
|
||||
#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22)) && defined(CONFIG_SLUB)
|
||||
@@ -1061,17 +1102,16 @@ static int xusb_read_proc_show(struct seq_file *sfile, void *data)
|
||||
stamp_last_pcm_read, accumulate_diff);
|
||||
#endif
|
||||
memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay));
|
||||
seq_printf(sfile, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
|
||||
BUCKET_START, NUM_BUCKETS);
|
||||
seq_printf(sfile, "usb_tx_delay[%dus - %dus]: ",
|
||||
USEC_BUCKET * BUCKET_START,
|
||||
USEC_BUCKET * NUM_BUCKETS);
|
||||
for (i = BUCKET_START; i < NUM_BUCKETS; i++) {
|
||||
seq_printf(sfile, "%6d ", usb_tx_delay[i]);
|
||||
if (i == mark_limit)
|
||||
seq_printf(sfile, "| ");
|
||||
}
|
||||
seq_printf(sfile, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
|
||||
atomic_read(&xusb->pcm_tx_drops),
|
||||
atomic_read(&xusb->usb_sluggish_count)
|
||||
);
|
||||
seq_printf(sfile, "\nSluggish events: %d\n",
|
||||
atomic_read(&xusb->usb_sluggish_count));
|
||||
seq_printf(sfile, "\nCOUNTERS:\n");
|
||||
for (i = 0; i < XUSB_COUNTER_MAX; i++) {
|
||||
seq_printf(sfile, "\t%-15s = %d\n", xusb_counters[i].name,
|
||||
@@ -1103,7 +1143,6 @@ static const struct file_operations xusb_read_proc_ops = {
|
||||
MODULE_DESCRIPTION("XPP USB Transport Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
|
||||
module_init(xpp_usb_init);
|
||||
module_exit(xpp_usb_shutdown);
|
||||
|
||||
@@ -191,20 +191,20 @@ static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
xtable = xproto_table(xpd->type);
|
||||
xtable = xproto_table(xpd->xpd_type);
|
||||
if (!xtable) {
|
||||
if (printk_ratelimit())
|
||||
XPD_ERR(xpd,
|
||||
"%s: no protocol table (type=%d)\n",
|
||||
__func__, xpd->type);
|
||||
"%s: no protocol table (xpd_type=%d)\n",
|
||||
__func__, xpd->xpd_type);
|
||||
goto out;
|
||||
}
|
||||
xe = xproto_card_entry(xtable, op);
|
||||
if (!xe) {
|
||||
if (printk_ratelimit()) {
|
||||
XPD_NOTICE(xpd,
|
||||
"%s: bad command (type=%d,opcode=0x%x)\n",
|
||||
__func__, xpd->type, op);
|
||||
"%s: bad command (xpd_type=%d,opcode=0x%x)\n",
|
||||
__func__, xpd->xpd_type, op);
|
||||
dump_packet("packet_process -- bad command",
|
||||
pack, 1);
|
||||
}
|
||||
@@ -381,17 +381,36 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
||||
char data_buf[MAX_PROC_WRITE];
|
||||
|
||||
/* The size byte is not included */
|
||||
if (regcmd->bytes > sizeof(*regcmd) - 1) {
|
||||
if (regcmd->h.bytes > sizeof(*regcmd) - 1) {
|
||||
PORT_NOTICE(xbus, unit, port,
|
||||
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
|
||||
msg, regcmd->bytes);
|
||||
msg, regcmd->h.bytes);
|
||||
return;
|
||||
}
|
||||
if (regcmd->is_multibyte) {
|
||||
if (regcmd->h.bytes == REG_CMD_SIZE(RAM)) {
|
||||
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum,
|
||||
(REG_FIELD_RAM(regcmd, all_ports_broadcast)) ? "*" : "");
|
||||
if (REG_FIELD_RAM(regcmd, read_request)) {
|
||||
action = 'R';
|
||||
} else {
|
||||
action = 'W';
|
||||
}
|
||||
PORT_DBG(REGS, xbus, unit, port,
|
||||
"%s: %s %cR %02X %02X %02X %02X %02X %02X\n",
|
||||
msg, port_buf, action,
|
||||
REG_FIELD_RAM(regcmd, addr_low),
|
||||
REG_FIELD_RAM(regcmd, addr_high),
|
||||
REG_FIELD_RAM(regcmd, data_0),
|
||||
REG_FIELD_RAM(regcmd, data_1),
|
||||
REG_FIELD_RAM(regcmd, data_2),
|
||||
REG_FIELD_RAM(regcmd, data_3));
|
||||
return;
|
||||
}
|
||||
if (regcmd->h.is_multibyte) {
|
||||
char buf[MAX_PROC_WRITE + 1];
|
||||
int i;
|
||||
int n = 0;
|
||||
size_t len = regcmd->bytes;
|
||||
size_t len = regcmd->h.bytes;
|
||||
const __u8 *p = REG_XDATA(regcmd);
|
||||
|
||||
buf[0] = '\0';
|
||||
@@ -401,18 +420,18 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
||||
PORT_DBG(REGS, xbus, unit, port,
|
||||
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
|
||||
"%s[0..%zd]: %s%s\n",
|
||||
unit, port, regcmd->eoframe, msg, len - 1, buf,
|
||||
unit, port, regcmd->h.eoframe, msg, len - 1, buf,
|
||||
(n >= MAX_PROC_WRITE) ? "..." : "");
|
||||
return;
|
||||
}
|
||||
/* The size byte is not included */
|
||||
if (regcmd->bytes != sizeof(*regcmd) - 1) {
|
||||
if (regcmd->h.bytes != REG_CMD_SIZE(REG)) {
|
||||
PORT_NOTICE(xbus, unit, port,
|
||||
"%s: %s: Wrong size: regcmd->bytes = %d\n",
|
||||
__func__, msg, regcmd->bytes);
|
||||
__func__, msg, regcmd->h.bytes);
|
||||
return;
|
||||
}
|
||||
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum,
|
||||
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum,
|
||||
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
|
||||
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
|
||||
modifier = 'D';
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
*/
|
||||
#define XPP_PROTOCOL_VERSION 30
|
||||
|
||||
struct unit_descriptor;
|
||||
|
||||
struct xpd_addr {
|
||||
uint8_t subunit:SUBUNIT_BITS;
|
||||
uint8_t reserved:1;
|
||||
@@ -127,7 +129,6 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
|
||||
#define XENTRY(prototab, module, op) \
|
||||
[ XPROTO_NAME(module, op) ] = { \
|
||||
.handler = XPROTO_HANDLER(module, op), \
|
||||
.datalen = RPACKET_SIZE(module, op), \
|
||||
.name = #op, \
|
||||
.table = &PROTO_TABLE(prototab) \
|
||||
}
|
||||
@@ -167,35 +168,84 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
|
||||
|
||||
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
|
||||
|
||||
typedef struct reg_cmd {
|
||||
struct reg_cmd_header {
|
||||
__u8 bytes:3; /* Length (for Multibyte) */
|
||||
__u8 eoframe:1; /* For BRI -- end of frame */
|
||||
__u8 portnum:3; /* For port specific registers */
|
||||
__u8 is_multibyte:1;
|
||||
} PACKED;
|
||||
|
||||
struct reg_cmd_REG {
|
||||
__u8 reserved:3;
|
||||
__u8 do_expander:1;
|
||||
__u8 do_datah:1;
|
||||
__u8 do_subreg:1;
|
||||
__u8 read_request:1;
|
||||
__u8 all_ports_broadcast:1;
|
||||
__u8 regnum;
|
||||
__u8 subreg;
|
||||
__u8 data_low;
|
||||
__u8 data_high;
|
||||
} PACKED;
|
||||
|
||||
struct reg_cmd_RAM {
|
||||
__u8 reserved:4;
|
||||
__u8 do_datah:1;
|
||||
__u8 do_subreg:1;
|
||||
__u8 read_request:1;
|
||||
__u8 all_ports_broadcast:1;
|
||||
__u8 addr_low;
|
||||
__u8 addr_high;
|
||||
__u8 data_0;
|
||||
__u8 data_1;
|
||||
__u8 data_2;
|
||||
__u8 data_3;
|
||||
} PACKED;
|
||||
|
||||
typedef struct reg_cmd {
|
||||
struct reg_cmd_header h;
|
||||
union {
|
||||
struct {
|
||||
__u8 reserved:4;
|
||||
__u8 do_datah:1;
|
||||
__u8 do_subreg:1;
|
||||
__u8 read_request:1;
|
||||
__u8 all_ports_broadcast:1;
|
||||
__u8 regnum;
|
||||
__u8 subreg;
|
||||
__u8 data_low;
|
||||
__u8 data_high;
|
||||
} PACKED r;
|
||||
struct reg_cmd_REG r;
|
||||
/* For Write-Multibyte commands in BRI */
|
||||
struct {
|
||||
__u8 xdata[MULTIBYTE_MAX_LEN];
|
||||
} PACKED d;
|
||||
struct reg_cmd_RAM m;
|
||||
} PACKED alt;
|
||||
} PACKED reg_cmd_t;
|
||||
|
||||
/* Shortcut access macros */
|
||||
#define REG_CMD_SIZE(variant) (sizeof(struct reg_cmd_ ## variant))
|
||||
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
|
||||
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata)
|
||||
#define REG_FIELD_RAM(regptr, member) ((regptr)->alt.m.member)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define XFRAME_CMD_LEN(variant) \
|
||||
( \
|
||||
sizeof(struct xpacket_header) + \
|
||||
sizeof(struct reg_cmd_header) + \
|
||||
sizeof(struct reg_cmd_ ## variant) \
|
||||
)
|
||||
|
||||
#define XFRAME_NEW_REG_CMD(frm, p, xbus, card, variant, to) \
|
||||
do { \
|
||||
int pack_len = XFRAME_CMD_LEN(variant); \
|
||||
\
|
||||
if (!XBUS_FLAGS(xbus, CONNECTED)) \
|
||||
return -ENODEV; \
|
||||
(frm) = ALLOC_SEND_XFRAME(xbus); \
|
||||
if (!(frm)) \
|
||||
return -ENOMEM; \
|
||||
(p) = xframe_next_packet(frm, pack_len); \
|
||||
if (!(p)) \
|
||||
return -ENOMEM; \
|
||||
XPACKET_INIT(p, card, REGISTER_REQUEST, to, 0, 0); \
|
||||
XPACKET_LEN(p) = pack_len; \
|
||||
(frm)->usec_towait = 0; \
|
||||
} while (0)
|
||||
|
||||
/*----------------- protocol tables ----------------------------------*/
|
||||
|
||||
typedef struct xproto_entry xproto_entry_t;
|
||||
@@ -245,12 +295,14 @@ struct phoneops {
|
||||
int (*card_open) (xpd_t *xpd, lineno_t pos);
|
||||
int (*card_close) (xpd_t *xpd, lineno_t pos);
|
||||
int (*card_state) (xpd_t *xpd, bool on);
|
||||
int (*span_assigned) (xpd_t *xpd);
|
||||
};
|
||||
|
||||
struct xops {
|
||||
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone);
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone);
|
||||
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);
|
||||
@@ -259,7 +311,6 @@ struct xops {
|
||||
|
||||
struct xproto_entry {
|
||||
xproto_handler_t handler;
|
||||
int datalen;
|
||||
const char *name;
|
||||
xproto_table_t *table;
|
||||
};
|
||||
|
||||
@@ -1404,6 +1404,35 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
|
||||
/*! Maximum audio mask */
|
||||
#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
|
||||
|
||||
#ifndef TIMER_DATA_TYPE
|
||||
#define TIMER_DATA_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
|
||||
/**
|
||||
* timer_setup - Added in 4.13.0. We can make a direct translation to the
|
||||
* setup_timer interface since DAHDI does not pass any flags to any of the
|
||||
* timer_setup functions.
|
||||
*
|
||||
*/
|
||||
static inline void
|
||||
timer_setup(struct timer_list *timer,
|
||||
void (*timer_callback)(TIMER_DATA_TYPE data),
|
||||
unsigned long flags)
|
||||
{
|
||||
WARN_ON(flags != 0);
|
||||
setup_timer(timer, timer_callback, (TIMER_DATA_TYPE)timer);
|
||||
}
|
||||
|
||||
#define from_timer(var, callback_timer, timer_fieldname) \
|
||||
container_of((struct timer_list *)(callback_timer), \
|
||||
typeof(*var), timer_fieldname)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
|
||||
#define refcount_read atomic_read
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
|
||||
|
||||
/* DAHDI only was using the xxx_clear_bit variants. */
|
||||
@@ -1533,6 +1562,15 @@ static inline int strcasecmp(const char *s1, const char *s2)
|
||||
#endif /* 2.6.31 */
|
||||
#endif /* 3.10.0 */
|
||||
#endif /* 3.16.0 */
|
||||
#endif /* 4.11.0 */
|
||||
#endif /* 4.13.0 */
|
||||
#else /* >= 4.15.0 */
|
||||
|
||||
#ifndef TIMER_DATA_TYPE
|
||||
#define TIMER_DATA_TYPE struct timer_list *
|
||||
#endif
|
||||
|
||||
#endif /* 4.15.0 */
|
||||
|
||||
#ifndef DEFINE_SPINLOCK
|
||||
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
|
||||
|
||||
Reference in New Issue
Block a user