Compare commits

..

2 Commits

Author SHA1 Message Date
Shaun Ruffell
c1d867b8b7 dahdi: Fix previous CentOS 6.5 commit.
The previous commit from earlier today to fix the backport of PDE_DATA was
wrong in that it would not then process the other defines for older kernels if
it detected it was running on a redhat release.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
(cherry picked from commit 71c003ba49)
2013-12-03 09:36:40 -06:00
Shaun Ruffell
1ff5629078 dahdi: CentOS 6.5 backported PDE_DATA definition.
This will fix the "error: redefinition of 'PDE_DATA'" error when compiling.

Internal-Issue-ID: DAHLIN-330
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
(cherry picked from commit 5ec9d756aa)
2013-12-03 09:36:40 -06:00
113 changed files with 63259 additions and 34579 deletions

13
.gitignore vendored
View File

@@ -1,14 +1,10 @@
# Files that are generated as part of the build process which we do not want git
# to track.
/.pc
.cache.mk
*.[oa]
*.mod
*.mod.[oc]
*.ko
*.ko.unsigned
*.cmd
*.order
*.tar.gz
@@ -17,7 +13,6 @@ cscope.*
*.symvers
*.markers
.*.o.d
*.ur-safe
README.html
modules.order
@@ -43,12 +38,4 @@ drivers/dahdi/firmware/dahdi-fw-oct6114-256.bin
drivers/dahdi/firmware/dahdi-fw-tc400m.bin
drivers/dahdi/firmware/dahdi-fw-te820.bin
drivers/dahdi/firmware/dahdi-fw-vpmoct032.bin
drivers/dahdi/firmware/dahdi-fw-a4a.bin
drivers/dahdi/firmware/dahdi-fw-a4b.bin
drivers/dahdi/firmware/dahdi-fw-a8a.bin
drivers/dahdi/firmware/dahdi-fw-a8b.bin
drivers/dahdi/firmware/dahdi-fw-oct6114-032.bin
drivers/dahdi/firmware/dahdi-fw-te133.bin
drivers/dahdi/firmware/dahdi-fw-te134.bin
drivers/dahdi/firmware/dahdi-fw-te435.bin
drivers/dahdi/firmware/make_firmware_object

View File

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

278
README
View File

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

View File

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

40
build_tools/genudevrules Executable file
View File

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

View File

@@ -1,21 +0,0 @@
#!/bin/sh
# This is a helper script intended to be called from
# drivers/dahdi/firmware/Makefile to install the different firmware version.
FIRMWARE_PATTERN=$1
FIRMWARE_VERSION=$2
DESTDIR=$3
target="$DESTDIR/lib/firmware"
if ! test -f $target/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}; then
echo "Installing ${FIRMWARE_PATTERN}.bin to $target"
tar --no-same-owner -xf ${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}.tar.gz || exit 1
install -m 644 ${FIRMWARE_PATTERN}.bin $target || exit 1
rm -rf $target/.${FIRMWARE_PATTERN}-*
touch $target/.${FIRMWARE_PATTERN}-${FIRMWARE_VERSION}
# Remove the .bin file so that if the version is reverted, it will not
# be installed with a non-matching ${FIRMARE_VERSION} file.
rm ${FIRMWARE_PATTERN}.bin
else
echo "Firmware ${FIRMWARE_PATTERN}.bin is already installed with required version ${FIRMWARE_VERSION}"
fi

View File

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

View File

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

View File

@@ -2,18 +2,119 @@
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
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
if [ $? -ne 0 ]; then
MODIFIED=""
# 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
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}
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}
fi
echo ${VERSION}
else
# Use the directory information in the absence of any other version
# information

View File

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

View File

@@ -1,57 +0,0 @@
version: '3'
services:
test-centos7:
build:
context: ./
dockerfile: test/docker/centos7
volumes:
- ./:/source
network_mode: "host"
security_opt:
- label=type:container_runtime_t
tty: true
test-centos6:
build:
context: ./
dockerfile: test/docker/centos6
volumes:
- ./:/source
network_mode: "host"
security_opt:
- label=type:container_runtime_t
tty: true
test-debianstable:
build:
context: ./
dockerfile: test/docker/debianstable
volumes:
- ./:/source
network_mode: "host"
security_opt:
- label=type:container_runtime_t
tty: true
test-debiantesting:
build:
context: ./
dockerfile: test/docker/debiantesting
volumes:
- ./:/source
network_mode: "host"
security_opt:
- label=type:container_runtime_t
tty: true
test-fedorarawhide:
build:
context: ./
dockerfile: test/docker/fedorarawhide
volumes:
- ./:/source
network_mode: "host"
security_opt:
- label=type:container_runtime_t
tty: true

View File

@@ -7,38 +7,28 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF) += dahdi_dynamic_ethmf.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o
ifdef CONFIG_PCI
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) += oct612x/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
wcte13xp-objs := wcte13xp-base.o oct612x/lib.a
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE43X) += wcte43x.o
wcte43x-objs := wcte43x-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcte43x-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte43x-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCAXX) += wcaxx.o
wcaxx-objs := wcaxx-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcaxx-base.o += -I$(src)/oct612x/ -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcaxx-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/
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/
@@ -59,7 +49,7 @@ obj-m += dahdi_echocan_oslec.o
obj-m += ../staging/echo/echo.o
endif
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src) -Wno-format-truncation
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src)
ifndef HOTPLUG_FIRMWARE
ifneq (,$(filter y m,$(CONFIG_FW_LOADER)))
@@ -127,7 +117,6 @@ dahdi_vpmadt032_loader-objs := vpmadt032_loader/dahdi_vpmadt032_loader.o
ifneq ($(DAHDI_ARCH),)
ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_$(DAHDI_ARCH).o_shipped),)
$(shell touch $(KBUILD_EXTMOD)/vpmadt032_loader/.vpmadt032_$(DAHDI_ARCH).o.cmd)
VPMADT032_LOADER_PRESENT=yes
dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_$(DAHDI_ARCH).o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o
@@ -152,9 +141,15 @@ 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 := makefw
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
clean-files := radfw.h tor2fw.h

View File

@@ -69,6 +69,18 @@ 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
@@ -146,6 +158,23 @@ 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
@@ -222,5 +251,44 @@ config DAHDI_DYNAMIC_LOC
If unsure, say Y.
config DAHDI_TOR2
tristate "Tormenta2 quad-port T1/E1 Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called tor2.
If unsure, say Y.
config DAHDI_WCFXO
tristate "Digium Wildcard X100P Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called wcfxo.
If unsure, say Y.
config DAHDI_WCT1XXP
tristate "Digium Wildcard T100P Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called wct1xxp.
If unsure, say Y.
config DAHDI_WCTE11XP
tristate "Digium Wildcard TE110P Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called wcte11xp.
If unsure, say Y.
source "drivers/dahdi/xpp/Kconfig"

View File

@@ -50,8 +50,10 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/ktime.h>
#include <linux/slab.h>
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
#include <linux/smp_lock.h>
#endif
#include <linux/ppp_defs.h>
@@ -62,11 +64,6 @@
/* 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"
@@ -99,7 +96,7 @@
#define chan_to_netdev(h) ((h)->hdlcnetdev->netdev)
/* macro-oni for determining a unit (channel) number */
#define UNIT(file) MINOR(file->f_path.dentry->d_inode->i_rdev)
#define UNIT(file) MINOR(file->f_dentry->d_inode->i_rdev)
EXPORT_SYMBOL(dahdi_transcode_fops);
EXPORT_SYMBOL(dahdi_init_tone_state);
@@ -176,7 +173,7 @@ static sumtype *conf_sums_next;
static sumtype *conf_sums;
static sumtype *conf_sums_prev;
static struct dahdi_span *master_span;
static struct dahdi_span *master;
struct file_operations *dahdi_transcode_fops = NULL;
@@ -194,7 +191,7 @@ static int maxlinks;
static struct core_timer {
struct timer_list timer;
ktime_t start_interval;
struct timespec start_interval;
unsigned long interval;
int dahdi_receive_used;
atomic_t count;
@@ -614,7 +611,7 @@ void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec)
/* Is this span our syncronization master? */
int dahdi_is_sync_master(const struct dahdi_span *span)
{
return span == master_span;
return span == master;
}
static inline void rotate_sums(void)
@@ -735,8 +732,6 @@ enum spantypes dahdi_str2spantype(const char *name)
return SPANTYPE_DIGITAL_BRI_TE;
else if (strcasecmp("BRI_SOFT", name) == 0)
return SPANTYPE_DIGITAL_BRI_SOFT;
else if (strcasecmp("DYNAMIC", name) == 0)
return SPANTYPE_DIGITAL_DYNAMIC;
else
return SPANTYPE_INVALID;
}
@@ -754,7 +749,6 @@ const char *dahdi_spantype2str(enum spantypes st)
case SPANTYPE_DIGITAL_BRI_NT: return "BRI_NT";
case SPANTYPE_DIGITAL_BRI_TE: return "BRI_TE";
case SPANTYPE_DIGITAL_BRI_SOFT: return "BRI_SOFT";
case SPANTYPE_DIGITAL_DYNAMIC: return "DYNAMIC";
default:
case SPANTYPE_INVALID: return "INVALID";
};
@@ -793,7 +787,6 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
int crc4_bit = 0;
int len = 0;
int bit;
bool written = false;
for (bit = 4; bit <= 12; bit++) {
int mask = (1 << bit);
@@ -805,10 +798,8 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
case DAHDI_CONFIG_AMI:
case DAHDI_CONFIG_HDB3:
framing_bit = bit;
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
len += snprintf(buf + len, size, "%s/",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
if (!coding_bit) {
@@ -817,18 +808,14 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
case DAHDI_CONFIG_D4:
case DAHDI_CONFIG_CCS:
coding_bit = bit;
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
len += snprintf(buf + len, size, "%s",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
if (!crc4_bit && mask == DAHDI_CONFIG_CRC4) {
crc4_bit = bit;
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
len += snprintf(buf + len, size, "/%s",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
return len;
@@ -992,13 +979,10 @@ static int dahdi_seq_show(struct seq_file *sfile, void *data)
seq_fill_alarm_string(sfile, chan->chan_alarms);
mutex_lock(&chan->mutex);
if (chan->ec_factory) {
if (chan->ec_factory)
seq_printf(sfile, "(EC: %s - %s) ",
chan->ec_factory->get_name(chan),
chan->ec_state ? "ACTIVE" : "INACTIVE");
}
mutex_unlock(&chan->mutex);
seq_printf(sfile, "\n");
}
@@ -1011,14 +995,6 @@ static int dahdi_proc_open(struct inode *inode, struct file *file)
return single_open(file, dahdi_seq_show, PDE_DATA(inode));
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops dahdi_proc_ops = {
.proc_open = dahdi_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations dahdi_proc_ops = {
.owner = THIS_MODULE,
.open = dahdi_proc_open,
@@ -1026,7 +1002,6 @@ static const struct file_operations dahdi_proc_ops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif /* DAHDI_HAVE_PROC_OPS */
#endif
@@ -1502,13 +1477,14 @@ static const struct dahdi_echocan_factory hwec_factory = {
static int dahdi_enable_hw_preechocan(struct dahdi_chan *chan)
{
int res;
unsigned long flags;
mutex_lock(&chan->mutex);
spin_lock_irqsave(&chan->lock, flags);
if (chan->ec_factory != &hwec_factory)
res = -ENODEV;
else
res = 0;
mutex_unlock(&chan->mutex);
spin_unlock_irqrestore(&chan->lock, flags);
if (-ENODEV == res)
return 0;
@@ -1821,17 +1797,6 @@ static int start_tone(struct dahdi_chan *chan, int tone)
return res;
}
/**
* stop_tone - Stops any tones on a channel.
*
* Must be called with chan->lock held.
*
*/
static inline int stop_tone(struct dahdi_chan *chan)
{
return start_tone(chan, -1);
}
static int set_tone_zone(struct dahdi_chan *chan, int zone)
{
int res = 0;
@@ -1859,9 +1824,6 @@ static int set_tone_zone(struct dahdi_chan *chan, int zone)
return -ENODATA;
spin_lock_irqsave(&chan->lock, flags);
stop_tone(chan);
if (chan->curzone) {
struct dahdi_zone *zone = chan->curzone;
chan->curzone = NULL;
@@ -1910,7 +1872,6 @@ static void __dahdi_init_chan(struct dahdi_chan *chan)
might_sleep();
spin_lock_init(&chan->lock);
mutex_init(&chan->mutex);
init_waitqueue_head(&chan->waitq);
if (!chan->master)
chan->master = chan;
@@ -1974,10 +1935,12 @@ static inline void print_debug_writebuf(struct dahdi_chan* ss, struct sk_buff *s
#endif
#ifdef CONFIG_DAHDI_NET
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
static inline struct net_device_stats *hdlc_stats(struct net_device *dev)
{
return &dev->stats;
}
#endif
static int dahdi_net_open(struct net_device *dev)
{
@@ -2327,10 +2290,10 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
*/
}
mutex_lock(&chan->mutex);
spin_lock_irqsave(&chan->lock, flags);
release_echocan(chan->ec_factory);
chan->ec_factory = NULL;
mutex_unlock(&chan->mutex);
spin_unlock_irqrestore(&chan->lock, flags);
#ifdef CONFIG_DAHDI_NET
if (dahdi_have_netdev(chan)) {
@@ -2413,9 +2376,6 @@ 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) {
@@ -2533,9 +2493,6 @@ 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)) {
@@ -3085,64 +3042,57 @@ static const struct file_operations dahdi_chan_fops;
static int dahdi_specchan_open(struct file *file)
{
int res = -ENXIO;
int res = 0;
struct dahdi_chan *const chan = chan_from_file(file);
if (!chan || !chan->sig)
return -ENXIO;
/* Make sure we're not already open, a net device, or a slave
* device */
if (dahdi_have_netdev(chan))
res = -EBUSY;
else if (chan->master != chan)
res = -EBUSY;
else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
res = -EBUSY;
else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
unsigned long flags;
const struct dahdi_span_ops *const ops =
(!is_pseudo_chan(chan)) ? chan->span->ops : NULL;
if (ops && !try_module_get(ops->owner)) {
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
return -ENXIO;
}
res = initialize_channel(chan);
if (res) {
/* Reallocbufs must have failed */
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
return res;
}
spin_lock_irqsave(&chan->lock, flags);
if (is_pseudo_chan(chan))
chan->flags |= DAHDI_FLAG_AUDIO;
chan->file = file;
file->private_data = chan;
/* Since we know we're a channel now, we can
* update the f_op pointer and bypass a few of
* the checks on the minor number. */
file->f_op = &dahdi_chan_fops;
spin_unlock_irqrestore(&chan->lock, flags);
if (ops && ops->open) {
res = ops->open(chan);
if (chan && chan->sig) {
/* Make sure we're not already open, a net device, or a slave device */
if (dahdi_have_netdev(chan))
res = -EBUSY;
else if (chan->master != chan)
res = -EBUSY;
else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
res = -EBUSY;
else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
unsigned long flags;
res = initialize_channel(chan);
if (res) {
spin_lock_irqsave(&chan->lock, flags);
chan->file = NULL;
file->private_data = NULL;
spin_unlock_irqrestore(&chan->lock, flags);
module_put(ops->owner);
close_channel(chan);
clear_bit(DAHDI_FLAGBIT_OPEN,
&chan->flags);
/* Reallocbufs must have failed */
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
return res;
}
spin_lock_irqsave(&chan->lock, flags);
if (is_pseudo_chan(chan))
chan->flags |= DAHDI_FLAG_AUDIO;
if (chan->span) {
const struct dahdi_span_ops *const ops =
chan->span->ops;
if (!try_module_get(ops->owner)) {
res = -ENXIO;
} else if (ops->open) {
res = ops->open(chan);
if (res)
module_put(ops->owner);
}
}
if (!res) {
chan->file = file;
file->private_data = chan;
/* Since we know we're a channel now, we can
* update the f_op pointer and bypass a few of
* the checks on the minor number. */
file->f_op = &dahdi_chan_fops;
spin_unlock_irqrestore(&chan->lock, flags);
} else {
spin_unlock_irqrestore(&chan->lock, flags);
close_channel(chan);
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
}
} else {
res = -EBUSY;
}
} else {
res = -EBUSY;
}
} else
res = -ENXIO;
return res;
}
@@ -3883,31 +3833,6 @@ void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms)
spin_unlock_irqrestore(&chan->lock, flags);
}
struct dahdi_span *get_master_span(void)
{
return master_span;
}
void set_master_span(int spanno)
{
struct dahdi_span *s;
unsigned long flags;
struct dahdi_span *old_master;
spin_lock_irqsave(&chan_lock, flags);
old_master = master_span;
list_for_each_entry(s, &span_list, spans_node) {
if (spanno == s->spanno) {
master_span = s;
break;
}
}
spin_unlock_irqrestore(&chan_lock, flags);
if ((debug & DEBUG_MAIN) && (old_master != master_span))
module_printk(KERN_NOTICE, "Master span is set to %d (%s)\n",
master_span->spanno, master_span->name);
}
static void __dahdi_find_master_span(void)
{
struct dahdi_span *s;
@@ -3915,7 +3840,7 @@ static void __dahdi_find_master_span(void)
struct dahdi_span *old_master;
spin_lock_irqsave(&chan_lock, flags);
old_master = master_span;
old_master = master;
list_for_each_entry(s, &span_list, spans_node) {
if (s->alarms && old_master)
continue;
@@ -3925,23 +3850,31 @@ static void __dahdi_find_master_span(void)
continue;
if (!can_provide_timing(s))
continue;
if (master_span == s)
if (master == s)
continue;
master_span = s;
master = s;
break;
}
spin_unlock_irqrestore(&chan_lock, flags);
if ((debug & DEBUG_MAIN) && (old_master != master_span))
if ((debug & DEBUG_MAIN) && (old_master != master))
module_printk(KERN_NOTICE, "Master changed to %s\n", s->name);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void _dahdi_find_master_span(void *work)
{
__dahdi_find_master_span();
}
static DECLARE_WORK(find_master_work, _dahdi_find_master_span, NULL);
#else
static void _dahdi_find_master_span(struct work_struct *work)
{
__dahdi_find_master_span();
}
static DECLARE_WORK(find_master_work, _dahdi_find_master_span);
#endif
static void dahdi_find_master_span(void)
{
@@ -3966,7 +3899,7 @@ void dahdi_alarm_notify(struct dahdi_span *span)
dahdi_alarm_channel(span->chans[x], span->alarms);
/* If we're going into or out of alarm we should try to find a
* new master_span that may be a better fit. */
* new master that may be a better fit. */
dahdi_find_master_span();
/* Report more detailed alarms */
@@ -4065,6 +3998,14 @@ dahdi_timer_unlocked_ioctl(struct file *file, unsigned int cmd,
return 0;
}
#ifndef HAVE_UNLOCKED_IOCTL
static int dahdi_timer_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
return dahdi_timer_unlocked_ioctl(file, cmd, data);
}
#endif
static int dahdi_ioctl_getgains(struct file *file, unsigned long data)
{
int res = 0;
@@ -4953,6 +4894,9 @@ static int dahdi_ioctl_chanconfig(struct file *file, unsigned long data)
chan->hdlcnetdev->netdev = alloc_hdlcdev(chan->hdlcnetdev);
if (chan->hdlcnetdev->netdev) {
chan->hdlcnetdev->chan = chan;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
SET_MODULE_OWNER(chan->hdlcnetdev->netdev);
#endif
chan->hdlcnetdev->netdev->tx_queue_len = 50;
#ifdef HAVE_NET_DEVICE_OPS
chan->hdlcnetdev->netdev->netdev_ops = &dahdi_netdev_ops;
@@ -5185,7 +5129,7 @@ static int dahdi_ioctl_startup(struct file *file, unsigned long data)
}
/* Now that this span is running, it might be selected as the
* master_span */
* master span */
__dahdi_find_master_span();
}
put_span(s);
@@ -5245,6 +5189,7 @@ static bool dahdi_is_hwec_available(const struct dahdi_chan *chan)
static int dahdi_ioctl_attach_echocan(unsigned long data)
{
unsigned long flags;
struct dahdi_chan *chan;
struct dahdi_attach_echocan ae;
const struct dahdi_echocan_factory *new = NULL, *old;
@@ -5286,10 +5231,10 @@ static int dahdi_ioctl_attach_echocan(unsigned long data)
}
}
mutex_lock(&chan->mutex);
spin_lock_irqsave(&chan->lock, flags);
old = chan->ec_factory;
chan->ec_factory = new;
mutex_unlock(&chan->mutex);
spin_unlock_irqrestore(&chan->lock, flags);
if (old)
release_echocan(old);
@@ -5689,9 +5634,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, sizeof(chan->conflast));
memset(chan->conflast1, 0, sizeof(chan->conflast1));
memset(chan->conflast2, 0, sizeof(chan->conflast2));
memset(chan->conflast, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast1, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast2, 0, DAHDI_MAX_CHUNKSIZE);
}
oldconf = chan->confna; /* save old conference number */
chan->confna = conf.confno; /* set conference number */
@@ -6349,7 +6294,6 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
if (ecp->tap_length == 0) {
/* disable mode, don't need to inspect params */
mutex_lock(&chan->mutex);
spin_lock_irqsave(&chan->lock, flags);
ec_state = chan->ec_state;
chan->ec_state = NULL;
@@ -6360,7 +6304,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
ec_state->ops->echocan_free(chan, ec_state);
release_echocan(ec_current);
}
mutex_unlock(&chan->mutex);
return 0;
}
@@ -6377,7 +6321,6 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
goto exit_with_free;
}
mutex_lock(&chan->mutex);
/* free any echocan that may be on the channel already */
spin_lock_irqsave(&chan->lock, flags);
ec_state = chan->ec_state;
@@ -6448,7 +6391,6 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
}
exit_with_free:
mutex_unlock(&chan->mutex);
kfree(params);
return ret;
@@ -6999,6 +6941,25 @@ exit:
return ret;
}
#ifndef HAVE_UNLOCKED_IOCTL
static int dahdi_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
return dahdi_unlocked_ioctl(file, cmd, data);
}
#endif
#ifdef HAVE_COMPAT_IOCTL
static long dahdi_ioctl_compat(struct file *file, unsigned int cmd,
unsigned long data)
{
if (cmd == DAHDI_SFCONFIG)
return -ENOTTY; /* Not supported yet */
return dahdi_unlocked_ioctl(file, cmd, data);
}
#endif
/**
* _get_next_channo - Return the next taken channel number from the span list.
* @span: The span with which to start the search.
@@ -7233,7 +7194,7 @@ EXPORT_SYMBOL(dahdi_init_span);
* @spanno: The span number we would like assigned. If 0, the first
* available spanno/basechan will be used.
* @basechan: The base channel number we would like. Ignored if spanno is 0.
* @prefmaster: will the new span be preferred as a master_span?
* @prefmaster: will the new span be preferred as a master?
*
* Assigns a span for usage with DAHDI. All the channel numbers in it will
* have their numbering started at basechan.
@@ -7252,7 +7213,6 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
{
int res = 0;
unsigned int x;
unsigned long flags;
if (!span || !span->ops || !span->ops->owner)
return -EFAULT;
@@ -7264,16 +7224,6 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
return -EINVAL;
}
/* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via
* sysfs, so when the span is being reassigned we should make sure it's
* cleared. This eliminates the need for board drivers to re-report
* their alarm states on span reassignment. */
spin_lock_irqsave(&span->lock, flags);
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
dahdi_alarm_notify(span);
spin_unlock_irqrestore(&span->lock, flags);
if (span->ops->enable_hw_preechocan ||
span->ops->disable_hw_preechocan) {
if ((NULL == span->ops->enable_hw_preechocan) ||
@@ -7380,15 +7330,6 @@ int dahdi_assign_device_spans(struct dahdi_device *ddev)
static int auto_assign_spans = 1;
static const char *UNKNOWN = "";
/**
* dahdi_auto_assign_spans - is the parameter auto_assign_spans set?
*/
int dahdi_get_auto_assign_spans(void)
{
return auto_assign_spans;
}
EXPORT_SYMBOL(dahdi_get_auto_assign_spans);
/**
* _dahdi_register_device - Registers a DAHDI device and assign its spans.
* @ddev: the DAHDI device
@@ -7416,7 +7357,6 @@ static int _dahdi_register_device(struct dahdi_device *ddev,
__dahdi_init_span(s);
}
ddev->registration_time = ktime_get();
ret = dahdi_sysfs_add_device(ddev, parent);
if (ret)
return ret;
@@ -7532,8 +7472,8 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
for (x=0;x<span->channels;x++)
dahdi_chan_unreg(span->chans[x]);
new_master = master_span; /* FIXME: locking */
if (master_span == span)
new_master = master; /* FIXME: locking */
if (master == span)
new_master = NULL;
spin_lock_irqsave(&chan_lock, flags);
@@ -7544,13 +7484,13 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
break;
}
spin_unlock_irqrestore(&chan_lock, flags);
if (master_span != new_master) {
if (master != new_master) {
if (debug & DEBUG_MAIN) {
module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__,
(new_master)? new_master->name: "no master");
}
}
master_span = new_master;
master = new_master;
return 0;
}
@@ -7921,7 +7861,7 @@ static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigne
memset(getlin, 0, DAHDI_CHUNKSIZE * sizeof(short));
txb[0] = DAHDI_LIN2X(0, ms);
memset(txb + 1, txb[0], DAHDI_CHUNKSIZE - 1);
/* fallthrough */
/* fall through to normal conf mode */
case DAHDI_CONF_CONF: /* Normal conference mode */
if (is_pseudo_chan(ms)) /* if pseudo-channel */
{
@@ -8484,7 +8424,7 @@ static void __dahdi_hooksig_pvt(struct dahdi_chan *chan, enum dahdi_rxsig rxsig)
break;
}
#endif
/* fallthrough */
/* fall through intentionally */
case DAHDI_SIG_FXSGS: /* FXS Groundstart */
if (rxsig == DAHDI_RXSIG_ONHOOK) {
chan->ringdebtimer = RING_DEBOUNCE_TIME;
@@ -8503,7 +8443,7 @@ static void __dahdi_hooksig_pvt(struct dahdi_chan *chan, enum dahdi_rxsig rxsig)
chan->gotgs = 1;
}
}
/* fallthrough */
/* fall through intentionally */
case DAHDI_SIG_FXOLS: /* FXO Loopstart */
case DAHDI_SIG_FXOKS: /* FXO Kewlstart */
switch(rxsig) {
@@ -9345,7 +9285,11 @@ that the waitqueue is empty. */
#ifdef CONFIG_DAHDI_NET
if (skb && dahdi_have_netdev(ms))
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
skb->mac.raw = skb->data;
#else
skb_reset_mac_header(skb);
#endif
skb->dev = chan_to_netdev(ms);
#ifdef DAHDI_HDLC_TYPE_TRANS
skb->protocol = hdlc_type_trans(skb,
@@ -10003,22 +9947,40 @@ static void coretimer_cleanup(void)
#else
static unsigned long core_diff_ms(struct timespec *t0, struct timespec *t1)
{
long nanosec, sec;
unsigned long ms;
sec = (t1->tv_sec - t0->tv_sec);
nanosec = (t1->tv_nsec - t0->tv_nsec);
while (nanosec >= NSEC_PER_SEC) {
nanosec -= NSEC_PER_SEC;
++sec;
}
while (nanosec < 0) {
nanosec += NSEC_PER_SEC;
--sec;
}
ms = (sec * 1000) + (nanosec / 1000000L);
return ms;
}
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(TIMER_DATA_TYPE unused)
static void coretimer_func(unsigned long param)
{
unsigned long flags;
long ms_since_start;
ktime_t now;
unsigned long ms_since_start;
struct timespec now;
const unsigned long MAX_INTERVAL = 100000L;
const unsigned long ONESEC_INTERVAL = HZ;
const long MS_LIMIT = 3000;
long difference;
now = ktime_get();
ktime_get_ts(&now);
if (atomic_read(&core_timer.count) ==
atomic_read(&core_timer.last_count)) {
@@ -10036,7 +9998,7 @@ static void coretimer_func(TIMER_DATA_TYPE unused)
core_timer.interval);
}
ms_since_start = ktime_ms_delta(now, core_timer.start_interval);
ms_since_start = core_diff_ms(&core_timer.start_interval, &now);
/*
* If the system time has changed, it is possible for us to be
@@ -10089,14 +10051,16 @@ static void coretimer_func(TIMER_DATA_TYPE unused)
static void coretimer_init(void)
{
timer_setup(&core_timer.timer, coretimer_func, 0);
core_timer.start_interval = ktime_get();
init_timer(&core_timer.timer);
core_timer.timer.function = coretimer_func;
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);
mod_timer(&core_timer.timer, jiffies + core_timer.interval);
core_timer.timer.expires = jiffies + core_timer.interval;
add_timer(&core_timer.timer);
}
static void coretimer_cleanup(void)
@@ -10236,35 +10200,33 @@ MODULE_PARM_DESC(auto_assign_spans,
"channel numbers assigned by the driver. If 0, user space "
"will need to assign them via /sys/bus/dahdi_devices.");
static ssize_t dahdi_no_read(struct file *file, char __user *usrbuf,
size_t count, loff_t *ppos)
{
return -ENOSYS;
}
static ssize_t dahdi_no_write(struct file *file, const char __user *usrbuf,
size_t count, loff_t *ppos)
{
return -ENOSYS;
}
static const struct file_operations dahdi_fops = {
.owner = THIS_MODULE,
.open = dahdi_open,
.release = dahdi_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = dahdi_unlocked_ioctl,
#ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = dahdi_ioctl_compat,
#endif
#else
.ioctl = dahdi_ioctl,
#endif
.poll = dahdi_poll,
.read = dahdi_no_read,
.write = dahdi_no_write,
};
static const struct file_operations dahdi_timer_fops = {
.owner = THIS_MODULE,
.release = dahdi_timer_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = dahdi_timer_unlocked_ioctl,
#ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = dahdi_timer_unlocked_ioctl,
#endif
#else
.ioctl = dahdi_timer_ioctl,
#endif
.poll = dahdi_timer_poll,
.read = dahdi_no_read,
.write = dahdi_no_write,
};
/*
@@ -10324,9 +10286,35 @@ nodev_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data)
return nodev_common("ioctl");
}
#ifndef HAVE_UNLOCKED_IOCTL
static int nodev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
return nodev_unlocked_ioctl(file, cmd, data);
}
#endif
#ifdef HAVE_COMPAT_IOCTL
static long nodev_ioctl_compat(struct file *file, unsigned int cmd,
unsigned long data)
{
if (cmd == DAHDI_SFCONFIG)
return -ENOTTY; /* Not supported yet */
return nodev_unlocked_ioctl(file, cmd, data);
}
#endif
static const struct file_operations nodev_fops = {
.owner = THIS_MODULE,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = nodev_unlocked_ioctl,
#ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = nodev_ioctl_compat,
#endif
#else
.ioctl = nodev_ioctl,
#endif
.read = nodev_chan_read,
.write = nodev_chan_write,
.poll = nodev_chan_poll,
@@ -10336,7 +10324,14 @@ static const struct file_operations dahdi_chan_fops = {
.owner = THIS_MODULE,
.open = dahdi_open,
.release = dahdi_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = dahdi_unlocked_ioctl,
#ifdef HAVE_COMPAT_IOCTL
.compat_ioctl = dahdi_ioctl_compat,
#endif
#else
.ioctl = dahdi_ioctl,
#endif
.read = dahdi_chan_read,
.write = dahdi_chan_write,
.poll = dahdi_chan_poll,
@@ -10345,7 +10340,7 @@ static const struct file_operations dahdi_chan_fops = {
#ifdef CONFIG_DAHDI_WATCHDOG
static struct timer_list watchdogtimer;
static void watchdog_check(TIMER_DATA_TYPE ignored)
static void watchdog_check(unsigned long ignored)
{
unsigned long flags;
static int wdcheck=0;
@@ -10386,7 +10381,10 @@ static void watchdog_check(TIMER_DATA_TYPE ignored)
static int __init watchdog_init(void)
{
timer_setup(&watchdogtimer, watchdog_check, 0);
init_timer(&watchdogtimer);
watchdogtimer.expires = 0;
watchdogtimer.data =0;
watchdogtimer.function = watchdog_check;
/* Run every couple of jiffy or so */
mod_timer(&watchdogtimer, jiffies + 2);
return 0;
@@ -10442,10 +10440,35 @@ failed_driver_init:
return res;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
#ifdef CONFIG_PCI
void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state)
{
u16 reg16;
int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
PCIE_LINK_STATE_CLKPM);
if (!pos)
return;
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
reg16 &= ~(state);
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
}
EXPORT_SYMBOL(dahdi_pci_disable_link_state);
#endif /* CONFIG_PCI */
#endif /* 2.6.25 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
static inline void flush_find_master_work(void)
{
flush_scheduled_work();
}
#else
static inline void flush_find_master_work(void)
{
cancel_work_sync(&find_master_work);
}
#endif
static void __exit dahdi_cleanup(void)
{

View File

@@ -33,11 +33,9 @@
/* shortcuts, for code readability */
#define MAKE_DAHDI_DEV(num, name) \
device_create(dahdi_class, NULL, MKDEV(DAHDI_MAJOR, num), \
NULL, "%s", name)
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
#define DEL_DAHDI_DEV(num) \
device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, num))
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
static struct class *dahdi_class;
@@ -160,7 +158,6 @@ 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),
@@ -177,39 +174,6 @@ 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)
{
@@ -232,11 +196,7 @@ static int chan_match(struct device *dev, struct device_driver *driver)
static struct bus_type chan_bus_type = {
.name = "dahdi_channels",
.match = chan_match,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
.dev_attrs = chan_dev_attrs,
#else
.dev_groups = chan_dev_groups,
#endif
};
static int chan_probe(struct device *dev)

View File

@@ -32,15 +32,8 @@
#include "dahdi-sysfs.h"
static char *initdir;
module_param(initdir, charp, 0444);
MODULE_PARM_DESC(initdir,
"deprecated, should use <tools_rootdir>/usr/share/dahdi");
static char *tools_rootdir;
module_param(tools_rootdir, charp, 0444);
MODULE_PARM_DESC(tools_rootdir,
"root directory of all tools paths (default /)");
static char *initdir = "/usr/share/dahdi";
module_param(initdir, charp, 0644);
static int span_match(struct device *dev, struct device_driver *driver)
{
@@ -54,13 +47,43 @@ static inline struct dahdi_span *dev_to_span(struct device *dev)
#define SPAN_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
initdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
} while (0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
return err; \
} while (0)
static int span_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct dahdi_span *span;
int i = 0;
int len = 0;
if (!dev)
return -ENODEV;
span = dev_to_span(dev);
if (!span)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
dev_name(dev), span->name);
SPAN_VAR_BLOCK;
envp[i] = NULL;
return 0;
}
#else
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(kenv, fmt, val); \
@@ -83,6 +106,8 @@ static int span_uevent(struct device *dev, struct kobj_uevent_env *kenv)
return 0;
}
#endif
#define span_attr(field, format_string) \
static BUS_ATTR_READER(field##_show, dev, buf) \
{ \
@@ -180,7 +205,6 @@ 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),
@@ -197,89 +221,17 @@ 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)
{
struct dahdi_span *s = get_master_span();
return snprintf(buf, PAGE_SIZE, "%d\n", (s) ? s->spanno : 0);
}
static ssize_t master_span_store(struct device_driver *driver, const char *buf,
size_t count)
{
int spanno;
if (sscanf(buf, "%d", &spanno) != 1) {
module_printk(KERN_ERR, "non-numeric input '%s'\n", buf);
return -EINVAL;
}
set_master_span(spanno);
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static struct driver_attribute dahdi_attrs[] = {
__ATTR(master_span, S_IRUGO | S_IWUSR, master_span_show,
master_span_store),
__ATTR_NULL,
};
#else
static DRIVER_ATTR_RW(master_span);
static struct attribute *dahdi_attrs[] = {
&driver_attr_master_span.attr,
NULL,
};
ATTRIBUTE_GROUPS(dahdi);
#endif
static struct bus_type spans_bus_type = {
.name = "dahdi_spans",
.match = span_match,
.uevent = span_uevent,
#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
.drv_groups = dahdi_groups,
#endif
};
static int span_probe(struct device *dev)
@@ -344,7 +296,6 @@ void span_sysfs_remove(struct dahdi_span *span)
get_device(span_device);
span_uevent_send(span, KOBJ_OFFLINE);
sysfs_remove_link(&span_device->kobj, "ddev");
device_unregister(span->span_device);
dev_set_drvdata(span_device, NULL);
span_device->parent = NULL;
@@ -385,15 +336,6 @@ int span_sysfs_create(struct dahdi_span *span)
span->span_device = NULL;
goto cleanup;
}
res = sysfs_create_link(&span_device->kobj, &span_device->parent->kobj,
"ddev");
if (res) {
span_err(span, "%s: sysfs_create_link failed: %d\n", __func__,
res);
kfree(span->span_device);
span->span_device = NULL;
goto cleanup;
}
for (x = 0; x < span->channels; x++) {
res = chan_sysfs_create(span->chans[x]);
@@ -420,40 +362,8 @@ static inline struct dahdi_device *to_ddev(struct device *dev)
return container_of(dev, struct dahdi_device, dev);
}
#define DEVICE_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
initdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_HWID=%s", \
ddev->hardware_id); \
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_LOCATION=%s", \
ddev->location); \
} while (0)
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(kenv, fmt, val); \
if (err) \
return err; \
} while (0)
static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv)
{
struct dahdi_device *ddev;
if (!dev)
return -ENODEV;
ddev = to_ddev(dev);
if (!ddev)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev));
DEVICE_VAR_BLOCK;
return 0;
}
static ssize_t
manufacturer_show(struct device *dev,
dahdi_device_manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -461,7 +371,7 @@ manufacturer_show(struct device *dev,
}
static ssize_t
type_show(struct device *dev,
dahdi_device_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -469,7 +379,7 @@ type_show(struct device *dev,
}
static ssize_t
span_count_show(struct device *dev,
dahdi_device_span_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -483,7 +393,7 @@ span_count_show(struct device *dev,
}
static ssize_t
hardware_id_show(struct device *dev,
dahdi_device_hardware_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -493,17 +403,7 @@ hardware_id_show(struct device *dev,
}
static ssize_t
location_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n",
(ddev->location) ? ddev->location : "");
}
static ssize_t
auto_assign_store(struct device *dev, struct device_attribute *attr,
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -512,7 +412,7 @@ auto_assign_store(struct device *dev, struct device_attribute *attr,
}
static ssize_t
assign_span_store(struct device *dev, struct device_attribute *attr,
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
@@ -547,7 +447,7 @@ assign_span_store(struct device *dev, struct device_attribute *attr,
}
static ssize_t
unassign_span_store(struct device *dev, struct device_attribute *attr,
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
@@ -600,8 +500,7 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
{
struct dahdi_device *const ddev = to_ddev(dev);
int ret;
struct dahdi_span *span = NULL;
struct dahdi_span *cur;
struct dahdi_span *span;
unsigned int local_span_number;
char spantype_name[80];
enum spantypes spantype;
@@ -617,18 +516,9 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
list_for_each_entry(cur, &ddev->spans, device_node) {
if (local_spanno(cur) == local_span_number) {
span = cur;
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_spanno(span) == local_span_number)
break;
}
}
if (!span || (local_spanno(span) != local_span_number)) {
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
@@ -637,6 +527,12 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
if (local_spanno(span) != local_span_number) {
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
if (!span->ops->set_spantype) {
module_printk(KERN_WARNING, "Span %s does not support "
@@ -648,70 +544,22 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return (ret < 0) ? ret : count;
}
static ssize_t
dahdi_registration_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
int count = 0;
struct timespec64 ts = ktime_to_timespec64(ddev->registration_time);
count += sprintf(buf, "%010lld.%09ld\n",
(s64)ts.tv_sec,
ts.tv_nsec);
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
static struct device_attribute dahdi_device_attrs[] = {
__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(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
__ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
__ATTR(span_count, S_IRUGO, dahdi_device_span_count_show, NULL),
__ATTR(hardware_id, S_IRUGO, dahdi_device_hardware_id_show, NULL),
__ATTR(auto_assign, S_IWUSR, NULL, dahdi_device_auto_assign),
__ATTR(assign_span, S_IWUSR, NULL, dahdi_device_assign_span),
__ATTR(unassign_span, S_IWUSR, NULL, dahdi_device_unassign_span),
__ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
dahdi_spantype_store),
__ATTR(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)
@@ -791,19 +639,6 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
int res = 0;
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
/* Handle dahdi-tools paths (for udev environment) */
if (tools_rootdir && initdir) {
dahdi_err("Cannot use tools-rootdir and initdir parameters simultaneously\n");
return -EINVAL;
}
if (initdir)
pr_notice("dahdi: initdir is depracated -- prefer using \"tools_rootdir\" parameter\n");
else
initdir = "/usr/share/dahdi";
if (!tools_rootdir)
tools_rootdir = "";
res = bus_register(&dahdi_device_bus);
if (res)
return res;

View File

@@ -21,6 +21,29 @@
#define DRIVER_ATTR_READER(name, drv, buf) \
ssize_t name(struct device_driver *drv, char * buf)
/* Device file creation macros */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, NULL, "%s", name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, name)
#else
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, NULL, devt, device, name)
#endif
/* Device file destruction macros */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#define CLASS_DEV_DESTROY(class, devt) \
device_destroy(class, devt)
#else
#define CLASS_DEV_DESTROY(class, devt) \
class_device_destroy(class, devt)
#endif
/* Global */
int __init dahdi_sysfs_chan_init(const struct file_operations *fops);
void dahdi_sysfs_chan_exit(void);

View File

@@ -38,7 +38,8 @@
#include <linux/version.h>
#if defined(CONFIG_HIGH_RES_TIMERS)
#if defined(CONFIG_HIGH_RES_TIMERS) && \
LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
#define USE_HIGHRESTIMER
#endif
@@ -49,8 +50,9 @@
#include <linux/moduleparam.h>
#include <linux/slab.h>
#if defined(USE_HIGHRESTIMER)
#include <linux/hrtimer.h>
#if !defined(USE_HIGHRESTIMER)
#else
#include <linux/timer.h>
#endif
@@ -79,7 +81,7 @@ struct dahdi_dummy {
struct dahdi_chan *chan;
#if !defined(USE_HIGHRESTIMER)
unsigned long calls_since_start;
ktime_t start_interval;
struct timespec start_interval;
#endif
};
@@ -137,19 +139,36 @@ static enum hrtimer_restart dahdi_dummy_hr_int(struct hrtimer *htmr)
return HRTIMER_RESTART;
}
#else
static void dahdi_dummy_timer(TIMER_DATA_TYPE unused)
static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1)
{
long ms_since_start;
ktime_t now;
const long MAX_INTERVAL = 100000L;
const long MS_LIMIT = 3000;
long nanosec, sec;
unsigned long ms;
sec = (t1->tv_sec - t0->tv_sec);
nanosec = (t1->tv_nsec - t0->tv_nsec);
while (nanosec >= NSEC_PER_SEC) {
nanosec -= NSEC_PER_SEC;
++sec;
}
while (nanosec < 0) {
nanosec += NSEC_PER_SEC;
--sec;
}
ms = (sec * 1000) + (nanosec / 1000000L);
return ms;
}
static void dahdi_dummy_timer(unsigned long param)
{
unsigned long ms_since_start;
struct timespec now;
const unsigned long MAX_INTERVAL = 100000L;
const unsigned long MS_LIMIT = 3000;
if (!atomic_read(&shutdown))
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
now = ktime_get();
ms_since_start = ktime_ms_delta(now, ztd->start_interval);
now = current_kernel_time();
ms_since_start = timespec_diff_ms(&ztd->start_interval, &now);
/*
* If the system time has changed, it is possible for us to be far
@@ -239,10 +258,12 @@ 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
timer_setup(&timer, dahdi_dummy_timer, 0);
ztd->start_interval = ktime_get();
init_timer(&timer);
timer.function = dahdi_dummy_timer;
ztd->start_interval = current_kernel_time();
timer.expires = jiffies + JIFFIES_INTERVAL;
atomic_set(&shutdown, 0);
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
add_timer(&timer);
#endif
if (debug)

View File

@@ -201,9 +201,7 @@ static void dahdi_dynamic_sendmessage(struct dahdi_dynamic *d)
static void __dahdi_dynamic_run(void)
{
struct dahdi_dynamic *d;
#ifdef ENABLE_TASKLETS
struct dahdi_dynamic_driver *drv;
#endif
rcu_read_lock();
list_for_each_entry_rcu(d, &dspan_list, list) {
@@ -213,13 +211,6 @@ static void __dahdi_dynamic_run(void)
}
#ifdef ENABLE_TASKLETS
list_for_each_entry_rcu(drv, &driver_list, list) {
/* Flush any traffic still pending in the driver */
if (drv->flush) {
drv->flush();
}
}
#else
/* If tasklets are not enabled, the above section will be called in
* interrupt context and the flushing of each driver will be called in a
* separate tasklet that only handles that. This is necessary since some
@@ -230,6 +221,13 @@ static void __dahdi_dynamic_run(void)
*
*/
tasklet_hi_schedule(&dahdi_dynamic_flush_tlet);
#else
list_for_each_entry_rcu(drv, &driver_list, list) {
/* Flush any traffic still pending in the driver */
if (drv->flush) {
drv->flush();
}
}
#endif
rcu_read_unlock();
}
@@ -467,7 +465,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 (refcount_read(&d->kref.refcount) > 2) {
if (atomic_read(&d->kref.refcount) > 2) {
dynamic_put(d);
return -EBUSY;
}
@@ -632,14 +630,10 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
d->span.deflaw = DAHDI_LAW_MULAW;
d->span.flags |= DAHDI_FLAG_RBS;
d->span.chans = d->chans;
d->span.spantype = SPANTYPE_DIGITAL_DYNAMIC;
d->span.linecompat = DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_CCS |
DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_NOTOPEN;
d->span.ops = &dynamic_ops;
for (x = 0; x < d->span.channels; x++) {
snprintf(d->chans[x]->name, sizeof(d->chans[x]->name),
"DYN/%s/%s/%d", dds->driver, dds->addr, x+1);
sprintf(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 +825,7 @@ EXPORT_SYMBOL(dahdi_dynamic_unregister_driver);
static struct timer_list alarmcheck;
static void check_for_red_alarm(TIMER_DATA_TYPE unused)
static void check_for_red_alarm(unsigned long ignored)
{
int newalarm;
int alarmchanged = 0;
@@ -867,7 +861,10 @@ static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
static int dahdi_dynamic_init(void)
{
/* Start process to check for RED ALARM */
timer_setup(&alarmcheck, check_for_red_alarm, 0);
init_timer(&alarmcheck);
alarmcheck.expires = 0;
alarmcheck.data = 0;
alarmcheck.function = check_for_red_alarm;
/* Check once per second */
mod_timer(&alarmcheck, jiffies + 1 * HZ);
#ifdef ENABLE_TASKLETS

View File

@@ -80,7 +80,11 @@ static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
{
struct dahdi_span *span;
struct ztdeth_header *zh;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
zh = (struct ztdeth_header *)skb_network_header(skb);
#else
zh = (struct ztdeth_header *)skb->nh.raw;
#endif
span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
if (span) {
skb_pull(skb, sizeof(struct ztdeth_header));
@@ -162,9 +166,18 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
/* Setup protocol and such */
skb->protocol = __constant_htons(ETH_P_DAHDI_DETH);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
skb_set_network_header(skb, 0);
#else
skb->nh.raw = skb->data;
#endif
skb->dev = dev;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
dev_hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len);
#else
if (dev->hard_header)
dev->hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len);
#endif
skb_queue_tail(&skbs, skb);
}
}
@@ -253,7 +266,6 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
struct ztdeth *z = dyn->pvt;
unsigned long flags;
struct ztdeth *prev=NULL, *cur;
spin_lock_irqsave(&zlock, flags);
cur = zdevs;
while(cur) {
@@ -267,14 +279,12 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
prev = cur;
cur = cur->next;
}
spin_unlock_irqrestore(&zlock, flags);
if (cur == z) { /* Successfully removed */
dyn->pvt = NULL;
dev_put(z->dev);
printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
kfree(z);
}
spin_unlock_irqrestore(&zlock, flags);
}
static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
@@ -355,7 +365,11 @@ static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
}
z->subaddr = htons(sub);
}
z->dev = dev_get_by_name(&init_net, z->ethdev);
z->dev = dev_get_by_name(
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
&init_net,
#endif
z->ethdev);
if (!z->dev) {
printk(KERN_NOTICE "TDMoE: Invalid device '%s'\n", z->ethdev);
kfree(z);

View File

@@ -236,7 +236,11 @@ static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
unsigned int samples, channels, rbslen, flags;
unsigned int skip = 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
zh = (struct ztdeth_header *) skb_network_header(skb);
#else
zh = (struct ztdeth_header *) skb->nh.raw;
#endif
if (ntohs(zh->subaddr) & 0x8000) {
/* got a multi-span frame */
num_spans = ntohs(zh->subaddr) & 0xFF;
@@ -480,9 +484,19 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
/* Setup protocol type */
skb->protocol = __constant_htons(ETH_P_ZTDETH);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
skb_set_network_header(skb, 0);
#else
skb->nh.raw = skb->data;
#endif
skb->dev = dev;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
dev_hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len);
#else
if (dev->hard_header)
dev->hard_header(skb, dev, ETH_P_ZTDETH, addr,
dev->dev_addr, skb->len);
#endif
/* queue frame for delivery */
if (dev) {
skb_queue_tail(&skbs, skb);
@@ -589,7 +603,11 @@ static int ztdethmf_create(struct dahdi_dynamic *dyn, const char *addr)
kfree(z);
return -EINVAL;
}
z->dev = dev_get_by_name(&init_net, z->ethdev);
z->dev = dev_get_by_name(
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
&init_net,
#endif
z->ethdev);
if (!z->dev) {
printk(KERN_ERR "TDMoE Multiframe: Invalid device '%s'\n", z->ethdev);
kfree(z);
@@ -663,13 +681,16 @@ 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(TIMER_DATA_TYPE unused)
static void timer_callback(unsigned long param)
{
if (ethmf_delay_dec()) {
if (!atomic_read(&timer_deleted))
mod_timer(&timer, jiffies + HZ);
if (!atomic_read(&timer_deleted)) {
timer.expires = jiffies + HZ;
add_timer(&timer);
}
} else {
printk(KERN_INFO "All TDMoE multiframe span groups are active.\n");
del_timer(&timer);
}
}
@@ -733,28 +754,21 @@ static int ztdethmf_proc_open(struct inode *inode, struct file *file)
return single_open(file, ztdethmf_proc_show, NULL);
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops ztdethmf_proc_fops = {
.proc_open = ztdethmf_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = seq_release,
};
#else
static const struct file_operations ztdethmf_proc_fops = {
.owner = THIS_MODULE,
.open = ztdethmf_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.open = ztdethmf_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#endif /* DAHDI_HAVE_PROC_OPS */
#endif
static int __init ztdethmf_init(void)
{
timer_setup(&timer, timer_callback, 0);
mod_timer(&timer, jiffies + HZ);
init_timer(&timer);
timer.expires = jiffies + HZ;
timer.function = &timer_callback;
if (!timer_pending(&timer))
add_timer(&timer);
dev_add_pack(&ztdethmf_ptype);
register_netdevice_notifier(&ztdethmf_nblock);

View File

@@ -168,9 +168,8 @@ static void dtc_release(struct dahdi_transcoder_channel *chan)
BUG_ON(!chan);
if (chan->parent && chan->parent->release) {
chan->parent->release(chan);
} else {
dahdi_tc_clear_busy(chan);
}
dahdi_tc_clear_busy(chan);
}
static int dahdi_tc_release(struct inode *inode, struct file *file)
@@ -397,6 +396,13 @@ static long dahdi_tc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
};
}
#ifndef HAVE_UNLOCKED_IOCTL
static int dahdi_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
{
return (int)dahdi_tc_unlocked_ioctl(file, cmd, data);
}
#endif
static unsigned int dahdi_tc_poll(struct file *file, struct poll_table_struct *wait_table)
{
int ret;
@@ -420,7 +426,11 @@ static struct file_operations __dahdi_transcode_fops = {
.owner = THIS_MODULE,
.open = dahdi_tc_open,
.release = dahdi_tc_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = dahdi_tc_unlocked_ioctl,
#else
.ioctl = dahdi_tc_ioctl,
#endif
.read = dahdi_tc_read,
.write = dahdi_tc_write,
.poll = dahdi_tc_poll,

View File

@@ -8,7 +8,7 @@ PWD=$(shell pwd)
MODULESO:=$(MODULES:%=%.o)
MODULESKO:=$(MODULES:%=%.ko)
KMAKE = $(MAKE) -C $(KSRC) M=$(PWD)
KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD)
KMAKE_INST = $(KMAKE) \
INSTALL_MOD_PATH=$(INSTALL_PREFIX) INSTALL_MOD_DIR=misc modules_install

View File

@@ -1063,23 +1063,12 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
used = pvc_is_used(pvc);
if (type == ARPHRD_ETHER) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
dev = alloc_netdev(sizeof(struct net_device_stats),
"pvceth%d", NET_NAME_UNKNOWN, ether_setup);
#else
if (type == ARPHRD_ETHER)
dev = alloc_netdev(sizeof(struct net_device_stats),
"pvceth%d", ether_setup);
#endif
} else {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
dev = alloc_netdev(sizeof(struct net_device_stats),
"pvc%d", NET_NAME_UNKNOWN, dlci_setup);
#else
else
dev = alloc_netdev(sizeof(struct net_device_stats),
"pvc%d", dlci_setup);
#endif
}
if (!dev) {
printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",

View File

@@ -282,12 +282,7 @@ static void hdlc_setup(struct net_device *dev)
struct net_device *alloc_hdlcdev(void *priv)
{
struct net_device *dev;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d",
NET_NAME_UNKNOWN, hdlc_setup);
#else
dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
#endif
if (dev)
dev_to_hdlc(dev)->priv = priv;
return dev;

View File

@@ -51,7 +51,6 @@
#include <linux/pkt_sched.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/slab.h>
#include <net/syncppp.h>
@@ -148,7 +147,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 (TIMER_DATA_TYPE timer);
static void sppp_cp_timeout (unsigned long arg);
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,9 +188,12 @@ 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;
timer_setup(&p->pp_timer, sppp_cp_timeout, 0);
mod_timer(&p->pp_timer, jiffies + s*HZ);
add_timer(&p->pp_timer);
}
}

View File

@@ -3,7 +3,7 @@
#
# Makefile for firmware downloading/installation
#
# Copyright (C) 2007-2013, Digium, Inc.
# Copyright (C) 2007-2010, Digium, Inc.
#
# Joshua Colp <jcolp@digium.com>
#
@@ -31,20 +31,12 @@ VPMADT032_VERSION:=1.25.0
HX8_VERSION:=2.06
VPMOCT032_VERSION:=1.12.0
WCT820_VERSION:=1.76
TE133_VERSION:=7a001e
TE134_VERSION:=780017
TE435_VERSION:=13001e
TE436_VERSION:=10017
A8A_VERSION:=1d0017
A8B_VERSION:=1f001e
A4A_VERSION:=a0017
A4B_VERSION:=d001e
TE133_VERSION:=6f0017
TE134_VERSION:=6f0017
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256
ALL_FIRMWARE+=FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435 FIRMWARE-TE436
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
# First example: dahdi-fw-oct6114-064-1.05.01
@@ -63,12 +55,6 @@ FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE435=dahdi-fw-te435-$(TE435_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE436=dahdi-fw-te436-$(TE436_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8A=dahdi-fw-a8b-$(A8B_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8B=dahdi-fw-a8a-$(A8A_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4A=dahdi-fw-a4b-$(A4B_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4B=dahdi-fw-a4a-$(A4A_VERSION).tar.gz)
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
@@ -84,8 +70,6 @@ OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
# Force usage of wget, for now
DOWNLOAD=wget
WGET=wget
INSTALL_FIRMWARE=../../../build_tools/install_firmware
RUN_INST=$(INSTALL_FIRMWARE) $(1) $(2) $(DESTDIR)
# If "fetch" is used, --continue is not a valid option.
ifeq ($(WGET),wget)
@@ -111,6 +95,7 @@ dahdi-fw-%.tar.gz:
echo "Attempting to download $@"; \
if test ! -f $@; then $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \
if test ! -f $@; then exit 1; fi; \
(cat $@ | gzip -d | tar --no-same-owner -xf -) \
fi
firmware-loaders: $(FWLOADERS)
@@ -129,22 +114,117 @@ $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware:
# Install all downloaded firmware images for hotplug usage
hotplug-install: $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware $(FIRMWARE)
@$(call RUN_INST,dahdi-fw-oct6114-032,$(OCT6114_032_VERSION))
@$(call RUN_INST,dahdi-fw-oct6114-064,$(OCT6114_064_VERSION))
@$(call RUN_INST,dahdi-fw-oct6114-128,$(OCT6114_128_VERSION))
@$(call RUN_INST,dahdi-fw-oct6114-256,$(OCT6114_256_VERSION))
@$(call RUN_INST,dahdi-fw-tc400m,$(TC400M_VERSION))
@$(call RUN_INST,dahdi-fw-hx8,$(HX8_VERSION))
@$(call RUN_INST,dahdi-fw-vpmoct032,$(VPMOCT032_VERSION))
@$(call RUN_INST,dahdi-fw-te820,$(WCT820_VERSION))
@$(call RUN_INST,dahdi-fw-te133,$(TE133_VERSION))
@$(call RUN_INST,dahdi-fw-te134,$(TE134_VERSION))
@$(call RUN_INST,dahdi-fw-te435,$(TE435_VERSION))
@$(call RUN_INST,dahdi-fw-te436,$(TE436_VERSION))
@$(call RUN_INST,dahdi-fw-a8a,$(A8A_VERSION))
@$(call RUN_INST,dahdi-fw-a8b,$(A8B_VERSION))
@$(call RUN_INST,dahdi-fw-a4a,$(A4A_VERSION))
@$(call RUN_INST,dahdi-fw-a4b,$(A4B_VERSION))
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-032.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
else
@echo "Firmware dahdi-fw-oct6114-032.bin is already installed with required version $(OCT6114_032_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-064.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION)
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION)
else
@echo "Firmware dahdi-fw-oct6114-064.bin is already installed with required version $(OCT6114_064_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-128.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION)
@install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION)
else
@echo "Firmware dahdi-fw-oct6114-128.bin is already installed with required version $(OCT6114_128_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-256.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
else
@echo "Firmware dahdi-fw-oct6114-256.bin is already installed with required version $(OCT6114_256_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-tc400m.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION)
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION)
else
@echo "Firmware dahdi-fw-tc400m.bin is already installed with required version $(TC400M_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-$(HX8_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-$(HX8_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-hx8.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-hx8.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-$(HX8_VERSION)
@install -m 644 dahdi-fw-hx8.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-$(HX8_VERSION)
else
@echo "Firmware dahdi-fw-hx8.bin is already installed with required version $(HX8_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-vpmoct032.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-vpmoct032.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION)
@install -m 644 dahdi-fw-vpmoct032.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION)
else
@echo "Firmware dahdi-fw-vpmoct032.bin is already installed with required version $(VPMOCT032_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te820.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te820-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
else
@echo "Firmware dahdi-fw-te820.bin is already installed with required version $(WCT820_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te133.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION)
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te133-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION)
else
@echo "Firmware dahdi-fw-te133.bin is already installed with required version $(TE133_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te134.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION)
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te134-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION)
else
@echo "Firmware dahdi-fw-te134.bin is already installed with required version $(TE134_VERSION)"
endif
# Uninstall any installed dahdi firmware images from hotplug firmware directories
hotplug-uninstall:

View File

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

View File

@@ -129,7 +129,7 @@ $Octasic_Revision: 16 $
/***************************** TYPES ***************************************/
/*Change this type if your platform uses 64bits semaphores/locks */
typedef void* tOCT6100_USER_SERIAL_OBJECT;
typedef UINT32 tOCT6100_USER_SERIAL_OBJECT;
typedef struct _OCT6100_GET_TIME_
{

View File

@@ -1,207 +0,0 @@
/*
* Octasic OCT6100 Interface
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/hrtimer.h>
#include <dahdi/kernel.h>
#include "oct612x.h"
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
{
/* Why couldn't they just take a timeval like everyone else? */
u64 total_usecs;
total_usecs = ktime_to_us(ktime_get_real());
f_pTime->aulWallTimeUs[0] = total_usecs;
f_pTime->aulWallTimeUs[1] = total_usecs >> 32;
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern,
UINT32 f_ulLength)
{
memset(f_pAddress, f_ulPattern, f_ulLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource,
UINT32 f_ulLength)
{
memcpy(f_pDestination, f_pSource, f_ulLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserCreateSerializeObject(
tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
{
struct oct612x_context *context = f_pCreate->pProcessContext;
struct mutex *lock = kzalloc(sizeof(*lock), GFP_KERNEL);
if (!lock) {
dev_err(context->dev, "Out of memory in %s.\n", __func__);
return cOCT6100_ERR_BASE;
}
mutex_init(lock);
f_pCreate->ulSerialObjHndl = lock;
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDestroySerializeObject(
tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
{
struct mutex *lock = f_pDestroy->ulSerialObjHndl;
kfree(lock);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserSeizeSerializeObject(
tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
{
struct mutex *lock = f_pSeize->ulSerialObjHndl;
mutex_lock(lock);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserReleaseSerializeObject(
tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
{
struct mutex *lock = f_pRelease->ulSerialObjHndl;
mutex_unlock(lock);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
{
struct oct612x_context *context = f_pWriteParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write(context, f_pWriteParams->ulWriteAddress,
f_pWriteParams->usWriteData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
{
struct oct612x_context *context = f_pSmearParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write_smear) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write_smear(context, f_pSmearParams->ulWriteAddress,
f_pSmearParams->usWriteData,
f_pSmearParams->ulWriteLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteBurstApi(
tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
{
struct oct612x_context *context = f_pBurstParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write_burst) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write_burst(context, f_pBurstParams->ulWriteAddress,
f_pBurstParams->pusWriteData,
f_pBurstParams->ulWriteLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
{
struct oct612x_context *context = f_pReadParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->read) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->read(context, f_pReadParams->ulReadAddress,
f_pReadParams->pusReadData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
{
struct oct612x_context *context = f_pBurstParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->read_burst) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->read_burst(context, f_pBurstParams->ulReadAddress,
f_pBurstParams->pusReadData,
f_pBurstParams->ulReadLength);
return cOCT6100_ERR_OK;
}
EXPORT_SYMBOL(Oct6100ChipOpen);
EXPORT_SYMBOL(Oct6100ChipClose);
EXPORT_SYMBOL(Oct6100ChipCloseDef);
EXPORT_SYMBOL(Oct6100GetInstanceSize);
EXPORT_SYMBOL(Oct6100GetInstanceSizeDef);
EXPORT_SYMBOL(Oct6100ChipOpenDef);
EXPORT_SYMBOL(Oct6100ChannelModify);
EXPORT_SYMBOL(Oct6100ToneDetectionEnableDef);
EXPORT_SYMBOL(Oct6100InterruptServiceRoutine);
EXPORT_SYMBOL(Oct6100InterruptServiceRoutineDef);
EXPORT_SYMBOL(Oct6100ApiGetCapacityPins);
EXPORT_SYMBOL(Oct6100ToneDetectionEnable);
EXPORT_SYMBOL(Oct6100EventGetToneDef);
EXPORT_SYMBOL(Oct6100EventGetTone);
EXPORT_SYMBOL(Oct6100ApiGetCapacityPinsDef);
EXPORT_SYMBOL(Oct6100ChannelOpen);
EXPORT_SYMBOL(Oct6100ChannelOpenDef);
EXPORT_SYMBOL(Oct6100ChannelModifyDef);
static int __init oct612x_module_init(void)
{
/* This registration with dahdi.ko will fail since the span is not
* defined, but it will make sure that this module is a dependency of
* dahdi.ko, so that when it is being unloded, this module will be
* unloaded as well. */
dahdi_register_device(NULL, NULL);
return 0;
}
module_init(oct612x_module_init);
static void __exit oct612x_module_cleanup(void)
{
/* Nothing to do */;
}
module_exit(oct612x_module_cleanup);
MODULE_AUTHOR("Digium Incorporated <support@digium.com>");
MODULE_DESCRIPTION("Octasic OCT6100 Hardware Echocan Library");
MODULE_LICENSE("GPL v2");

View File

@@ -1,49 +0,0 @@
/*
* Octasic OCT6100 Interface
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __OCT612X_H__
#define __OCT612X_H__
#include <oct6100api/oct6100_api.h>
struct oct612x_context;
/**
* struct oct612x_ops - Callbacks used by oct612x library to talk to part.
*
*/
struct oct612x_ops {
int (*write)(struct oct612x_context *context, u32 address, u16 value);
int (*read)(struct oct612x_context *context, u32 address, u16 *value);
int (*write_smear)(struct oct612x_context *context, u32 address,
u16 value, size_t count);
int (*write_burst)(struct oct612x_context *context, u32 address,
const u16 *value, size_t count);
int (*read_burst)(struct oct612x_context *context, u32 address,
u16 *value, size_t count);
};
struct oct612x_context {
const struct oct612x_ops *ops;
struct device *dev;
};
#endif /* __OCT612X_H__ */

1890
drivers/dahdi/pciradio.c Normal file

File diff suppressed because it is too large Load Diff

10531
drivers/dahdi/pciradio.rbt Normal file

File diff suppressed because it is too large Load Diff

186
drivers/dahdi/tor2-hw.h Normal file
View File

@@ -0,0 +1,186 @@
/*
* 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 */

1543
drivers/dahdi/tor2.c Normal file

File diff suppressed because it is too large Load Diff

17482
drivers/dahdi/tormenta2.rbt Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -33,8 +33,11 @@
#include <linux/version.h>
#include <linux/types.h>
#include <linux/pci.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#include <linux/slab.h>
#else
#include <asm/semaphore.h>
#endif
#include <dahdi/kernel.h>
#include <dahdi/user.h>
@@ -376,9 +379,15 @@ static void update_channel_config(struct vpmadt032 *vpm, unsigned int channel,
* the hardware can take some time while messages are sent to the VPMADT032
* module and the driver waits for the responses.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void vpmadt032_bh(void *data)
{
struct vpmadt032 *vpm = data;
#else
static void vpmadt032_bh(struct work_struct *data)
{
struct vpmadt032 *vpm = container_of(data, struct vpmadt032, work);
#endif
struct change_order *order;
while ((order = get_next_order(vpm))) {
@@ -504,7 +513,11 @@ vpmadt032_alloc(struct vpmadt032_options *options)
sema_init(&vpm->sem, 1);
vpm->curpage = 0x80;
vpm->dspid = -1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&vpm->work, vpmadt032_bh, vpm);
#else
INIT_WORK(&vpm->work, vpmadt032_bh);
#endif
/* Do not use the global workqueue for processing these events. Some of
* the operations can take 100s of ms, most of that time spent sleeping.

View File

@@ -42,7 +42,10 @@
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
#include <linux/semaphore.h>
#endif
#include "gpakenum.h"
#include "adt_lec.h"

View File

@@ -1000,7 +1000,6 @@ __vb_rx_demand_poll(struct voicebus *vb)
__vb_setctl(vb, 0x0010, 0x00000000);
}
#ifndef CONFIG_VOICEBUS_TIMER
static void
__vb_enable_interrupts(struct voicebus *vb)
{
@@ -1009,7 +1008,6 @@ __vb_enable_interrupts(struct voicebus *vb)
else
__vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS);
}
#endif
static void
__vb_disable_interrupts(struct voicebus *vb)
@@ -1035,7 +1033,8 @@ 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)
mod_timer(&vb->timer, jiffies + HZ/1000);
vb->timer.expires = jiffies + HZ/1000;
add_timer(&vb->timer);
#else
/* Clear the interrupt status register. */
__vb_setctl(vb, SR_CSR5, 0xffffffff);
@@ -1197,8 +1196,11 @@ voicebus_release(struct voicebus *vb)
#endif
/* Make sure the underrun_work isn't running or going to run. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
flush_scheduled_work();
#else
cancel_work_sync(&vb->underrun_work);
#endif
/* quiesce the hardware */
voicebus_stop(vb);
@@ -1233,6 +1235,9 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
struct list_head *buffers)
{
struct vbb *vbb;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
struct vbb *n;
#endif
int i;
LIST_HEAD(local);
@@ -1268,7 +1273,12 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
}
handle_transmit(vb, &local);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
list_for_each_entry_safe(vbb, n, &local, entry)
list_move_tail(&vbb->entry, buffers);
#else
list_splice_tail(&local, buffers);
#endif
/* Set the new latency (but we want to ensure that there aren't any
* printks to the console, so we don't call the function) */
@@ -1622,10 +1632,16 @@ tx_error_exit:
* @work: The work_struct used to queue this function.
*
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void handle_hardunderrun(void *data)
{
struct voicebus *vb = data;
#else
static void handle_hardunderrun(struct work_struct *work)
{
struct voicebus *vb = container_of(work, struct voicebus,
underrun_work);
#endif
if (test_bit(VOICEBUS_STOP, &vb->flags) ||
test_bit(VOICEBUS_STOPPED, &vb->flags))
return;
@@ -1660,7 +1676,11 @@ static void handle_hardunderrun(struct work_struct *work)
* since it doesn't employ any locking on the voicebus interface.
*/
static irqreturn_t
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
vb_isr(int irq, void *dev_id, struct pt_regs *regs)
#else
vb_isr(int irq, void *dev_id)
#endif
{
struct voicebus *vb = dev_id;
unsigned long flags;
@@ -1726,13 +1746,18 @@ vb_isr(int irq, void *dev_id)
* the timer.
*/
static void
vb_timer(TIMER_DATA_TYPE timer)
vb_timer(unsigned long data)
{
unsigned long start = jiffies;
struct voicebus *vb = from_timer(vb, timer, timer);
struct voicebus *vb = (struct voicebus *)data;
#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)) {
mod_timer(&vb->timer, start + HZ/1000);
vb->timer.expires = start + HZ/1000;
add_timer(&vb->timer);
}
}
#endif
@@ -1775,10 +1800,16 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
INIT_LIST_HEAD(&vb->free_rx);
#if defined(CONFIG_VOICEBUS_TIMER)
timer_setup(&vb->timer, vb_timer, 0);
init_timer(&vb->timer);
vb->timer.function = vb_timer;
vb->timer.data = (unsigned long)vb;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&vb->underrun_work, handle_hardunderrun, vb);
#else
INIT_WORK(&vb->underrun_work, handle_hardunderrun);
#endif
/* ----------------------------------------------------------------
Configure the hardware / kernel module interfaces.
@@ -1854,7 +1885,7 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
goto cleanup;
#if !defined(CONFIG_VOICEBUS_TIMER)
retval = request_irq(vb->pdev->irq, vb_isr, IRQF_SHARED,
retval = request_irq(vb->pdev->irq, vb_isr, DAHDI_IRQ_SHARED,
board_name, vb);
if (retval) {
dev_warn(&vb->pdev->dev, "Failed to request interrupt line.\n");

View File

@@ -64,11 +64,7 @@
* platform does not support it.
*
*/
#ifdef CONFIG_VOICEBUS_DISABLE_ASPM
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
#include <linux/pci-aspm.h>
#endif
#endif
#undef CONFIG_VOICEBUS_DISABLE_ASPM
/* Define this to use a FIFO for the software echocan reference.
* (experimental) */
@@ -177,7 +173,9 @@ struct voicebus {
struct sk_buff_head captured_packets;
struct net_device *netdev;
struct net_device_stats net_stats;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
struct napi_struct napi;
#endif
atomic_t tx_seqnum;
atomic_t rx_seqnum;
#endif

View File

@@ -27,7 +27,6 @@
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <dahdi/kernel.h>
@@ -104,6 +103,26 @@ static int vb_net_receive(struct voicebus *vb, int max)
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
static int vb_net_poll(struct net_device *netdev, int *budget)
{
struct voicebus *vb = voicebus_from_netdev(netdev);
int count = 0;
int quota = min(netdev->quota, *budget);
count = vb_net_receive(vb, quota);
*budget -= count;
netdev->quota -= count;
if (!skb_queue_len(&vb->captured_packets)) {
netif_rx_complete(netdev);
return 0;
} else {
return -1;
}
}
#else
static int vb_net_poll(struct napi_struct *napi, int budget)
{
struct voicebus *vb = container_of(napi, struct voicebus, napi);
@@ -122,6 +141,7 @@ static int vb_net_poll(struct napi_struct *napi, int budget)
}
return count;
}
#endif
static void vb_net_set_multi(struct net_device *netdev)
{
@@ -134,7 +154,11 @@ static int vb_net_up(struct net_device *netdev)
{
struct voicebus *vb = voicebus_from_netdev(netdev);
dev_dbg(&vb->pdev->dev, "%s\n", __func__);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
netif_poll_enable(netdev);
#else
napi_enable(&vb->napi);
#endif
return 0;
}
@@ -142,7 +166,11 @@ static int vb_net_down(struct net_device *netdev)
{
struct voicebus *vb = voicebus_from_netdev(netdev);
dev_dbg(&vb->pdev->dev, "%s\n", __func__);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
netif_poll_disable(netdev);
#else
napi_disable(&vb->napi);
#endif
return 0;
}
@@ -178,13 +206,7 @@ int vb_net_register(struct voicebus *vb, const char *board_name)
struct voicebus_netdev_priv *priv;
const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
netdev = alloc_netdev(sizeof(*priv), board_name,
NET_NAME_UNKNOWN, ether_setup);
#else
netdev = alloc_netdev(sizeof(*priv), board_name, ether_setup);
#endif
if (!netdev)
return -ENOMEM;
priv = netdev_priv(netdev);
@@ -202,7 +224,12 @@ int vb_net_register(struct voicebus *vb, const char *board_name)
netdev->promiscuity = 0;
netdev->flags |= IFF_NOARP;
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
netdev->poll = vb_net_poll;
netdev->weight = 64;
# else
netif_napi_add(netdev, &vb->napi, vb_net_poll, 64);
# endif
skb_queue_head_init(&vb->captured_packets);
res = register_netdev(netdev);
@@ -325,7 +352,9 @@ void vb_net_capture_vbb(struct voicebus *vb, const void *vbb, const int tx,
return;
skb_queue_tail(&vb->captured_packets, skb);
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
netif_rx_schedule(netdev);
# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
netif_rx_schedule(netdev, &vb->napi);
# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
netif_rx_schedule(&vb->napi);

View File

@@ -26,7 +26,6 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/crc32.h>
#include <linux/slab.h>
#include "voicebus/vpmoct.h"
#include "linux/firmware.h"
@@ -393,10 +392,16 @@ struct vpmoct_load_work {
* long running firmware load.
*
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void vpmoct_load_complete_fn(void *data)
{
struct vpmoct_load_work *work = data;
#else
static void vpmoct_load_complete_fn(struct work_struct *data)
{
struct vpmoct_load_work *work =
container_of(data, struct vpmoct_load_work, work);
#endif
/* Do not touch work->vpm after calling load complete. It may have
* been freed in the function by the board driver. */
work->load_complete(work->vpm->dev, work->operational);
@@ -415,7 +420,11 @@ vpmoct_load_complete(struct vpmoct_load_work *work, bool operational)
{
work->operational = operational;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&work->work, vpmoct_load_complete_fn, work);
#else
INIT_WORK(&work->work, vpmoct_load_complete_fn);
#endif
schedule_work(&work->work);
}
@@ -480,10 +489,16 @@ static void vpmoct_release_firmware(const struct firmware *fw)
* @vpm: The VPMOCT032 module to check / load.
*
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void vpmoct_load_flash(void *data)
{
struct vpmoct_load_work *work = data;
#else
static void vpmoct_load_flash(struct work_struct *data)
{
struct vpmoct_load_work *work =
container_of(data, struct vpmoct_load_work, work);
#endif
int res;
struct vpmoct *const vpm = work->vpm;
const struct firmware *fw;
@@ -670,7 +685,11 @@ int vpmoct_init(struct vpmoct *vpm, load_complete_func_t load_complete)
return -ENOMEM;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&work->work, vpmoct_load_flash, work);
#else
INIT_WORK(&work->work, vpmoct_load_flash);
#endif
work->vpm = vpm;
work->load_complete = load_complete;

View File

@@ -23,7 +23,6 @@
#include <linux/ctype.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <dahdi/kernel.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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 from STIO2 */
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data from STIO1 */
#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_CH_SNUM_SHIFT (1)
#define V_CH_SNUM_MASK (31 << 1)
@@ -367,16 +367,6 @@
#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
@@ -395,8 +385,7 @@
struct b4xxp_span {
struct b4xxp *parent;
int port; /* virtual port */
int phy_port; /* physical port */
int port; /* which S/T port this span belongs to */
unsigned char writechunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
unsigned char readchunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
@@ -437,9 +426,7 @@ 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 */
B430P, /* Digium B430P */
B230P /* Digium B230P */
QUADBRI_EVAL /* HFC-4S CCD Eval. Board */
};
/* This structure exists one per card */

1093
drivers/dahdi/wcfxo.c Normal file

File diff suppressed because it is too large Load Diff

1449
drivers/dahdi/wct1xxp.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -40,7 +40,6 @@
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/crc32.h>
#include <linux/slab.h>
#include <stdbool.h>
#include <dahdi/kernel.h>
@@ -48,6 +47,16 @@
#include "wct4xxp.h"
#include "vpm450m.h"
/* Work queues are a way to better distribute load on SMP systems */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
/*
* Work queues can significantly improve performance and scalability
* on multi-processor machines, but requires bypassing some kernel
* API's, so it's not guaranteed to be compatible with all kernels.
*/
/* #define ENABLE_WORKQUEUES */
#endif
/* Support first generation cards? */
#define SUPPORT_GEN1
@@ -69,6 +78,88 @@
/* Maximum latency to be used with Gen 5 */
#define GEN5_MAX_LATENCY 127
#ifdef ENABLE_WORKQUEUES
#include <linux/cpu.h>
/* XXX UGLY!!!! XXX We have to access the direct structures of the workqueue which
are only defined within workqueue.c because they don't give us a routine to allow us
to nail a work to a particular thread of the CPU. Nailing to threads gives us substantially
higher scalability in multi-CPU environments though! */
/*
* The per-CPU workqueue (if single thread, we always use cpu 0's).
*
* The sequence counters are for flush_scheduled_work(). It wants to wait
* until until all currently-scheduled works are completed, but it doesn't
* want to be livelocked by new, incoming ones. So it waits until
* remove_sequence is >= the insert_sequence which pertained when
* flush_scheduled_work() was called.
*/
struct cpu_workqueue_struct {
spinlock_t lock;
long remove_sequence; /* Least-recently added (next to run) */
long insert_sequence; /* Next to add */
struct list_head worklist;
wait_queue_head_t more_work;
wait_queue_head_t work_done;
struct workqueue_struct *wq;
task_t *thread;
int run_depth; /* Detect run_workqueue() recursion depth */
} ____cacheline_aligned;
/*
* The externally visible workqueue abstraction is an array of
* per-CPU workqueues:
*/
struct workqueue_struct {
/* TODO: Find out exactly where the API changed */
struct cpu_workqueue_struct *cpu_wq;
const char *name;
struct list_head list; /* Empty if single thread */
};
/* Preempt must be disabled. */
static void __t4_queue_work(struct cpu_workqueue_struct *cwq,
struct work_struct *work)
{
unsigned long flags;
spin_lock_irqsave(&cwq->lock, flags);
work->wq_data = cwq;
list_add_tail(&work->entry, &cwq->worklist);
cwq->insert_sequence++;
wake_up(&cwq->more_work);
spin_unlock_irqrestore(&cwq->lock, flags);
}
/*
* Queue work on a workqueue. Return non-zero if it was successfully
* added.
*
* We queue the work to the CPU it was submitted, but there is no
* guarantee that it will be processed by that CPU.
*/
static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu)
{
int ret = 0;
get_cpu();
if (!test_and_set_bit(0, &work->pending)) {
BUG_ON(!list_empty(&work->entry));
__t4_queue_work(wq->cpu_wq + cpu, work);
ret = 1;
}
put_cpu();
return ret;
}
#endif
/*
* Define CONFIG_FORCE_EXTENDED_RESET to allow the qfalc framer extra time
* to reset itself upon hardware initialization. This exits for rare
@@ -87,18 +178,12 @@
*/
/* #define CONFIG_WCT4XXP_DISABLE_ASPM */
#ifdef CONFIG_WCT4XXP_DISABLE_ASPM
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
#include <linux/pci-aspm.h>
#endif
#endif
#if defined(CONFIG_FORCE_EXTENDED_RESET) && defined(CONFIG_NOEXTENDED_RESET)
#error "You cannot define both CONFIG_FORCE_EXTENDED_RESET and " \
"CONFIG_NOEXTENDED_RESET."
#endif
int debug = 0;
static int debug=0;
static int timingcable = 0;
static int t1e1override = -1; /* deprecated */
static char *default_linemode = "auto";
@@ -214,7 +299,6 @@ struct t4_span {
unsigned long alarmcheck_time;
int spanflags;
int syncpos;
#ifdef SUPPORT_GEN1
int e1check; /* E1 check */
#endif
@@ -238,6 +322,9 @@ struct t4_span {
unsigned long dtmfmask;
unsigned long dtmfmutemask;
#endif
#ifdef ENABLE_WORKQUEUES
struct work_struct swork;
#endif
struct dahdi_chan *chans[32]; /* Individual channels */
struct dahdi_echocan_state *ec[32]; /* Echocan state for each channel */
};
@@ -258,7 +345,6 @@ struct t4 {
int irq; /* IRQ used by device */
int order; /* Order */
const struct devtype *devtype;
unsigned int reset_required:1; /* If reset needed in serial_setup */
unsigned int falc31:1; /* are we falc v3.1 (atomic not necessary) */
unsigned int t1e1:8; /* T1 / E1 select pins */
int ledreg; /* LED Register */
@@ -270,6 +356,10 @@ struct t4 {
int spansstarted; /* number of spans started */
u32 *writechunk; /* Double-word aligned write memory */
u32 *readchunk; /* Double-word aligned read memory */
#ifdef ENABLE_WORKQUEUES
atomic_t worklist;
struct workqueue_struct *workq;
#endif
int last0; /* for detecting double-missed IRQ */
/* DMA related fields */
@@ -278,14 +368,9 @@ struct t4 {
dma_addr_t writedma;
void __iomem *membase; /* Base address of card */
#define T4_CHECK_VPM 0
#define T4_LOADING_FW 1
#define T4_STOP_DMA 2
#define T4_CHECK_TIMING 3
#define T4_CHANGE_LATENCY 4
#define T4_IGNORE_LATENCY 5
/* Flags for our bottom half */
unsigned long checkflag;
struct work_struct bh_work;
struct tasklet_struct t4_tlet;
/* Latency related additions */
unsigned char rxident;
unsigned char lastindex;
@@ -420,7 +505,7 @@ static void t4_check_sigbits(struct t4 *wc, int span);
#define FMR5_EIBR (1 << 6) /* Internal Bit Robbing Access */
#define DEC_T 0x60 /* Diable Error Counter */
#define IERR_T 0x1B /* Single Bit Defect Insertion Register */
#define IBV (1 << 0) /* Bipolar violation */
#define IBV 0 /* Bipolar violation */
#define IPE (1 << 1) /* PRBS defect */
#define ICASE (1 << 2) /* CAS defect */
#define ICRCE (1 << 3) /* CRC defect */
@@ -461,6 +546,8 @@ static void t4_check_sigbits(struct t4 *wc, int span);
#define MAX_T4_CARDS 64
static void t4_isr_bh(unsigned long data);
static struct t4 *cards[MAX_T4_CARDS];
struct t8_firm_header {
@@ -1032,11 +1119,16 @@ static int t4_echocan_create(struct dahdi_chan *chan,
struct t4 *wc = chan->pvt;
struct t4_span *tspan = container_of(chan->span, struct t4_span, span);
int channel;
const struct dahdi_echocan_ops *ops;
const struct dahdi_echocan_features *features;
const bool alaw = (chan->span->deflaw == 2);
if (!vpmsupport || !wc->vpm)
return -ENODEV;
ops = &vpm_ec_ops;
features = &vpm_ec_features;
if (ecp->param_count > 0) {
dev_warn(&wc->dev->dev, "%s echo canceller does not support "
"parameters; failing request\n",
@@ -1045,8 +1137,8 @@ static int t4_echocan_create(struct dahdi_chan *chan,
}
*ec = tspan->ec[chan->chanpos - 1];
(*ec)->ops = &vpm_ec_ops;
(*ec)->features = vpm_ec_features;
(*ec)->ops = ops;
(*ec)->features = *features;
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
@@ -1620,11 +1712,8 @@ _t4_spanconfig(struct file *file, struct dahdi_span *span,
if (lc->sync < 0)
lc->sync = 0;
if (lc->sync > wc->numspans) {
dev_warn(&wc->dev->dev, "WARNING: Cannot set priority on span %d to %d. Please set to a number between 1 and %d\n",
span->spanno, lc->sync, wc->numspans);
if (lc->sync > wc->numspans)
lc->sync = 0;
}
/* remove this span number from the current sync sources, if there */
for(i = 0; i < wc->numspans; i++) {
@@ -1739,6 +1828,16 @@ t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
return 0;
}
static int t4_open(struct dahdi_chan *chan)
{
return 0;
}
static int t4_close(struct dahdi_chan *chan)
{
return 0;
}
static int set_span_devicetype(struct t4 *wc)
{
#ifdef VPM_SUPPORT
@@ -1791,33 +1890,6 @@ static void setup_chunks(struct t4 *wc, int which)
}
}
static int __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags,
bool first_time);
static int __t4_hardware_init_2(struct t4 *wc, bool first_time);
static int t4_hardware_stop(struct t4 *wc);
static void t4_framer_reset(struct t4 *wc)
{
const bool first_time = false;
bool have_vpm = wc->vpm != NULL;
if (have_vpm) {
release_vpm450m(wc->vpm);
wc->vpm = NULL;
}
t4_hardware_stop(wc);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
__t4_hardware_init_1(wc, wc->devtype->flags, first_time);
__t4_hardware_init_2(wc, first_time);
if (have_vpm) {
t4_vpm_init(wc);
wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0;
t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
}
setup_chunks(wc, 0);
wc->lastindex = 0;
}
/**
* t4_serial_setup - Setup serial parameters and system interface.
* @wc: The card to configure.
@@ -1827,7 +1899,6 @@ static void t4_serial_setup(struct t4 *wc)
{
unsigned long flags;
unsigned int unit;
bool reset_required = false;
if (debug) {
dev_info(&wc->dev->dev,
@@ -1835,14 +1906,6 @@ static void t4_serial_setup(struct t4 *wc)
wc->numspans);
}
spin_lock_irqsave(&wc->reglock, flags);
reset_required = wc->reset_required > 0;
wc->reset_required = 0;
spin_unlock_irqrestore(&wc->reglock, flags);
if (reset_required)
t4_framer_reset(wc);
spin_lock_irqsave(&wc->reglock, flags);
/* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from
* channel 0 */
@@ -1993,7 +2056,6 @@ static void t4_span_assigned(struct dahdi_span *span)
struct t4 *wc = tspan->owner;
struct dahdi_span *pos;
unsigned int unassigned_spans = 0;
unsigned long flags;
/* We use this to make sure all the spans are assigned before
* running the serial setup. */
@@ -2002,22 +2064,14 @@ static void t4_span_assigned(struct dahdi_span *span)
++unassigned_spans;
}
if (0 == unassigned_spans) {
if (0 == unassigned_spans)
t4_serial_setup(wc);
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
}
}
static void free_wc(struct t4 *wc)
{
unsigned int x, y;
flush_scheduled_work();
for (x = 0; x < ARRAY_SIZE(wc->tspans); x++) {
if (!wc->tspans[x])
continue;
@@ -2173,7 +2227,6 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
enum linemode mode;
const char *old_name;
static DEFINE_MUTEX(linemode_lock);
unsigned long flags;
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name,
dahdi_spantype2str(linemode));
@@ -2181,10 +2234,6 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
if (span->spantype == linemode)
return 0;
spin_lock_irqsave(&wc->reglock, flags);
wc->reset_required = 1;
spin_unlock_irqrestore(&wc->reglock, flags);
/* Do not allow the t1e1 member to be changed by multiple threads. */
mutex_lock(&linemode_lock);
old_name = dahdi_spantype2str(span->spantype);
@@ -2231,6 +2280,8 @@ static const struct dahdi_span_ops t4_gen1_span_ops = {
.shutdown = t4_shutdown,
.rbsbits = t4_rbsbits,
.maint = t4_maint,
.open = t4_open,
.close = t4_close,
.ioctl = t4_ioctl,
.hdlc_hard_xmit = t4_hdlc_hard_xmit,
.assigned = t4_span_assigned,
@@ -2245,6 +2296,8 @@ static const struct dahdi_span_ops t4_gen2_span_ops = {
.shutdown = t4_shutdown,
.rbsbits = t4_rbsbits,
.maint = t4_maint,
.open = t4_open,
.close = t4_close,
.ioctl = t4_ioctl,
.hdlc_hard_xmit = t4_hdlc_hard_xmit,
.dacs = t4_dacs,
@@ -2617,7 +2670,7 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev
if (lineconfig & DAHDI_CONFIG_AMI) {
line = "AMI";
/* workaround for errata #2 in ES v3 09-10-16 */
fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0;
fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
} else {
line = "B8ZS";
fmr0 = 0xf0;
@@ -2716,7 +2769,7 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
if (lineconfig & DAHDI_CONFIG_AMI) {
line = "AMI";
/* workaround for errata #2 in ES v3 09-10-16 */
fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0;
fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
} else {
line = "HDB3";
fmr0 = 0xf0;
@@ -2777,10 +2830,6 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
__t4_framer_out(wc, unit, 0x17, 0x04 | imr3extra); /* IMR3: AIS */
__t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */
__t4_framer_out(wc, unit, 0x2f, 0x00);
__t4_framer_out(wc, unit, 0x30, 0x00);
__t4_framer_out(wc, unit, 0x31, 0x00);
dev_info(&wc->dev->dev, "TE%dXXP: Span %d configured for %s/%s%s\n",
wc->numspans, unit + 1, framing, line, crc4);
}
@@ -3102,6 +3151,19 @@ static inline void __transmit_span(struct t4_span *ts)
_dahdi_transmit(&ts->span);
}
#ifdef ENABLE_WORKQUEUES
static void workq_handlespan(void *data)
{
struct t4_span *ts = data;
struct t4 *wc = ts->owner;
__receive_span(ts);
__transmit_span(ts);
atomic_dec(&wc->worklist);
if (!atomic_read(&wc->worklist))
t4_pci_out(wc, WC_INTR, 0);
}
#else
static void t4_prep_gen2(struct t4 *wc)
{
int x;
@@ -3113,6 +3175,7 @@ static void t4_prep_gen2(struct t4 *wc)
}
}
#endif
#ifdef SUPPORT_GEN1
static void t4_transmitprep(struct t4 *wc, int irq)
{
@@ -3189,6 +3252,8 @@ static void t4_check_sigbits(struct t4 *wc, int span)
dev_notice(&wc->dev->dev, "Checking sigbits on span %d\n",
span + 1);
if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
return;
if (E1 == ts->linemode) {
for (i = 0; i < 15; i++) {
a = t4_framer_in(wc, span, 0x71 + i);
@@ -3578,7 +3643,6 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
struct t4_span *ts = wc->tspans[span];
struct dahdi_chan *sigchan;
unsigned long flags;
bool recheck_sigbits = false;
/* 1st gen cards isn't used interrupts */
@@ -3604,8 +3668,6 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
ts->span.count.ebit += __t4_framer_in(wc, span, EBCL_T);
ts->span.count.be += __t4_framer_in(wc, span, BECL_T);
ts->span.count.prbs = __t4_framer_in(wc, span, FRS1_T);
if (DAHDI_RXSIG_INITIAL == ts->span.chans[0]->rxhooksig)
recheck_sigbits = true;
}
spin_unlock_irqrestore(&wc->reglock, flags);
@@ -3614,7 +3676,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
ts->span.count.errsec += 1;
}
if (isr0 & 0x08 || recheck_sigbits)
if (isr0)
t4_check_sigbits(wc, span);
if (E1 == ts->linemode) {
@@ -3837,7 +3899,7 @@ static irqreturn_t _t4_interrupt(int irq, void *dev_id)
return IRQ_RETVAL(1);
}
static irqreturn_t t4_interrupt(int irq, void *dev_id)
DAHDI_IRQ_HANDLER(t4_interrupt)
{
irqreturn_t ret;
unsigned long flags;
@@ -3941,9 +4003,9 @@ static void t4_increase_latency(struct t4 *wc, int newlatency)
}
static void t4_work_func(struct work_struct *work)
static void t4_isr_bh(unsigned long data)
{
struct t4 *wc = container_of(work, struct t4, bh_work);
struct t4 *wc = (struct t4 *)data;
if (test_bit(T4_CHANGE_LATENCY, &wc->checkflag)) {
if (wc->needed_latency != wc->numbufs) {
@@ -3990,6 +4052,10 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
return IRQ_NONE;
}
#ifdef ENABLE_WORKQUEUES
__t4_pci_out(wc, WC_INTR, status & 0x00000008);
#endif
if (unlikely(!wc->spansstarted)) {
dev_info(&wc->dev->dev, "Not prepped yet!\n");
return IRQ_NONE;
@@ -4052,6 +4118,28 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
#endif
if (likely(status & 0x2)) {
#ifdef ENABLE_WORKQUEUES
int cpus = num_online_cpus();
atomic_set(&wc->worklist, wc->numspans);
if (wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)
t4_queue_work(wc->workq, &wc->tspans[0]->swork, 0);
else
atomic_dec(&wc->worklist);
if (wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)
t4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus);
else
atomic_dec(&wc->worklist);
if (wc->numspans == 4) {
if (wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)
t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus);
else
atomic_dec(&wc->worklist);
if (wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)
t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus);
else
atomic_dec(&wc->worklist);
}
#else
unsigned int reg5 = __t4_pci_in(wc, 5);
#ifdef DEBUG
@@ -4071,6 +4159,7 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
t4_prep_gen2(wc);
}
#endif
t4_do_counters(wc);
spin_lock(&wc->reglock);
__handle_leds(wc);
@@ -4123,13 +4212,16 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
out:
if (unlikely(test_bit(T4_CHANGE_LATENCY, &wc->checkflag) || test_bit(T4_CHECK_VPM, &wc->checkflag)))
schedule_work(&wc->bh_work);
tasklet_schedule(&wc->t4_tlet);
#ifndef ENABLE_WORKQUEUES
__t4_pci_out(wc, WC_INTR, 0);
#endif
return IRQ_RETVAL(1);
}
static irqreturn_t t4_interrupt_gen2(int irq, void *dev_id)
DAHDI_IRQ_HANDLER(t4_interrupt_gen2)
{
irqreturn_t ret;
unsigned long flags;
@@ -4214,7 +4306,7 @@ static void t4_vpm_init(struct t4 *wc)
laws[x] = 1;
}
vpm_capacity = get_vpm450m_capacity(&wc->dev->dev);
vpm_capacity = get_vpm450m_capacity(wc);
if (vpm_capacity != wc->numspans * 32) {
dev_info(&wc->dev->dev, "Disabling VPMOCT%03d. TE%dXXP"\
" requires a VPMOCT%03d", vpm_capacity,
@@ -4286,8 +4378,7 @@ static void t4_vpm_init(struct t4 *wc)
return;
}
wc->vpm = init_vpm450m(&wc->dev->dev, laws, wc->numspans, firmware);
if (!wc->vpm) {
if (!(wc->vpm = init_vpm450m(wc, laws, wc->numspans, firmware))) {
dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n");
if (firmware != &embedded_firmware)
release_firmware(firmware);
@@ -4774,23 +4865,25 @@ cleanup:
return res;
}
static int
__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
{
unsigned int version;
int res;
version = t4_pci_in(wc, WC_VERSION);
if (is_octal(wc) && first_time) {
if (is_octal(wc)) {
dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n",
(version & 0xf00) >> 8,
version & 0xff);
} else if (first_time) {
} else {
dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version);
}
if (debug) {
dev_info(&wc->dev->dev, "Burst Mode: %s\n",
(!(cardflags & FLAG_BURST) && noburst) ? "Off" : "On");
#ifdef ENABLE_WORKQUEUES
dev_info(&wc->dev->dev, "Work Queues: Enabled\n");
#endif
}
/* Check the field updatable firmware for the wcte820 */
@@ -4830,33 +4923,30 @@ __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
t4_pci_out(wc, WC_INTR, 0x00000000);
/* Read T1/E1 status */
if (first_time) {
if (!strcasecmp("auto", default_linemode)) {
if (-1 == t1e1override) {
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) &
0x0f00) >> 8);
wc->t1e1 &= 0xf;
if (is_octal(wc)) {
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
0x0f00) >> 4;
}
} else {
dev_warn(&wc->dev->dev,
"'t1e1override' is deprecated. Please use 'default_linemode'.\n");
wc->t1e1 = t1e1override & 0xf;
if (!strcasecmp("auto", default_linemode)) {
if (-1 == t1e1override) {
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8);
wc->t1e1 &= 0xf;
if (is_octal(wc)) {
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
0x0f00) >> 4;
}
} else if (!strcasecmp("t1", default_linemode)) {
wc->t1e1 = 0;
} else if (!strcasecmp("e1", default_linemode)) {
wc->t1e1 = 0xff;
} else if (!strcasecmp("j1", default_linemode)) {
wc->t1e1 = 0;
j1mode = 1;
} else {
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
default_linemode);
wc->t1e1 = 0;
dev_warn(&wc->dev->dev, "'t1e1override' is deprecated. "
"Please use 'default_linemode'.\n");
wc->t1e1 = t1e1override & 0xf;
}
} else if (!strcasecmp("t1", default_linemode)) {
wc->t1e1 = 0;
} else if (!strcasecmp("e1", default_linemode)) {
wc->t1e1 = 0xff;
} else if (!strcasecmp("j1", default_linemode)) {
wc->t1e1 = 0;
j1mode = 1;
} else {
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
default_linemode);
wc->t1e1 = 0;
}
wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28;
@@ -4885,12 +4975,7 @@ __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
return 0;
}
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
{
return __t4_hardware_init_1(wc, cardflags, true);
}
static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
static int t4_hardware_init_2(struct t4 *wc)
{
int x;
unsigned int regval;
@@ -4922,14 +5007,13 @@ static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
if (!is_octal(wc)) {
regval = t4_framer_in(wc, 0, 0x4a);
if (first_time && regval == 0x05) {
if (regval == 0x05) {
dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or "
"earlier\n");
} else if (regval == 0x20) {
if (first_time)
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
wc->falc31 = 1;
} else if (first_time) {
} else {
dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
"(VSTR = 0x%02x)\n", regval);
}
@@ -4949,24 +5033,14 @@ static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
t4_pci_in(wc, x));
}
}
wc->gpio = 0x00000000;
t4_pci_out(wc, WC_GPIO, wc->gpio);
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
t4_gpio_setdir(wc, (0xff), (0xff));
return 0;
}
static int t4_hardware_init_2(struct t4 *wc)
{
return __t4_hardware_init_2(wc, true);
}
static int __devinit t4_launch(struct t4 *wc)
{
int x;
int res;
unsigned long flags;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
return 0;
@@ -4998,14 +5072,17 @@ static int __devinit t4_launch(struct t4 *wc)
&wc->ddev->spans);
}
INIT_WORK(&wc->bh_work, t4_work_func);
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
if (res) {
dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n");
return res;
}
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
return 0;
}
@@ -5149,6 +5226,15 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
wc->num = x;
cards[x] = wc;
#ifdef ENABLE_WORKQUEUES
if (wc->devtype->flags & FLAG_2NDGEN) {
char tmp[20];
sprintf(tmp, "te%dxxp[%d]", wc->numspans, wc->num);
wc->workq = create_workqueue(tmp);
}
#endif
/* Allocate pieces we need here */
for (x = 0; x < ports_on_framer(wc); x++) {
struct t4_span *ts;
@@ -5161,6 +5247,9 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
wc->tspans[x] = ts;
#ifdef ENABLE_WORKQUEUES
INIT_WORK(&ts->swork, workq_handlespan, ts);
#endif
ts->spanflags |= wc->devtype->flags;
linemode = (wc->t1e1 & (1 << x)) ? E1 : ((j1mode) ? J1 : T1);
t4_alloc_channels(wc, wc->tspans[x], linemode);
@@ -5172,7 +5261,7 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef SUPPORT_GEN1
if (request_irq(pdev->irq, (wc->devtype->flags & FLAG_2NDGEN) ?
t4_interrupt_gen2 : t4_interrupt,
IRQF_SHARED,
DAHDI_IRQ_SHARED,
(wc->numspans == 8) ? "wct8xxp" :
(wc->numspans == 2) ? "wct2xxp" :
"wct4xxp",
@@ -5186,7 +5275,7 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
if (request_irq(pdev->irq, t4_interrupt_gen2,
IRQF_SHARED, "t4xxp", wc)) {
DAHDI_IRQ_SHARED, "t4xxp", wc)) {
#endif
dev_notice(&wc->dev->dev, "Unable to request IRQ %d\n",
pdev->irq);
@@ -5207,6 +5296,10 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&wc->dev->dev,
"Found a Wildcard: %s\n", wc->devtype->desc);
}
wc->gpio = 0x00000000;
t4_pci_out(wc, WC_GPIO, wc->gpio);
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
t4_gpio_setdir(wc, (0xff), (0xff));
#ifdef VPM_SUPPORT
if (!wc->vpm) {
@@ -5300,6 +5393,13 @@ static void _t4_remove_one(struct t4 *wc)
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN))
basesize = basesize * 2;
#ifdef ENABLE_WORKQUEUES
if (wc->workq) {
flush_workqueue(wc->workq);
destroy_workqueue(wc->workq);
}
#endif
free_irq(wc->dev->irq, wc);
if (wc->membase)
@@ -5387,7 +5487,7 @@ static int __init t4_init(void)
"Please use 'default_linemode' instead.\n");
}
res = pci_register_driver(&t4_driver);
res = dahdi_pci_module(&t4_driver);
if (res)
return -ENODEV;

View File

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

View File

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

View File

@@ -131,6 +131,13 @@ struct t4_reg {
unsigned int val;
};
#define T4_CHECK_VPM 0
#define T4_LOADING_FW 1
#define T4_STOP_DMA 2
#define T4_CHECK_TIMING 3
#define T4_CHANGE_LATENCY 4
#define T4_IGNORE_LATENCY 5
#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)

File diff suppressed because it is too large Load Diff

2881
drivers/dahdi/wctdm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -44,15 +44,17 @@ 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>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
#include <linux/crc32.h>
#include <linux/slab.h>
#include <stdbool.h>
@@ -69,10 +71,6 @@ 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"
@@ -328,9 +326,15 @@ struct bg {
int ret;
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void bg_work_func(void *data)
{
struct bg *bg = data;
#else
static void bg_work_func(struct work_struct *work)
{
struct bg *bg = container_of(work, struct bg, work);
#endif
bg->ret = bg->fn(bg->wc, bg->param);
complete(&bg->complete);
}
@@ -367,7 +371,11 @@ bg_create(struct wctdm *wc, bg_work_func_t fn, unsigned long param)
}
init_completion(&bg->complete);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&bg->work, bg_work_func, bg);
#else
INIT_WORK(&bg->work, bg_work_func);
#endif
bg->wc = wc;
bg->fn = fn;
@@ -449,10 +457,16 @@ struct vpmadt032_channel_setup {
struct wctdm *wc;
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void vpm_setup_work_func(void *data)
{
struct vpmadt032_channel_setup *setup = data;
#else
static void vpm_setup_work_func(struct work_struct *work)
{
struct vpmadt032_channel_setup *setup =
container_of(work, struct vpmadt032_channel_setup, work);
#endif
int i;
int res;
GpakChannelConfig_t chanconfig;
@@ -614,7 +628,13 @@ static int config_vpmadt032(struct vpmadt032 *vpm, struct wctdm *wc)
return -ENOMEM;
setup->wc = wc;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&setup->work, vpm_setup_work_func, setup);
#else
INIT_WORK(&setup->work, vpm_setup_work_func);
#endif
queue_work(vpm->wq, &setup->work);
return 0;
@@ -1955,14 +1975,12 @@ wctdm_check_battery_lost(struct wctdm *wc, struct wctdm_module *const mod)
break;
case BATTERY_UNKNOWN:
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
/* fallthrough */
case BATTERY_PRESENT:
fxo->battery_state = BATTERY_DEBOUNCING_LOST;
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM:
/* fallthrough */
case BATTERY_DEBOUNCING_LOST:
case BATTERY_DEBOUNCING_LOST: /* Intentional drop through */
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
if (debug) {
dev_info(&wc->vb.pdev->dev,
@@ -2065,8 +2083,7 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
break;
case BATTERY_UNKNOWN:
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
/* fallthrough */
case BATTERY_LOST:
case BATTERY_LOST: /* intentional drop through */
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT;
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
@@ -3083,8 +3100,6 @@ wctdm_init_voicedaa(struct wctdm *wc, struct wctdm_module *mod,
spin_unlock_irqrestore(&wc->reglock, flags);
msleep(20);
memset(&mod->mod.fxo, 0, sizeof(mod->mod.fxo));
if (!sane && wctdm_voicedaa_insane(wc, mod))
return -2;
@@ -3229,7 +3244,8 @@ wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod,
return -2;
/* Initialize VMWI settings */
memset(fxs, 0, sizeof(*fxs));
memset(&(fxs->vmwisetting), 0, sizeof(fxs->vmwisetting));
fxs->vmwi_linereverse = 0;
/* By default, don't send on hook */
if (!reversepolarity != !fxs->reversepolarity)
@@ -4368,6 +4384,32 @@ wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
return wctdm_wait_for_ready(wc);
}
/*
* wctdm24xxp_assigned - Called when span is assigned.
* @span: The span that is now assigned.
*
* This function is called by the core of DAHDI after the span number and
* channel numbers have been assigned.
*
*/
static void wctdm24xxp_assigned(struct dahdi_span *span)
{
struct dahdi_span *s;
struct dahdi_device *ddev = span->parent;
struct wctdm *wc = NULL;
list_for_each_entry(s, &ddev->spans, device_node) {
wc = (container_of(s, struct wctdm_span, span))->wc;
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
return;
}
if (wc) {
WARN_ON(0 == wc->not_ready);
--wc->not_ready;
}
}
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.owner = THIS_MODULE,
.hooksig = wctdm_hooksig,
@@ -4377,6 +4419,7 @@ static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.watchdog = wctdm_watchdog,
.chanconfig = wctdm_chanconfig,
.dacs = wctdm_dacs,
.assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -4395,6 +4438,7 @@ static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = {
.spanconfig = b400m_spanconfig,
.chanconfig = b400m_chanconfig,
.dacs = wctdm_dacs,
.assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -5907,9 +5951,6 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return -1;
}
WARN_ON(wc->not_ready <= 0);
--wc->not_ready;
dev_info(&wc->vb.pdev->dev,
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
(is_hx8(wc)) ? "Hybrid card" : "Wildcard TDM",
@@ -6029,7 +6070,11 @@ 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 }
@@ -6105,7 +6150,7 @@ static int __init wctdm_init(void)
b400m_module_init();
res = pci_register_driver(&wctdm_driver);
res = dahdi_pci_module(&wctdm_driver);
if (res)
return -ENODEV;

View File

@@ -29,7 +29,11 @@
#include <dahdi/kernel.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
#include "voicebus/voicebus.h"

View File

@@ -25,7 +25,6 @@
#include <linux/ppp_defs.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#define FAST_HDLC_NEED_TABLES
#include <dahdi/kernel.h>
@@ -2386,9 +2385,15 @@ int b400m_dchan(struct dahdi_span *span)
/*
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void xhfc_work(void *data)
{
struct b400m *b4 = data;
#else
static void xhfc_work(struct work_struct *work)
{
struct b400m *b4 = container_of(work, struct b400m, xhfc_wq);
#endif
int i, j, k, fifo;
unsigned char b, b2;
@@ -2558,10 +2563,9 @@ static int b400m_probe(struct wctdm *wc, int modpos)
struct b400m *b4;
unsigned long flags;
int chiprev;
u8 lastreg = 0;
wctdm_setreg(wc, &wc->mods[modpos], 0x10, 0x10);
id = xhfc_getreg(wc, &wc->mods[modpos], R_CHIP_ID, &lastreg);
id = xhfc_getreg(wc, &wc->mods[modpos], R_CHIP_ID, &x);
/* chip ID high 7 bits must be 0x62, see datasheet */
if ((id & 0xfe) != 0x62)
@@ -2576,7 +2580,6 @@ static int b400m_probe(struct wctdm *wc, int modpos)
/* card found, enabled and main struct allocated. Fill it out. */
b4->wc = wc;
b4->lastreg = lastreg;
b4->position = modpos;
/* which B400M in the system is this one? count all of them found so
@@ -2626,7 +2629,11 @@ void b400m_post_init(struct b400m *b4)
snprintf(b4->name, sizeof(b4->name) - 1, "b400m-%d",
b4->b400m_no);
b4->xhfc_ws = create_singlethread_workqueue(b4->name);
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&b4->xhfc_wq, xhfc_work, b4);
# else
INIT_WORK(&b4->xhfc_wq, xhfc_work);
# endif
b4->inited = 1;
}

1642
drivers/dahdi/wcte11xp.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,167 @@
/*
* 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,193 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __WCXB_H__
#define __WCXB_H__
#define WCXB_DEFAULT_LATENCY 3U
#define WCXB_DEFAULT_MAXLATENCY 12U
#define WCXB_DMA_CHAN_SIZE 128
struct wcxb;
struct wcxb_operations {
void (*handle_receive)(struct wcxb *xb, void *frame);
void (*handle_transmit)(struct wcxb *xb, void *frame);
void (*handle_error)(struct wcxb *xb);
void (*handle_interrupt)(struct wcxb *xb, u32 pending);
};
struct wcxb_meta_desc;
struct wcxb_hw_desc;
/**
* struct wcxb - Interface to wcxb firmware.
* @last_retry_count: Running count of times firmware had to retry host DMA
* transaction. Debugging aide.
*/
struct wcxb {
struct pci_dev *pdev;
spinlock_t lock;
const struct wcxb_operations *ops;
unsigned int *debug;
unsigned int max_latency;
unsigned int latency;
struct {
u32 have_msi:1;
u32 latency_locked:1;
u32 drive_timing_cable:1;
u32 dma_ins:1;
} flags;
void __iomem *membase;
struct wcxb_meta_desc *meta_dring;
struct wcxb_hw_desc *hw_dring;
unsigned int dma_head;
unsigned int dma_tail;
dma_addr_t hw_dring_phys;
struct dma_pool *pool;
unsigned long framecount;
#ifdef DEBUG
u8 last_retry_count;
u8 max_retry_count;
u32 last_dma_time;
u32 max_dma_time;
#endif
};
extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode);
extern void wcxb_release(struct wcxb *xb);
extern int wcxb_start(struct wcxb *xb);
extern void wcxb_stop(struct wcxb *xb);
extern int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms);
extern bool wcxb_is_stopped(struct wcxb *xb);
enum wcxb_clock_sources {
WCXB_CLOCK_SELF, /* Use the internal oscillator for timing. */
WCXB_CLOCK_RECOVER, /* Recover the clock from a framer. */
#ifdef RPC_RCLK
WCXB_CLOCK_RECOVER_ALT, /* Recover the clock from a framer. */
#endif
WCXB_CLOCK_SLAVE /* Recover clock from any timing header. */
};
extern enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb);
extern void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc);
static inline void wcxb_enable_timing_header_driver(struct wcxb *xb)
{
xb->flags.drive_timing_cable = 1;
}
static inline bool wcxb_is_timing_header_driver_enabled(struct wcxb *xb)
{
return 1 == xb->flags.drive_timing_cable;
}
static inline void wcxb_disable_timing_header_driver(struct wcxb *xb)
{
xb->flags.drive_timing_cable = 0;
}
enum wcxb_reset_option {
WCXB_RESET_NOW,
WCXB_RESET_LATER
};
extern u32 wcxb_get_firmware_version(struct wcxb *xb);
extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
const char *firmware_filename,
bool force_firmware,
enum wcxb_reset_option reset);
extern void wcxb_stop_dma(struct wcxb *xb);
extern void wcxb_disable_interrupts(struct wcxb *xb);
static inline void wcxb_gpio_set(struct wcxb *xb, u32 bits)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be(reg | bits, xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void wcxb_gpio_clear(struct wcxb *xb, u32 bits)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be(reg & (~bits), xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_set_maxlatency(struct wcxb *xb, unsigned int max_latency)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->max_latency = clamp(max_latency,
xb->latency,
WCXB_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_set_minlatency(struct wcxb *xb, unsigned int min_latency)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->latency = clamp(min_latency, WCXB_DEFAULT_LATENCY,
WCXB_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_lock_latency(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->flags.latency_locked = 1;
spin_unlock_irqrestore(&xb->lock, flags);
return;
}
static inline void
wcxb_unlock_latency(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->flags.latency_locked = 0;
spin_unlock_irqrestore(&xb->lock, flags);
return;
}
/* Interface for the echocan block */
extern void wcxb_enable_echocan(struct wcxb *xb);
extern void wcxb_disable_echocan(struct wcxb *xb);
extern void wcxb_reset_echocan(struct wcxb *xb);
extern void wcxb_enable_echocan_dram(struct wcxb *xb);
extern bool wcxb_is_echocan_present(struct wcxb *xb);
extern u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address);
extern void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val);
#endif

View File

@@ -1,170 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/sched.h>
#include "wcxb_spi.h"
#include "wcxb_flash.h"
#define FLASH_PAGE_PROGRAM 0x02
#define FLASH_READ 0x03
#define FLASH_READ_STATUS 0x05
#define FLASH_WRITE_ENABLE 0x06
#define FLASH_SECTOR_ERASE 0xd8
static int wcxb_flash_read_status_register(struct wcxb_spi_device *spi,
u8 *status)
{
u8 command[] = {
FLASH_READ_STATUS,
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_serial = {
.rx_buf = status,
.len = 1,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_serial, &m);
return wcxb_spi_sync(spi, &m);
}
int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address,
void *data, size_t len)
{
u8 command[] = {
FLASH_READ,
(address & 0xff0000) >> 16,
(address & 0xff00) >> 8,
(address & 0xff)
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_serial = {
.rx_buf = data,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_serial, &m);
return wcxb_spi_sync(spi, &m);
}
static int wcxb_flash_wait_until_not_busy(struct wcxb_spi_device *spi)
{
int res;
u8 status;
unsigned long stop = jiffies + 5*HZ;
do {
res = wcxb_flash_read_status_register(spi, &status);
} while (!res && (status & 0x1) && time_before(jiffies, stop));
if (!res)
return res;
if (time_after_eq(jiffies, stop))
return -EIO;
return 0;
}
static int wcxb_flash_write_enable(struct wcxb_spi_device *spi)
{
u8 command = FLASH_WRITE_ENABLE;
return wcxb_spi_write(spi, &command, 1);
}
int wcxb_flash_sector_erase(struct wcxb_spi_device *spi,
unsigned int address)
{
int res;
u8 command[] = {FLASH_SECTOR_ERASE, (address >> 16)&0xff, 0x00, 0x00};
/* Sector must be on 64KB boundary. */
if (address & 0xffff)
return -EINVAL;
/* Start the erase. */
res = wcxb_flash_write_enable(spi);
if (res)
return res;
res = wcxb_spi_write(spi, &command, sizeof(command));
if (res)
return res;
return wcxb_flash_wait_until_not_busy(spi);
}
int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address,
const void *data, size_t len)
{
int res;
const size_t FLASH_PAGE_SIZE = 256;
u8 command[] = {
FLASH_PAGE_PROGRAM,
(address & 0xff0000) >> 16,
(address & 0xff00) >> 8,
0x00,
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_data = {
.tx_buf = data,
.len = len,
};
struct wcxb_spi_message m;
/* We need to write on page size boundaries */
WARN_ON(address & 0xff);
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_data, &m);
while (len) {
res = wcxb_flash_write_enable(spi);
if (res)
return res;
command[1] = (address >> 16) & 0xff;
command[2] = (address >> 8) & 0xff;
t_data.tx_buf = data;
t_data.len = min(len, FLASH_PAGE_SIZE);
res = wcxb_spi_sync(spi, &m);
WARN_ON(res);
if (res)
return res;
res = wcxb_flash_wait_until_not_busy(spi);
WARN_ON(res);
if (res)
return res;
len -= t_data.len;
address += t_data.len;
data += t_data.len;
}
return 0;
}

View File

@@ -1,34 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __WCXB_FLASH_H__
#define __WCXB_FLASH_H__
extern int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address,
void *data, size_t len);
extern int wcxb_flash_sector_erase(struct wcxb_spi_device *spi, unsigned int
address);
extern int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address,
const void *data, size_t len);
#endif

View File

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

View File

@@ -1,116 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __WCXB_SPI_H
#define __WCXB_SPI_H
#include <linux/spi/spi.h>
#include <stdbool.h>
struct wcxb_spi_transfer {
const void *tx_buf;
void *rx_buf;
u32 len:16;
u16 delay_usecs;
struct list_head node;
};
struct wcxb_spi_message {
struct list_head transfers;
struct list_head node;
struct wcxb_spi_device *spi;
void (*complete)(void *arg);
void *arg;
int status;
};
struct wcxb_spi_master;
struct wcxb_spi_device {
struct wcxb_spi_master *master;
u16 chip_select;
};
extern struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent,
void __iomem *base, bool auto_cs);
extern void wcxb_spi_master_destroy(struct wcxb_spi_master *master);
extern int wcxb_spi_sync(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message);
extern int wcxb_spi_async(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message);
extern void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master);
static inline struct wcxb_spi_device *
wcxb_spi_device_create(struct wcxb_spi_master *master, u16 chip_select)
{
struct wcxb_spi_device *spi = kzalloc(sizeof(*spi), GFP_KERNEL);
if (!spi)
return NULL;
spi->master = master;
spi->chip_select = chip_select;
return spi;
}
static inline void wcxb_spi_device_destroy(struct wcxb_spi_device *spi)
{
kfree(spi);
}
static inline void wcxb_spi_message_init(struct wcxb_spi_message *m)
{
memset(m, 0, sizeof(*m));
INIT_LIST_HEAD(&m->transfers);
}
static inline void wcxb_spi_message_add_tail(struct wcxb_spi_transfer *t,
struct wcxb_spi_message *m)
{
list_add_tail(&t->node, &m->transfers);
}
static inline int
wcxb_spi_write(struct wcxb_spi_device *spi, const void *buffer, size_t len)
{
struct wcxb_spi_transfer t = {
.tx_buf = buffer,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t, &m);
return wcxb_spi_sync(spi, &m);
}
static inline int
wcxb_spi_read(struct wcxb_spi_device *spi, void *buffer, size_t len)
{
struct wcxb_spi_transfer t = {
.rx_buf = buffer,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t, &m);
return wcxb_spi_sync(spi, &m);
}
#endif

View File

@@ -36,9 +36,20 @@ EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT
obj-m += parport_debug.o
endif
# Just in case it was left from an older version:
# Handle versioning
XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi)
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_*
@@ -57,8 +68,8 @@ xpp_verified = $(foreach file, $(xpp_verifications), $(file).verified)
FXO_MODES = $(src)/../fxo_modes.h
FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
hostprogs := print_fxo_modes
always-y := $(xpp_verified)
hostprogs-y := print_fxo_modes
always := $(xpp_verified) xpp_version.h
print_fxo_modes-objs := print_fxo_modes.o
HOSTCFLAGS_print_fxo_modes.o += -include $(FXO_MODES)

View File

@@ -153,12 +153,8 @@ static int write_state_register(xpd_t *xpd, __u8 value);
static bool bri_packet_is_valid(xpacket_t *pack);
static void bri_packet_dump(const char *msg, xpacket_t *pack);
#ifdef CONFIG_PROC_FS
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops proc_bri_info_ops;
#else
static const struct file_operations proc_bri_info_ops;
#endif
#endif
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc);
static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
@@ -166,6 +162,7 @@ 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 {
@@ -471,8 +468,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
int ret = 0;
src = REG_XDATA(regcmd);
len = regcmd->h.bytes;
eoframe = regcmd->h.eoframe;
len = regcmd->bytes;
eoframe = regcmd->eoframe;
if (len <= 0)
return 0;
if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */
@@ -568,12 +565,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) = XFRAME_CMD_LEN(REG);
XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->h.bytes = len;
reg_cmd->h.is_multibyte = 1;
reg_cmd->h.portnum = xpd->addr.subunit;
reg_cmd->h.eoframe = eoframe;
reg_cmd->bytes = len;
reg_cmd->is_multibyte = 1;
reg_cmd->portnum = xpd->addr.subunit;
reg_cmd->eoframe = eoframe;
p = REG_XDATA(reg_cmd);
memcpy(p, buf, len);
if (debug)
@@ -614,7 +611,7 @@ static int tx_dchan(xpd_t *xpd)
return -ENOMEM;
}
for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
int packet_len = XFRAME_CMD_LEN(REG);
int packet_len = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
char buf[MULTIBYTE_MAX_LEN];
int len = MULTIBYTE_MAX_LEN;
@@ -690,29 +687,20 @@ 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,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
{
xpd_t *xpd = NULL;
int channels = min(3, CHANNELS_PERXPD);
if ((unit_descriptor->ports_per_chip < 1) ||
(unit_descriptor->ports_per_chip > 4)) {
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
unit_descriptor->ports_per_chip);
return NULL;
}
if ((unit_descriptor->numchips) < 1 ||
(unit_descriptor->numchips > 2)) {
XBUS_ERR(xbus, "Bad numchips=%d\n",
unit_descriptor->numchips);
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit,
sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct BRI_priv_data), proto_table, channels);
if (!xpd)
return NULL;
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
@@ -989,8 +977,7 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
0, /* data_low */
0, /* do_datah */
0, /* data_high */
0, /* should_reply */
0 /* do_expander */
0 /* should_reply */
);
if (IS_NT(xpd) && nt_keepalive
@@ -1439,8 +1426,7 @@ static int write_state_register(xpd_t *xpd, __u8 value)
value, /* data_low */
0, /* do_datah */
0, /* data_high */
0, /* should_reply */
0 /* do_expander */
0 /* should_reply */
);
return ret;
}
@@ -1552,7 +1538,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->h.portnum;
addr.subunit = info->portnum;
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
if (!xpd) {
static int rate_limit;
@@ -1577,9 +1563,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->h.is_multibyte) {
if (info->is_multibyte) {
XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
info->h.bytes, info->h.eoframe);
info->bytes, info->eoframe);
ret = rx_dchan(xpd, info);
if (ret < 0) {
priv->dchan_rx_drops++;
@@ -1744,22 +1730,13 @@ static int proc_bri_info_open(struct inode *inode, struct file *file)
return single_open(file, proc_bri_info_show, PDE_DATA(inode));
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops proc_bri_info_ops = {
.proc_open = proc_bri_info_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations proc_bri_info_ops = {
.owner = THIS_MODULE,
.open = proc_bri_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
.open = proc_bri_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif /* DAHDI_HAVE_PROC_OPS */
#endif
static int bri_xpd_probe(struct device *dev)
@@ -1768,9 +1745,9 @@ static int bri_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->xpd_type != XPD_TYPE_BRI) {
if (xpd->type != XPD_TYPE_BRI) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->xpd_type);
xpd->type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -1787,7 +1764,7 @@ static int bri_xpd_remove(struct device *dev)
}
static struct xpd_driver bri_driver = {
.xpd_type = XPD_TYPE_BRI,
.type = XPD_TYPE_BRI,
.driver = {
.name = "bri",
.owner = THIS_MODULE,
@@ -1801,6 +1778,7 @@ 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;
}
@@ -1815,6 +1793,7 @@ static void __exit card_bri_cleanup(void)
MODULE_DESCRIPTION("XPP BRI Card Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
MODULE_ALIAS_XPD(XPD_TYPE_BRI);
module_init(card_bri_startup);

View File

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

View File

@@ -100,25 +100,22 @@ 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, 0)
(writing), (reg), 0, 0, (dL), 0, 0, 0)
/*---------------- FXO Protocol Commands ----------------------------------*/
static bool fxo_packet_is_valid(xpacket_t *pack);
static void fxo_packet_dump(const char *msg, xpacket_t *pack);
#ifdef CONFIG_PROC_FS
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops proc_fxo_info_ops;
#else
static const struct file_operations proc_fxo_info_ops;
#endif
#ifdef WITH_METERING
static const struct proc_ops proc_xpd_metering_ops;
static const struct file_operations proc_xpd_metering_ops;
#endif
#endif
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"
@@ -491,13 +488,11 @@ 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,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
{
xpd_t *xpd = NULL;
int channels;
int subunit_ports;
if (to_phone) {
XBUS_NOTICE(xbus,
@@ -506,14 +501,13 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
unit, subunit);
return NULL;
}
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
if (unit_descriptor->subtype == 2)
if (subtype == 2)
channels = min(2, subunit_ports);
else
channels = min(8, subunit_ports);
xpd =
xpd_alloc(xbus, unit, subunit,
sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels);
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct FXO_priv_data), proto_table, channels);
if (!xpd)
return NULL;
PHONEDEV(xpd).direction = TO_PSTN;
@@ -624,6 +618,7 @@ 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);
@@ -632,23 +627,6 @@ 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;
@@ -1269,7 +1247,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->h.portnum;
portno = info->portnum;
switch (REG_FIELD(info, regnum)) {
case REG_INTERRUPT_SRC:
got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
@@ -1287,7 +1265,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->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
((info->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) ==
@@ -1334,7 +1312,6 @@ 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) = {
@@ -1488,22 +1465,13 @@ static int proc_fxo_info_open(struct inode *inode, struct file *file)
return single_open(file, proc_fxo_info_show, PDE_DATA(inode));
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops proc_fxo_info_ops = {
.proc_open = proc_fxo_info_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations proc_fxo_info_ops = {
.owner = THIS_MODULE,
.open = proc_fxo_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
.open = proc_fxo_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
#ifdef WITH_METERING
static int proc_xpd_metering_show(struct seq_file *sfile, void *not_used)
@@ -1585,9 +1553,9 @@ static int fxo_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->xpd_type != XPD_TYPE_FXO) {
if (xpd->type != XPD_TYPE_FXO) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->xpd_type);
xpd->type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -1613,7 +1581,7 @@ static int fxo_xpd_remove(struct device *dev)
}
static struct xpd_driver fxo_driver = {
.xpd_type = XPD_TYPE_FXO,
.type = XPD_TYPE_FXO,
.driver = {
.name = "fxo",
.owner = THIS_MODULE,
@@ -1632,6 +1600,7 @@ 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
@@ -1650,6 +1619,7 @@ 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);

File diff suppressed because it is too large Load Diff

View File

@@ -56,12 +56,12 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
* eoftx==1: Start sending us D-channel packets.
* eoftx==0: Stop sending us D-channel packets.
*/
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit);
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->h.bytes = 0;
reg_cmd->h.is_multibyte = 1;
reg_cmd->h.portnum = portno;
reg_cmd->h.eoframe = eoftx;
reg_cmd->bytes = 0;
reg_cmd->is_multibyte = 1;
reg_cmd->portnum = portno;
reg_cmd->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,14 +90,13 @@ 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, [R]AM */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
bool do_subreg = 0;
int regnum;
int subreg;
int data_low;
bool do_datah;
int data_high;
bool do_expander = 0;
int ret = -EBADR;
num_args = 2; /* port + operation */
@@ -159,12 +158,6 @@ 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') {
@@ -176,16 +169,6 @@ 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;
@@ -214,32 +197,6 @@ 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) {
@@ -307,17 +264,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 do_expander=%d\n",
"dataL=%d do_datah=%d dataH=%d\n",
portno, /* portno */
writing, /* writing */
regnum, do_subreg, /* use subreg */
subreg, /* subreg */
data_low, do_datah, /* use data_high */
data_high, do_expander);
data_high);
#endif
ret = xpp_register_request(xpd->xbus, xpd, portno,
writing, regnum, do_subreg, subreg,
data_low, do_datah, data_high, 1, do_expander);
data_low, do_datah, data_high, 1);
out:
return ret;
}
@@ -405,7 +362,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 do_expander)
bool should_reply)
{
int ret = 0;
xframe_t *xframe;
@@ -416,22 +373,23 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
DBG(REGS, "NO XBUS\n");
return -EINVAL;
}
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx);
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
xpd->xbus_idx);
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
data_low, data_high);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
/* do not count the 'bytes' field */
reg_cmd->h.bytes = REG_CMD_SIZE(REG);
reg_cmd->h.is_multibyte = 0;
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
reg_cmd->is_multibyte = 0;
if (portno == PORT_BROADCAST) {
reg_cmd->h.portnum = 0;
reg_cmd->portnum = 0;
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
} else {
reg_cmd->h.portnum = portno;
reg_cmd->portnum = portno;
REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
}
reg_cmd->h.eoframe = 0;
reg_cmd->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;
@@ -440,12 +398,11 @@ 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->h.portnum, reg_cmd);
reg_cmd->portnum, reg_cmd);
dump_packet("REG_REQ", pack, 1);
}
if (!xframe->usec_towait) { /* default processing time of SPI */
@@ -459,67 +416,6 @@ 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.
*/
@@ -615,11 +511,6 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
ret = -EPROTO;
goto proto_err;
}
if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) {
XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n");
ret = -EPROTO;
goto proto_err;
}
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
ret = -EPROTO;
goto proto_err;
@@ -649,14 +540,21 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
card_desc->magic = CARD_DESC_MAGIC;
INIT_LIST_HEAD(&card_desc->card_list);
card_desc->unit_descriptor = *this_unit;
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;
XBUS_INFO(xbus,
" CARD %d type=%d.%d ports=(%dx%d), "
" CARD %d type=%d.%d ports=%d (%dx%d), "
"port-dir=0x%02X\n",
this_unit->addr.unit, this_unit->type,
this_unit->subtype,
this_unit->numchips, this_unit->ports_per_chip,
this_unit->port_dir);
card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->ports,
card_desc->numchips, card_desc->ports_per_chip,
card_desc->port_dir);
spin_lock_irqsave(&worker->worker_lock, flags);
worker->num_units++;
XBUS_COUNTER(xbus, UNITS)++;
@@ -670,7 +568,6 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
goto out;
proto_err:
xbus_setstate(xbus, XBUS_STATE_FAIL);
dump_packet("AB_DESCRIPTION", pack, DBG_ANY);
out:
return ret;
@@ -688,7 +585,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
return -EPROTO;
}
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
reg);
dump_packet("REG_REPLY", pack, 1);
}
@@ -803,7 +700,6 @@ 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,
@@ -850,9 +746,8 @@ 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->xpd_type);
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
direction_mask);
@@ -861,7 +756,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, hw_type,
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd,
"Cannot initialize. pathname is longer "
@@ -878,7 +773,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->xpd_type, xbus->revision);
init_card, xpd->type, xbus->revision);
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
/*
* Carefully report results

View File

@@ -74,18 +74,9 @@ 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 do_expander);
bool should_reply);
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx, __u8 *buf, unsigned len);
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing,
__u8 addr_low,
__u8 addr_high,
__u8 data_0,
__u8 data_1,
__u8 data_2,
__u8 data_3,
bool should_reply);
extern xproto_table_t PROTO_TABLE(GLOBAL);
int run_initialize_registers(xpd_t *xpd);
int parse_chip_command(xpd_t *xpd, char *cmdline);

View File

@@ -85,6 +85,8 @@ 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,
@@ -388,8 +390,7 @@ static int query_subunit(xpd_t *xpd, __u8 regnum)
0, /* data_L */
0, /* do_datah */
0, /* data_H */
0, /* should_reply */
0 /* do_expander */
0 /* should_reply */
);
}
@@ -405,8 +406,7 @@ static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
val, /* data_L */
0, /* do_datah */
0, /* data_H */
0, /* should_reply */
0 /* do_expander */
0 /* should_reply */
);
}
@@ -421,8 +421,7 @@ 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 /* do_expander */
0 /* should_reply */
);
}
@@ -525,12 +524,9 @@ static void PRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
//XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
/* Add/remove all the trivial cases */
pcm_mask |= PHONEDEV(xpd).offhook_state;
if (priv->is_cas)
pcm_mask |= BITMASK(PHONEDEV(xpd).channels);
for_each_line(xpd, i)
if (IS_SET(pcm_mask, i))
line_count++;
else
if (priv->is_cas) {
if (priv->pri_protocol == PRI_PROTO_E1) {
/* CAS: Don't send PCM to D-Channel */
@@ -615,7 +611,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
}
priv->pri_protocol = set_proto;
priv->is_cas = -1;
phonedev_alloc_channels(xpd, pri_num_channels(set_proto));
phonedev->channels = pri_num_channels(set_proto);
phonedev->offhook_state = BITMASK(phonedev->channels);
CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
priv->deflaw = deflaw;
@@ -708,7 +704,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_SYPR, VAL_PC_GPI, VAL_PC_GPI };
__u8 reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI };
for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) {
__u8 reg_pc = reg_pc_init[i];
@@ -1086,7 +1082,6 @@ static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype)
struct phonedev *phonedev = container_of(span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
enum pri_protocol set_proto = PRI_PROTO_0;
int ret;
XPD_INFO(xpd, "%s: %s\n", __func__, dahdi_spantype2str(spantype));
switch (spantype) {
@@ -1104,13 +1099,7 @@ static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype)
__func__, dahdi_spantype2str(spantype));
return -EINVAL;
}
ret = set_pri_proto(xpd, set_proto);
if (ret < 0) {
XPD_ERR(xpd, "%s: set_pri_proto failed\n", __func__);
return ret;
}
dahdi_init_span(span);
return 0;
return set_pri_proto(xpd, set_proto);
}
static int PRI_card_open(xpd_t *xpd, lineno_t pos)
@@ -1235,7 +1224,7 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0)
set_mode_cas(xpd, 0);
} else {
if (chan->chanpos == 1) {
if (chan->channo == 1) {
XPD_DBG(GENERAL, xpd,
"channel %d (%s) marked a not DChan\n",
chan->channo, chan->name);
@@ -1256,29 +1245,21 @@ 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,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
{
xpd_t *xpd = NULL;
struct PRI_priv_data *priv;
int channels = min(31, CHANNELS_PERXPD); /* worst case */
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);
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit,
sizeof(struct PRI_priv_data), proto_table, unit_descriptor, channels);
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct PRI_priv_data), proto_table, channels);
if (!xpd)
return NULL;
priv = xpd->priv;
@@ -1298,7 +1279,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xpd);
XPD_DBG(GENERAL, xpd, "\n");
xpd->xpd_type = XPD_TYPE_PRI;
xpd->type = XPD_TYPE_PRI;
priv = xpd->priv;
if (priv->pri_protocol == PRI_PROTO_0) {
/*
@@ -1948,8 +1929,7 @@ static void PRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
dchan_state(xpd, 0);
}
if (IS_SET(physical_mask, i)) {
struct dahdi_chan *chan = XPD_CHAN(xpd, logical_chan);
r = chan->readchunk;
r = XPD_CHAN(xpd, logical_chan)->readchunk;
// memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG
memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
pcm += DAHDI_CHUNKSIZE;
@@ -2264,7 +2244,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->h.portnum;
addr.subunit = info->portnum;
regnum = REG_FIELD(info, regnum);
data_low = REG_FIELD(info, data_low);
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
@@ -2278,9 +2258,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->h.is_multibyte) {
if (info->is_multibyte) {
XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
info->h.bytes, info->h.eoframe);
info->bytes, info->eoframe);
goto end;
}
if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg))
@@ -2408,11 +2388,11 @@ static DEVICE_ATTR_WRITER(pri_protocol_store, dev, buf, count)
buf, i);
return -EINVAL;
}
if (strncasecmp(buf, "E1", 2) == 0)
if (strnicmp(buf, "E1", 2) == 0)
new_protocol = PRI_PROTO_E1;
else if (strncasecmp(buf, "T1", 2) == 0)
else if (strnicmp(buf, "T1", 2) == 0)
new_protocol = PRI_PROTO_T1;
else if (strncasecmp(buf, "J1", 2) == 0)
else if (strnicmp(buf, "J1", 2) == 0)
new_protocol = PRI_PROTO_J1;
else {
XPD_NOTICE(xpd,
@@ -2646,9 +2626,9 @@ static int pri_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->xpd_type != XPD_TYPE_PRI) {
if (xpd->type != XPD_TYPE_PRI) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->xpd_type);
xpd->type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -2731,7 +2711,7 @@ static int pri_xpd_remove(struct device *dev)
}
static struct xpd_driver pri_driver = {
.xpd_type = XPD_TYPE_PRI,
.type = XPD_TYPE_PRI,
.driver = {
.name = "pri",
.owner = THIS_MODULE,
@@ -2745,6 +2725,7 @@ 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
@@ -2764,6 +2745,7 @@ 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

View File

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

View File

@@ -3,13 +3,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_TYPE_6.hex
FPGA_1161.201.hex
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
OCT_FW = $(wildcard OCT6104E-256D.ima)
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
PROTO_VER = 30
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5 6)
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5)
SCRIPTS = $(SCRIPTS_BASE:%=../%)
TARGET = $(DESTDIR)/usr/share/dahdi
@@ -21,12 +20,4 @@ install:
mkdir -p $(TARGET)
install $(SCRIPTS) $(TARGET)/
install -m 644 ../XppConfig.pm $(FIRMWARES) $(TARGET)/
for id in 202 203; do \
if [ ! -r $(TARGET)/USB_FW.$$id.hex ]; then \
ln -s USB_FW.201.hex $(TARGET)/USB_FW.$$id.hex;\
fi; \
done
if [ ! -r $(TARGET)/FPGA_1161.203.hex ]; then \
ln -s FPGA_1161.201.hex $(TARGET)/FPGA_1161.203.hex;\
fi

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,5 +1,5 @@
#
# $Id: USB_FW.hex 11452 2015-03-29 18:21:13Z dima $
# $Id: USB_FW.hex 10401 2012-02-15 15:30:24Z dima $
#
:03004300021F0099
:03005300021F0089
@@ -27,7 +27,7 @@
:051EF1000300000000E9
:1011F50041E0370041E0B70042E0B2000041E0388D
:1012050000021BE0860218E07A43E0B40000004EBD
:10121500E03931313435314D502020202020200057
:10121500E03931303339354D502020202020200051
:101D9A008B518A528953E5561556AE557002155520
:101DAA004E6014AB510553E553AA52700205521402
:081DBA00F9ED12077180DF2230
@@ -165,7 +165,7 @@
:100B7800AB43AA44A9457401120771E4F54EE54E4A
:100B8800C454F0AB43AA44A94590000112078385D9
:100B98004656854757854858755908121A94AB46E2
:100BA800AA47A948900002120744FE5407FFEE54D2
:100BA800AA47A948900002120744FE5403FFEE54D6
:100BB80070F54F24E0602924F0604B24F0605D2438
:100BC800F0606F24406003020C50753F01851840A7
:100BD800851941EF24FE600624FE703B801C801FAF

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/blackfin.h>
@@ -561,6 +560,9 @@ static int __init xpp_mmap_init(void)
xframe_cache =
kmem_cache_create("xframe_cache",
sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
NULL,
#endif
NULL);
if (!xframe_cache) {
ret = -ENOMEM;

View File

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

View File

@@ -24,10 +24,8 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#ifdef PROTOCOL_DEBUG
#include <linux/ctype.h>
#endif
@@ -50,15 +48,8 @@ static const char rcsid[] = "$Id$";
#ifdef PROTOCOL_DEBUG
#ifdef CONFIG_PROC_FS
#define PROC_XBUS_COMMAND "command"
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops proc_xbus_command_ops;
#else
static const struct file_operations proc_xbus_command_ops;
#endif /* DAHDI_HAVE_PROC_OPS */
#endif
#endif
/* Command line parameters */
@@ -68,19 +59,12 @@ static DEF_PARM(uint, command_queue_length, 1500, 0444,
static DEF_PARM(uint, poll_timeout, 1000, 0644,
"Timeout (in jiffies) waiting for units to reply");
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0444,
"Register devices automatically (1) or not (0). UNUSED.");
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
"Register devices automatically (1) or not (0)");
#ifdef CONFIG_PROC_FS
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops xbus_read_proc_ops;
#else
static const struct file_operations xbus_read_proc_ops;
#endif /* DAHDI_HAVE_PROC_OPS */
#endif /* CONFIG_PROC_FS */
#endif
static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
ushort max_send_size,
struct device *transport_device, void *priv);
@@ -94,14 +78,8 @@ static struct proc_dir_entry *proc_xbuses;
static struct xbus_desc {
xbus_t *xbus;
int shutting_down;
} xbuses_array[MAX_BUSES];
static int xbus_is_shutting_down(int num)
{
return xbuses_array[num].shutting_down;
}
static xbus_t *xbus_byhwid(const char *hwid)
{
int i;
@@ -169,8 +147,6 @@ static void init_xbus(uint num, xbus_t *xbus)
BUG_ON(num >= ARRAY_SIZE(xbuses_array));
desc = &xbuses_array[num];
desc->xbus = xbus;
if (xbus)
desc->shutting_down = 0;
}
xbus_t *xbus_num(uint num)
@@ -210,12 +186,9 @@ static void finalize_xbuses_array(void)
static void xbus_destroy(struct kref *kref)
{
xbus_t *xbus;
int num;
xbus = kref_to_xbus(kref);
XBUS_DBG(DEVICES, xbus, "%s\n", __func__);
num = xbus->num;
xbuses_array[num].shutting_down = 1;
XBUS_NOTICE(xbus, "%s\n", __func__);
xbus_sysfs_remove(xbus);
}
@@ -224,11 +197,6 @@ xbus_t *get_xbus(const char *msg, uint num)
unsigned long flags;
xbus_t *xbus;
if (xbus_is_shutting_down(num)) {
DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n", __func__,
msg, num);
return NULL;
}
spin_lock_irqsave(&xbuses_lock, flags);
xbus = xbus_num(num);
if (xbus != NULL) {
@@ -242,13 +210,6 @@ xbus_t *get_xbus(const char *msg, uint num)
void put_xbus(const char *msg, xbus_t *xbus)
{
if (xbus_is_shutting_down(xbus->num)) {
if (!refcount_xbus(xbus)) {
DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n",
__func__, msg, xbus->num);
return;
}
}
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg,
refcount_xbus(xbus));
kref_put(&xbus->kref, xbus_destroy);
@@ -258,7 +219,7 @@ int refcount_xbus(xbus_t *xbus)
{
struct kref *kref = &xbus->kref;
return refcount_read(&kref->refcount);
return atomic_read(&kref->refcount);
}
/*------------------------- Frame Handling ------------------------*/
@@ -273,7 +234,7 @@ void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
xframe->packets = xframe->first_free = buf;
xframe->frame_maxlen = maxsize;
atomic_set(&xframe->frame_len, 0);
xframe->kt_created = ktime_get();
do_gettimeofday(&xframe->tv_created);
xframe->xframe_magic = XFRAME_MAGIC;
}
EXPORT_SYMBOL(xframe_init);
@@ -598,14 +559,6 @@ static void receive_tasklet_func(unsigned long data)
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe)
{
BUG_ON(!xbus);
if (xbus_is_shutting_down(xbus->num)) {
static int rate_limit;
if ((rate_limit++ % 1000) == 0)
XBUS_NOTICE(xbus, "%s: during shutdown (%d)\n",
__func__, rate_limit);
return;
}
if (rx_tasklet) {
xframe_enqueue_recv(xbus, xframe);
} else {
@@ -701,56 +654,10 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
return 0;
}
static xpd_type_t xpd_hw2xpd_type(const struct unit_descriptor *unit_descriptor)
static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
__u8 numchips, __u8 ports_per_chip, __u8 ports,
__u8 port_dir)
{
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;
@@ -758,19 +665,12 @@ static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
int remaining_ports;
const struct echoops *echoops;
/* 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);
proto_table = xproto_get(type);
if (!proto_table) {
XBUS_NOTICE(xbus,
"CARD %d: missing protocol table for xpd_type %d. "
"CARD %d: missing protocol table for type %d. "
"Ignored.\n",
unit, xpd_type);
unit, type);
return -EINVAL;
}
echoops = proto_table->echoops;
@@ -778,24 +678,26 @@ static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit);
if (ECHOOPS(xbus)) {
XBUS_NOTICE(xbus,
"CARD %d: tryies to define echoops (xpd_type %d) "
"CARD %d: tryies to define echoops (type %d) "
"but we already have one. Ignored.\n",
unit, xpd_type);
unit, type);
return -EINVAL;
}
xbus->echo_state.echoops = echoops;
xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
}
remaining_ports = ports;
subunits = subunits_of_xpd(unit_descriptor, proto_table);
subunits =
(ports + proto_table->ports_per_subunit -
1) / proto_table->ports_per_subunit;
XBUS_DBG(DEVICES, xbus,
"CARD %d xpd_type=%d/hw_type=%d ports=%d (%dx%d), "
"CARD %d type=%d.%d ports=%d (%dx%d), "
"%d subunits, port-dir=0x%02X\n",
unit, xpd_type, hw_type, ports, numchips, ports_per_chip, subunits,
unit, type, subtype, ports, numchips, ports_per_chip, subunits,
port_dir);
if (xpd_type == XPD_TYPE_PRI || xpd_type == XPD_TYPE_BRI)
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
xbus->quirks.has_digital_span = 1;
if (xpd_type == XPD_TYPE_FXO)
if (type == XPD_TYPE_FXO)
xbus->quirks.has_fxo = 1;
xbus->worker.num_units += subunits - 1;
for (i = 0; i < subunits; i++) {
@@ -819,10 +721,11 @@ static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
goto out;
}
XBUS_DBG(DEVICES, xbus,
"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);
"Creating XPD=%d%d type=%d.%d (%d ports)\n", unit, i,
type, subtype, subunit_ports);
ret =
create_xpd(xbus, proto_table, unit_descriptor, unit, i, xpd_type);
create_xpd(xbus, proto_table, unit, i, type, subtype,
subunits, subunit_ports, port_dir);
if (ret < 0) {
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit,
i, ret);
@@ -960,12 +863,12 @@ static int xbus_initialize(xbus_t *xbus)
int unit;
int subunit;
xpd_t *xpd;
ktime_t time_start;
ktime_t time_end;
struct timeval time_start;
struct timeval time_end;
unsigned long timediff;
int res = 0;
time_start = ktime_get();
do_gettimeofday(&time_start);
XBUS_DBG(DEVICES, xbus, "refcount_xbus=%d\n", refcount_xbus(xbus));
if (xbus_aquire_xpds(xbus) < 0) /* Until end of initialization */
return -EBUSY;
@@ -1003,7 +906,7 @@ static int xbus_initialize(xbus_t *xbus)
}
}
xbus_echocancel(xbus, 1);
time_end = ktime_get();
do_gettimeofday(&time_end);
timediff = usec_diff(&time_end, &time_start);
timediff /= 1000 * 100;
XBUS_INFO(xbus, "Initialized in %ld.%1ld sec\n", timediff / 10,
@@ -1034,8 +937,6 @@ static void xbus_free_ddev(xbus_t *xbus)
xbus->ddev = NULL;
}
static DEFINE_MUTEX(dahdi_registration_mutex);
int xbus_register_dahdi_device(xbus_t *xbus)
{
int i;
@@ -1043,20 +944,11 @@ int xbus_register_dahdi_device(xbus_t *xbus)
int ret;
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
if (ret < 0) {
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
goto err;
}
if (xbus_is_registered(xbus)) {
/*
* Ignore duplicate registrations (from dahdi_registration)
* Until we completely migrate to dahdi_autoreg=1 and
* hotplug-based span-assignments
*/
XBUS_DBG(DEVICES, xbus, "Already registered to DAHDI\n");
ret = 0;
goto out;
XBUS_ERR(xbus, "Already registered to DAHDI\n");
WARN_ON(1);
ret = -EINVAL;
goto err;
}
xbus->ddev = dahdi_create_device();
if (!xbus->ddev) {
@@ -1116,49 +1008,31 @@ int xbus_register_dahdi_device(xbus_t *xbus)
xpd_dahdi_postregister(xpd);
}
}
ret = 0;
out:
mutex_unlock(&dahdi_registration_mutex);
return ret;
return 0;
err:
xbus_free_ddev(xbus);
goto out;
return ret;
}
void xbus_unregister_dahdi_device(xbus_t *xbus)
{
int i;
int ret;
XBUS_DBG(DEVICES, xbus, "%s\n", __func__);
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
if (ret < 0) {
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
return;
}
if (!xbus_is_registered(xbus)) {
/*
* Ignore duplicate unregistrations
*/
XBUS_DBG(DEVICES, xbus, "Already unregistered to DAHDI\n");
goto err;
}
XBUS_NOTICE(xbus, "%s\n", __func__);
for (i = 0; i < MAX_XPDS; i++) {
xpd_t *xpd = xpd_of(xbus, i);
xpd_dahdi_preunregister(xpd);
}
if (xbus->ddev) {
dahdi_unregister_device(xbus->ddev);
XBUS_DBG(DEVICES, xbus,
"%s: finished dahdi_unregister_device()\n", __func__);
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n",
__func__);
xbus_free_ddev(xbus);
}
for (i = 0; i < MAX_XPDS; i++) {
xpd_t *xpd = xpd_of(xbus, i);
xpd_dahdi_postunregister(xpd);
}
err:
mutex_unlock(&dahdi_registration_mutex);
}
/*
@@ -1166,10 +1040,16 @@ err:
* it returns only when all XPD's on the bus are detected and
* initialized.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
static void xbus_populate(struct work_struct *work)
{
struct xbus_workqueue *worker =
container_of(work, struct xbus_workqueue, xpds_init_work);
#else
void xbus_populate(void *data)
{
struct xbus_workqueue *worker = data;
#endif
xbus_t *xbus;
struct list_head *card;
struct list_head *next_card;
@@ -1188,7 +1068,11 @@ static void xbus_populate(struct work_struct *work)
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->unit_descriptor);
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);
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
KZFREE(card_desc);
if (ret)
@@ -1216,7 +1100,7 @@ static void xbus_populate(struct work_struct *work)
*/
xbus_request_sync(xbus, SYNC_MODE_PLL);
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
if (!dahdi_get_auto_assign_spans())
if (dahdi_autoreg)
xbus_register_dahdi_device(xbus);
out:
XBUS_DBG(DEVICES, xbus, "Leaving\n");
@@ -1246,7 +1130,11 @@ int xbus_process_worker(xbus_t *xbus)
}
XBUS_DBG(DEVICES, xbus, "\n");
/* Initialize the work. (adapt to kernel API changes). */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
INIT_WORK(&worker->xpds_init_work, xbus_populate);
#else
INIT_WORK(&worker->xpds_init_work, xbus_populate, worker);
#endif
BUG_ON(!xbus);
/* Now send it */
if (!queue_work(worker->wq, &worker->xpds_init_work)) {
@@ -1270,7 +1158,8 @@ static void worker_reset(xbus_t *xbus)
name = (xbus) ? xbus->busname : "detached";
DBG(DEVICES, "%s\n", name);
if (!worker->xpds_init_done) {
XBUS_NOTICE(xbus, "XPDS initialization was not finished\n");
NOTICE("%s: worker(%s)->xpds_init_done=%d\n", __func__, name,
worker->xpds_init_done);
}
spin_lock_irqsave(&worker->worker_lock, flags);
list_for_each_safe(card, next_card, &worker->card_list) {
@@ -1288,15 +1177,13 @@ static void worker_reset(xbus_t *xbus)
spin_unlock_irqrestore(&worker->worker_lock, flags);
}
/*
* Called only after worker_reset(xbus)
*/
static void worker_destroy(xbus_t *xbus)
{
struct xbus_workqueue *worker;
BUG_ON(!xbus);
worker = &xbus->worker;
worker_reset(xbus);
XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish...\n");
down(&worker->running_initialization);
XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish -- done\n");
@@ -1349,7 +1236,6 @@ static int worker_run(xbus_t *xbus)
}
return 1;
err:
worker_reset(xbus);
worker_destroy(xbus);
return 0;
}
@@ -1517,7 +1403,6 @@ void xbus_disconnect(xbus_t *xbus)
del_timer_sync(&xbus->command_timer);
transportops_put(xbus);
transport_destroy(xbus);
/* worker_reset(xbus) was called in xbus_deactivate(xbus) */
worker_destroy(xbus);
XBUS_DBG(DEVICES, xbus, "Deactivated refcount_xbus=%d\n",
refcount_xbus(xbus));
@@ -1567,7 +1452,6 @@ void xbus_free(xbus_t *xbus)
num = xbus->num;
BUG_ON(!xbuses_array[num].xbus);
BUG_ON(xbus != xbuses_array[num].xbus);
init_xbus(num, NULL);
spin_unlock_irqrestore(&xbuses_lock, flags);
#ifdef CONFIG_PROC_FS
if (xbus->proc_xbus_dir) {
@@ -1594,6 +1478,7 @@ void xbus_free(xbus_t *xbus)
#endif
spin_lock_irqsave(&xbuses_lock, flags);
XBUS_DBG(DEVICES, xbus, "Going to free...\n");
init_xbus(num, NULL);
spin_unlock_irqrestore(&xbuses_lock, flags);
KZFREE(xbus);
}
@@ -1616,6 +1501,7 @@ 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;
@@ -1723,6 +1609,10 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
* FIXME: worker is created before ?????
* So by now it exists and initialized.
*/
/* until end of waitfor_xpds_show(): */
xbus = get_xbus(__func__, xbus->num);
if (!xbus)
return -ENODEV;
worker = &xbus->worker;
BUG_ON(!worker);
if (!worker->wq) {
@@ -1761,6 +1651,7 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
spin_unlock_irqrestore(&xbus->lock, flags);
}
out:
put_xbus(__func__, xbus); /* from start of waitfor_xpds_show() */
return len;
}
@@ -1769,7 +1660,8 @@ out:
static void xbus_fill_proc_queue(struct seq_file *sfile, struct xframe_queue *q)
{
seq_printf(sfile,
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02lld.%lld ms\n",
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count, q->max_count,
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
@@ -1805,9 +1697,8 @@ static int xbus_proc_show(struct seq_file *sfile, void *data)
seq_printf(sfile, "%5d ", xbus->cpu_rcv_tasklet[i]);
seq_printf(sfile, "\n");
}
seq_printf(sfile, "self_ticking: %d (last_tick at %lld)\n",
xbus->self_ticking, ktime_divns(xbus->ticker.last_sample,
NSEC_PER_SEC));
seq_printf(sfile, "self_ticking: %d (last_tick at %ld)\n",
xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec);
seq_printf(sfile, "command_tick: %d\n",
xbus->command_tick_counter);
seq_printf(sfile, "usec_nosend: %d\n", xbus->usec_nosend);
@@ -1842,22 +1733,13 @@ static int xbus_read_proc_open(struct inode *inode, struct file *file)
return single_open(file, xbus_proc_show, PDE_DATA(inode));
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops xbus_read_proc_ops = {
.proc_open = xbus_read_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations xbus_read_proc_ops = {
.owner = THIS_MODULE,
.open = xbus_read_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
.open = xbus_read_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif /* DAHDI_HAVE_PROC_OPS */
#ifdef PROTOCOL_DEBUG
static ssize_t proc_xbus_command_write(struct file *file,
@@ -1950,19 +1832,11 @@ static int proc_xbus_command_open(struct inode *inode, struct file *file)
return 0;
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops proc_xbus_command_ops = {
.proc_open = proc_xbus_command_open,
.proc_write = proc_xbus_command_write,
};
#else
static const struct file_operations proc_xbus_command_ops = {
.owner = THIS_MODULE,
.open = proc_xbus_command_open,
.write = proc_xbus_command_write,
};
#endif /* DAHDI_HAVE_PROC_OPS */
#endif
static int xpp_proc_read_show(struct seq_file *sfile, void *data)
@@ -1992,22 +1866,13 @@ static int xpp_proc_read_open(struct inode *inode, struct file *file)
return single_open(file, xpp_proc_read_show, PDE_DATA(inode));
}
#ifdef DAHDI_HAVE_PROC_OPS
static const struct proc_ops xpp_proc_read_ops = {
.proc_open = xpp_proc_read_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations xpp_proc_read_ops = {
.owner = THIS_MODULE,
.open = xpp_proc_read_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
.open = xpp_proc_read_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif /* DAHDI_HAVE_PROC_OPS */
#endif
@@ -2094,10 +1959,6 @@ int __init xbus_core_init(void)
{
int ret = 0;
if (dahdi_autoreg == 1) {
NOTICE("WARNING: The dahdi_autoreg parameter is deprecated " \
"-- just set dahdi.auto_assign_spans=0\n");
}
initialize_xbuses_array();
#ifdef PROTOCOL_DEBUG
INFO("FEATURE: with PROTOCOL_DEBUG\n");

View File

@@ -234,8 +234,8 @@ struct xbus {
spinlock_t lock;
/* PCM metrics */
ktime_t last_tx_sync;
ktime_t last_rx_sync;
struct timeval last_tx_sync;
struct timeval last_rx_sync;
unsigned long max_tx_sync;
unsigned long min_tx_sync;
unsigned long max_rx_sync;
@@ -255,7 +255,7 @@ struct xbus {
*/
int sync_adjustment;
int sync_adjustment_offset;
ktime_t pll_updated_at;
long pll_updated_at;
atomic_t num_xpds;
@@ -279,10 +279,10 @@ struct xframe {
struct list_head frame_list;
atomic_t frame_len;
xbus_t *xbus;
ktime_t kt_created;
ktime_t kt_queued;
ktime_t kt_submitted;
ktime_t kt_received;
struct timeval tv_created;
struct timeval tv_queued;
struct timeval tv_submitted;
struct timeval tv_received;
/* filled by transport layer */
size_t frame_maxlen;
__u8 *packets; /* max XFRAME_DATASIZE */
@@ -338,8 +338,6 @@ 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);
@@ -358,9 +356,4 @@ void xbus_sysfs_remove(xbus_t *xbus);
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
static inline s64 xpp_ktime_sec_delta(ktime_t later, ktime_t earlier)
{
return ktime_divns(ktime_sub(later, earlier), NSEC_PER_SEC);
}
#endif /* XBUS_CORE_H */

View File

@@ -111,23 +111,24 @@ static void xpp_ticker_init(struct xpp_ticker *ticker)
{
memset(ticker, 0, sizeof(*ticker));
spin_lock_init(&ticker->lock);
ticker->last_sample = ktime_get();
do_gettimeofday(&ticker->last_sample.tv);
ticker->first_sample = ticker->last_sample;
ticker_set_cycle(ticker, SYNC_ADJ_QUICK);
}
static int xpp_ticker_step(struct xpp_ticker *ticker, const ktime_t t)
static int xpp_ticker_step(struct xpp_ticker *ticker, const struct timeval *t)
{
unsigned long flags;
s64 usec;
long usec;
bool cycled = 0;
spin_lock_irqsave(&ticker->lock, flags);
ticker->last_sample = t;
ticker->last_sample.tv = *t;
/* rate adjust */
if ((ticker->count % ticker->cycle) == ticker->cycle - 1) {
usec = ktime_us_delta(ticker->last_sample,
ticker->first_sample);
usec =
(long)usec_diff(&ticker->last_sample.tv,
&ticker->first_sample.tv);
ticker->first_sample = ticker->last_sample;
ticker->tick_period = usec / ticker->cycle;
cycled = 1;
@@ -146,7 +147,7 @@ static inline void xbus_drift_clear(xbus_t *xbus)
{
struct xpp_drift *di = &xbus->drift;
di->last_lost_tick = ktime_get();
do_gettimeofday(&di->last_lost_tick.tv);
ticker_set_cycle(&xbus->ticker, SYNC_ADJ_QUICK);
di->max_speed = -SYNC_ADJ_MAX;
di->min_speed = SYNC_ADJ_MAX;
@@ -189,14 +190,14 @@ static void sample_tick(xbus_t *xbus, int sample)
* including abrupt changes in sync -- to verify the stability of the
* algorithm.
*/
static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
{
struct xpp_drift *di = &xbus->drift;
struct xpp_ticker *ticker = &xbus->ticker;
unsigned long flags;
spin_lock_irqsave(&di->lock, flags);
xpp_ticker_step(&xbus->ticker, kt);
xpp_ticker_step(&xbus->ticker, tv);
/*
* Do we need to be synchronized and is there an established reference
* ticker (another Astribank or another DAHDI device) already?
@@ -205,7 +206,7 @@ static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
&& xbus->sync_mode == SYNC_MODE_PLL) {
int new_delta_tick = ticker->count - ref_ticker->count;
int lost_ticks = new_delta_tick - di->delta_tick;
s64 usec_delta;
long usec_delta;
di->delta_tick = new_delta_tick;
if (lost_ticks) {
@@ -232,8 +233,9 @@ static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
}
} else {
/* Sample a delta */
usec_delta = ktime_us_delta(ticker->last_sample,
ref_ticker->last_sample);
usec_delta =
(long)usec_diff(&ticker->last_sample.tv,
&ref_ticker->last_sample.tv);
sample_tick(xbus, usec_delta);
if ((ticker->count % SYNC_CYCLE) >
(SYNC_CYCLE - SYNC_CYCLE_SAMPLE))
@@ -280,7 +282,8 @@ static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
di->offset_min = offset;
XBUS_DBG(SYNC, xbus,
"offset: %d, min_speed=%d, max_speed=%d, usec_delta(last)=%lld\n",
"offset: %d, min_speed=%d, "
"max_speed=%d, usec_delta(last)=%ld\n",
offset_prev, di->min_speed,
di->max_speed, usec_delta);
XBUS_DBG(SYNC, xbus,
@@ -350,11 +353,13 @@ static void xpp_set_syncer(xbus_t *xbus, bool on)
(syncer) ? syncer->busname : "NO-SYNC");
}
static void xbus_command_timer(TIMER_DATA_TYPE timer)
static void xbus_command_timer(unsigned long param)
{
xbus_t *xbus = from_timer(xbus, timer, command_timer);
xbus_t *xbus = (xbus_t *)param;
struct timeval now;
BUG_ON(!xbus);
do_gettimeofday(&now);
xbus_command_queue_tick(xbus);
if (!xbus->self_ticking) /* Must be 1KHz rate */
mod_timer(&xbus->command_timer, jiffies + 1);
@@ -366,9 +371,10 @@ 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");
timer_setup(&xbus->command_timer,
xbus_command_timer, 0);
mod_timer(&xbus->command_timer, jiffies + 1);
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);
}
} else if (timer_pending(&xbus->command_timer)) {
XBUS_DBG(SYNC, xbus, "del_timer\n");
@@ -484,34 +490,34 @@ static void reset_sync_counters(void)
static void send_drift(xbus_t *xbus, int drift)
{
const ktime_t now = ktime_get();
struct timeval now;
const char *msg;
s64 msec_delta;
BUG_ON(abs(drift) > SYNC_ADJ_MAX);
do_gettimeofday(&now);
if (drift > xbus->sync_adjustment)
msg = "up";
else
msg = "down";
msec_delta = ktime_ms_delta(now, xbus->pll_updated_at);
XBUS_DBG(SYNC, xbus,
"%sDRIFT adjust %s (%d) (last update %lld seconds ago)\n",
"%sDRIFT adjust %s (%d) (last update %ld seconds ago)\n",
(disable_pll_sync) ? "Fake " : "", msg, drift,
msec_delta / MSEC_PER_SEC);
now.tv_sec - xbus->pll_updated_at);
if (!disable_pll_sync)
CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL,
drift);
xbus->pll_updated_at = now;
xbus->pll_updated_at = now.tv_sec;
}
static void global_tick(void)
{
ktime_t now = ktime_get();
struct timeval now;
do_gettimeofday(&now);
atomic_inc(&xpp_tick_counter);
if ((atomic_read(&xpp_tick_counter) % BIG_TICK_INTERVAL) == 0)
reset_sync_counters();
xpp_ticker_step(&global_ticks_series, now);
xpp_ticker_step(&global_ticks_series, &now);
}
#ifdef DAHDI_SYNC_TICK
@@ -520,11 +526,11 @@ void dahdi_sync_tick(struct dahdi_span *span, int is_master)
struct phonedev *phonedev = container_of(span, struct phonedev, span);
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
static int redundant_ticks; /* for extra spans */
ktime_t now;
struct timeval now;
if (!force_dahdi_sync)
goto noop;
now = ktime_get();
do_gettimeofday(&now);
BUG_ON(!xpd);
/*
* Detect if any of our spans is dahdi sync master
@@ -557,7 +563,7 @@ void dahdi_sync_tick(struct dahdi_span *span, int is_master)
#endif
goto noop;
}
xpp_ticker_step(&dahdi_ticker, now);
xpp_ticker_step(&dahdi_ticker, &now);
dahdi_tick_count++;
//flip_parport_bit(1);
noop:
@@ -849,14 +855,15 @@ static bool pcm_valid(xpd_t *xpd, xpacket_t *pack)
static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
{
unsigned long flags;
const ktime_t now = ktime_get();
s64 usec;
struct timeval now;
unsigned long usec;
spin_lock_irqsave(&xbus->lock, flags);
do_gettimeofday(&now);
if (unlikely(disable_pcm || !XBUS_IS(xbus, READY)))
goto dropit;
if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
usec = ktime_us_delta(now, xbus->last_tx_sync);
usec = usec_diff(&now, &xbus->last_tx_sync);
xbus->last_tx_sync = now;
/* ignore startup statistics */
if (likely
@@ -866,7 +873,8 @@ static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
if ((rate_limit++ % 5003) == 0)
XBUS_DBG(SYNC, xbus,
"Bad PCM TX timing(%d): usec=%lld.\n",
"Bad PCM TX timing(%d): "
"usec=%ld.\n",
rate_limit, usec);
}
if (usec > xbus->max_tx_sync)
@@ -1180,10 +1188,11 @@ static void xbus_tick(xbus_t *xbus)
while ((xframe = xframe_dequeue(&xbus->pcm_tospan)) != NULL) {
copy_pcm_tospan(xbus, xframe);
if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
ktime_t now = ktime_get();
s64 usec;
struct timeval now;
unsigned long usec;
usec = ktime_us_delta(now, xbus->last_rx_sync);
do_gettimeofday(&now);
usec = usec_diff(&now, &xbus->last_rx_sync);
xbus->last_rx_sync = now;
/* ignore startup statistics */
if (likely
@@ -1194,7 +1203,9 @@ static void xbus_tick(xbus_t *xbus)
if ((rate_limit++ % 5003) == 0)
XBUS_DBG(SYNC, xbus,
"Bad PCM RX timing(%d): usec=%lld.\n",
"Bad PCM RX "
"timing(%d): "
"usec=%ld.\n",
rate_limit, usec);
}
if (usec > xbus->max_rx_sync)
@@ -1225,7 +1236,7 @@ static void xbus_tick(xbus_t *xbus)
}
}
static void do_tick(xbus_t *xbus, const ktime_t kt_received)
static void do_tick(xbus_t *xbus, const struct timeval *tv_received)
{
int counter = atomic_read(&xpp_tick_counter);
unsigned long flags;
@@ -1234,7 +1245,7 @@ static void do_tick(xbus_t *xbus, const ktime_t kt_received)
if (global_ticker == xbus)
global_tick(); /* called from here or dahdi_sync_tick() */
spin_lock_irqsave(&ref_ticker_lock, flags);
xpp_drift_step(xbus, kt_received);
xpp_drift_step(xbus, tv_received);
spin_unlock_irqrestore(&ref_ticker_lock, flags);
if (likely(xbus->self_ticking))
xbus_tick(xbus);
@@ -1258,7 +1269,7 @@ void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe)
* FIXME: what about PRI split?
*/
if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
do_tick(xbus, xframe->kt_received);
do_tick(xbus, &xframe->tv_received);
atomic_inc(&xbus->pcm_rx_counter);
} else
xbus->xbus_frag_count++;

View File

@@ -39,6 +39,16 @@ enum sync_mode {
SYNC_MODE_QUERY = 0x80,
};
/*
* Abstract representation of timestamp.
* It would (eventually) replace the hard-coded
* timeval structs so we can migrate to better
* time representations.
*/
struct xpp_timestamp {
struct timeval tv;
};
/*
* A ticker encapsulates the timing information of some
* abstract tick source. The following tickers are used:
@@ -50,8 +60,8 @@ enum sync_mode {
struct xpp_ticker { /* for rate calculation */
int count;
int cycle;
ktime_t first_sample;
ktime_t last_sample;
struct xpp_timestamp first_sample;
struct xpp_timestamp last_sample;
int tick_period; /* usec/tick */
spinlock_t lock;
};
@@ -65,7 +75,7 @@ struct xpp_drift {
int lost_ticks; /* occurances */
int lost_tick_count;
int sync_inaccuracy;
ktime_t last_lost_tick;
struct xpp_timestamp last_lost_tick;
long delta_sum;
int offset_prev;
int offset_range;
@@ -78,10 +88,15 @@ struct xpp_drift {
void xpp_drift_init(xbus_t *xbus);
static inline long usec_diff(const ktime_t *tv1,
const ktime_t *tv2)
static inline long usec_diff(const struct timeval *tv1,
const struct timeval *tv2)
{
return ktime_us_delta(*tv1, *tv2);
long diff_sec;
long diff_usec;
diff_sec = tv1->tv_sec - tv2->tv_sec;
diff_usec = tv1->tv_usec - tv2->tv_usec;
return diff_sec * 1000000 + diff_usec;
}
int xbus_pcm_init(void *top);

View File

@@ -30,8 +30,6 @@
#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/delay.h> /* for msleep() to debug */
#include <linux/sched.h>
#include <dahdi/kernel.h>
#include "xpd.h"
#include "xpp_dahdi.h"
#include "xbus-core.h"
@@ -56,19 +54,10 @@ static ssize_t sync_store(struct device_driver *driver, const char *buf,
return exec_sync_command(buf, count);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static struct driver_attribute xpp_attrs[] = {
__ATTR(sync, S_IRUGO | S_IWUSR, sync_show, sync_store),
__ATTR_NULL,
};
#else
static DRIVER_ATTR_RW(sync);
static struct attribute *xpp_attrs[] = {
&driver_attr_sync.attr,
NULL,
};
ATTRIBUTE_GROUPS(xpp);
#endif
/*--------- Sysfs Bus handling ----*/
static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
@@ -118,28 +107,24 @@ static DEVICE_ATTR_READER(timing_show, dev, buf)
xbus_t *xbus;
struct xpp_drift *driftinfo;
int len = 0;
ktime_t now;
struct timeval now;
now = ktime_get();
do_gettimeofday(&now);
xbus = dev_to_xbus(dev);
driftinfo = &xbus->drift;
len +=
snprintf(buf + len, PAGE_SIZE - len, "%-3s",
sync_mode_name(xbus->sync_mode));
if (xbus->sync_mode == SYNC_MODE_PLL) {
bool pll_updated = !dahdi_ktime_equal(xbus->pll_updated_at,
ktime_set(0, 0));
s64 update_delta =
(!pll_updated) ? 0 :
xpp_ktime_sec_delta(now, xbus->pll_updated_at);
len +=
snprintf(buf + len, PAGE_SIZE - len,
" %5d: lost (%4d,%4d) : ", xbus->ticker.cycle,
driftinfo->lost_ticks, driftinfo->lost_tick_count);
len +=
snprintf(buf + len, PAGE_SIZE - len,
"DRIFT %3d %lld sec ago", xbus->sync_adjustment,
update_delta);
"DRIFT %3d %ld sec ago", xbus->sync_adjustment,
(xbus->pll_updated_at ==
0) ? 0 : now.tv_sec - xbus->pll_updated_at);
}
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
return len;
@@ -234,7 +219,7 @@ static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
xbus_t *xbus;
struct xpp_drift *di;
struct xpp_ticker *ticker;
ktime_t now = ktime_get();
struct timeval now;
int len = 0;
int hours;
int minutes;
@@ -249,7 +234,8 @@ static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
/*
* Calculate lost ticks time
*/
seconds = ktime_ms_delta(now, di->last_lost_tick) / 1000;
do_gettimeofday(&now);
seconds = now.tv_sec - di->last_lost_tick.tv.tv_sec;
minutes = seconds / 60;
seconds = seconds % 60;
hours = minutes / 60;
@@ -307,43 +293,6 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
xbus_attr(connector, "%s\n");
xbus_attr(label, "%s\n");
static DEVICE_ATTR_WRITER(dahdi_registration_store, dev, buf, count)
{
xbus_t *xbus;
int dahdi_reg;
int ret;
xbus = dev_to_xbus(dev);
if (!xbus)
return -ENODEV;
ret = sscanf(buf, "%d", &dahdi_reg);
if (ret != 1)
return -EINVAL;
if (dahdi_reg) {
ret = xbus_register_dahdi_device(xbus);
if (ret < 0) {
XBUS_ERR(xbus,
"xbus_register_dahdi_device() failed (ret = %d)\n",
ret);
return ret;
}
} else {
xbus_unregister_dahdi_device(xbus);
}
return count;
}
static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf)
{
xbus_t *xbus;
int len;
xbus = dev_to_xbus(dev);
len = sprintf(buf, "%d\n", xbus_is_registered(xbus));
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,44 +307,8 @@ static struct device_attribute xbus_dev_attrs[] = {
#ifdef SAMPLE_TICKS
__ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
#endif
__ATTR(dahdi_registration, S_IRUGO | S_IWUSR,
dahdi_registration_show,
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)
{
@@ -411,6 +324,34 @@ static int astribank_match(struct device *dev, struct device_driver *driver)
XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); \
} while (0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
#define XBUS_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
return err; \
} while (0)
static int astribank_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
xbus_t *xbus;
int i = 0;
int len = 0;
extern char *initdir;
if (!dev)
return -ENODEV;
xbus = dev_to_xbus(dev);
DBG(GENERAL, "SYFS bus_id=%s xbus=%s\n", dev_name(dev), xbus->busname);
XBUS_VAR_BLOCK;
envp[i] = NULL;
return 0;
}
#else
#define XBUS_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(kenv, fmt, val); \
@@ -431,6 +372,8 @@ static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv)
return 0;
}
#endif
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
{
struct kobject *kobj;
@@ -465,16 +408,8 @@ 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
.drv_groups = xpp_groups,
#endif
};
static int astribank_probe(struct device *dev)
@@ -530,25 +465,13 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
REG_FIELD(regs, data_high));
} else
datah_str[0] = '\0';
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)) {
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->h.portnum, REG_FIELD(regs, regnum),
regs->portnum, REG_FIELD(regs, regnum),
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
datah_str);
} else {
@@ -556,7 +479,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->h.portnum,
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
datah_str);
}
@@ -678,12 +601,25 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
return -EINVAL;
if (!XBUS_IS(xpd->xbus, READY))
return -ENODEV;
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n",
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use pinned-spans)\n",
(dahdi_reg) ? "register" : "unregister");
if (dahdi_reg)
xbus_register_dahdi_device(xpd->xbus);
else
xbus_unregister_dahdi_device(xpd->xbus);
if (xbus_is_registered(xpd->xbus)) {
if (dahdi_reg) {
XPD_DBG(DEVICES, xpd,
"already registered %s. Ignored.\n",
xpd->xbus->busname);
} else {
xbus_unregister_dahdi_device(xpd->xbus);
}
} else {
if (!dahdi_reg) {
XPD_DBG(DEVICES, xpd,
"already unregistered %s. Ignored.\n",
xpd->xbus->busname);
} else {
xbus_register_dahdi_device(xpd->xbus);
}
}
return count;
}
@@ -700,19 +636,6 @@ 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;
@@ -768,63 +691,34 @@ 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->xpd_type != xpd->xpd_type) {
if (xpd_driver->type != xpd->type) {
XPD_DBG(DEVICES, xpd,
"SYSFS match fail: xpd->xpd_type = %d, "
"xpd_driver->xpd_type = %d\n",
xpd->xpd_type, xpd_driver->xpd_type);
"SYSFS match fail: xpd->type = %d, "
"xpd_driver->type = %d\n",
xpd->type, xpd_driver->type);
return 0;
}
XPD_DBG(DEVICES, xpd,
"SYSFS MATCH: xpd_type=%d dev->bus_id = %s, driver->name = %s\n",
xpd->xpd_type, dev_name(dev), driver->name);
"SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
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)
@@ -1034,13 +928,10 @@ void xbus_sysfs_remove(xbus_t *xbus)
struct device *astribank;
BUG_ON(!xbus);
XBUS_DBG(DEVICES, xbus, "\n");
astribank = &xbus->astribank;
if (!dev_get_drvdata(astribank)) {
XBUS_NOTICE(xbus, "%s: already removed\n", __func__);
if (!dev_get_drvdata(astribank))
return;
}
XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n",
refcount_read(&astribank->kobj.kref.refcount));
BUG_ON(dev_get_drvdata(astribank) != xbus);
device_unregister(astribank);
dev_set_drvdata(astribank, NULL);

View File

@@ -22,6 +22,8 @@
*
*/
#include "xpp_version.h"
#ifdef __KERNEL__
#include <linux/kernel.h>
@@ -103,7 +105,11 @@ typedef char *charp;
#ifdef __KERNEL__
/* Kernel versions... */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
#define KMEM_CACHE_T kmem_cache_t
#else
#define KMEM_CACHE_T struct kmem_cache
#endif
#define KZALLOC(size, gfp) my_kzalloc(size, gfp)
#define KZFREE(p) \
@@ -112,6 +118,7 @@ typedef char *charp;
kfree(p); \
} while (0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, char *buf)
@@ -119,6 +126,12 @@ typedef char *charp;
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
#else
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, const char *buf, size_t count)
#endif
#define DRIVER_ATTR_READER(name, drv, buf) \
ssize_t name(struct device_driver *drv, char * buf)
@@ -131,9 +144,19 @@ typedef char *charp;
#define SET_PROC_DIRENTRY_OWNER(p) do { } while (0);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
/* Also don't define this for later RHEL >= 5.2. */
#if defined(RHEL_RELEASE_CODE) && defined(RHEL_RELEASE_VERSION)
#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 3)
typedef int bool;
#endif
#else
typedef int bool;
#endif /* ifdef __KERNEL__ */
#endif
#endif
#else
typedef int bool;
#endif
typedef struct xbus xbus_t;
typedef struct xpd xpd_t;
typedef struct xframe xframe_t;

View File

@@ -34,15 +34,15 @@ static void __xframe_dump_queue(struct xframe_queue *q)
xframe_t *xframe;
int i = 0;
char prefix[30];
ktime_t now = ktime_get();
struct timeval now;
do_gettimeofday(&now);
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
THIS_MODULE->name, q->name);
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
s64 usec = ktime_us_delta(now, xframe->kt_queued);
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5lld.%03lld msec",
long usec = usec_diff(&now, &xframe->tv_queued);
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
i++, usec / 1000, usec % 1000);
dump_packet(prefix, pack, 1);
}
@@ -60,7 +60,9 @@ static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
if (q->count >= q->max_count) {
q->overflows++;
if ((overflow_cnt++ % 1000) < 5) {
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02lld.%lld ms\n",
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d "
"worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count,
q->max_count, q->worst_count, q->overflows,
q->worst_lag_usec / 1000,
@@ -73,7 +75,7 @@ static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
if (++q->count > q->worst_count)
q->worst_count = q->count;
list_add_tail(&xframe->frame_list, &q->head);
xframe->kt_queued = ktime_get();
do_gettimeofday(&xframe->tv_queued);
out:
return ret;
}
@@ -94,8 +96,8 @@ static xframe_t *__xframe_dequeue(struct xframe_queue *q)
{
xframe_t *frm = NULL;
struct list_head *h;
ktime_t now;
s64 usec_lag;
struct timeval now;
unsigned long usec_lag;
if (list_empty(&q->head))
goto out;
@@ -103,8 +105,12 @@ static xframe_t *__xframe_dequeue(struct xframe_queue *q)
list_del_init(h);
--q->count;
frm = list_entry(h, xframe_t, frame_list);
now = ktime_get();
usec_lag = ktime_us_delta(now, frm->kt_queued);
do_gettimeofday(&now);
usec_lag =
(now.tv_sec - frm->tv_queued.tv_sec) * 1000 * 1000 + (now.tv_usec -
frm->
tv_queued.
tv_usec);
if (q->worst_lag_usec < usec_lag)
q->worst_lag_usec = usec_lag;
out:
@@ -278,7 +284,7 @@ xframe_t *get_xframe(struct xframe_queue *q)
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
atomic_set(&xframe->frame_len, 0);
xframe->first_free = xframe->packets;
xframe->kt_created = ktime_get();
do_gettimeofday(&xframe->tv_created);
/*
* If later parts bother to correctly initialize their
* headers, there is no need to memset() the whole data.

View File

@@ -19,7 +19,7 @@ struct xframe_queue {
/* statistics */
unsigned int worst_count;
unsigned int overflows;
s64 worst_lag_usec; /* since xframe creation */
unsigned long worst_lag_usec; /* since xframe creation */
};
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,

View File

@@ -31,8 +31,11 @@
#include <linux/device.h>
#include <linux/version.h>
#include <asm/atomic.h>
#include <linux/slab.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
#include <linux/moduleparam.h>
#endif /* __KERNEL__ */
@@ -74,7 +77,14 @@
struct card_desc_struct {
struct list_head card_list;
u32 magic;
struct unit_descriptor unit_descriptor;
__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 */
};
typedef enum xpd_direction {
@@ -163,12 +173,11 @@ 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 xpd_type;
xpd_type_t type;
const char *type_name;
__u8 subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;
@@ -207,7 +216,7 @@ struct xpd {
#define for_each_line(xpd, i) \
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
#define IS_BRI(xpd) ((xpd)->xpd_type == XPD_TYPE_BRI)
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
#define TICK_TOLERANCE 500 /* usec */
#ifdef DEBUG_SYNC_PARPORT
@@ -227,7 +236,7 @@ static inline void *my_kzalloc(size_t size, gfp_t flags)
}
struct xpd_driver {
xpd_type_t xpd_type;
xpd_type_t type;
struct device_driver driver;
#define driver_to_xpd_driver(driver) \

View File

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

Some files were not shown because too many files have changed in this diff Show More