Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9992268a30 | ||
|
|
9fa8a58e2d | ||
|
|
c6e5ab448c | ||
|
|
8ff6810740 | ||
|
|
f3262ae381 | ||
|
|
c3c891abdd | ||
|
|
2fb5d7d6d7 | ||
|
|
08ce93306d | ||
|
|
dac1d88399 | ||
|
|
5218e90962 | ||
|
|
da2406db64 | ||
|
|
0b52fb24a0 | ||
|
|
2f880acd10 | ||
|
|
950a3f2486 | ||
|
|
2405c809e7 | ||
|
|
eb1c6cbeed |
52
.gitignore
vendored
52
.gitignore
vendored
@@ -1,52 +0,0 @@
|
||||
# Files that are generated as part of the build process which we do not want git
|
||||
# to track.
|
||||
|
||||
/.pc
|
||||
|
||||
*.[oa]
|
||||
*.mod
|
||||
*.mod.[oc]
|
||||
*.ko
|
||||
*.ko.unsigned
|
||||
*.cmd
|
||||
*.order
|
||||
*.tar.gz
|
||||
tags
|
||||
cscope.*
|
||||
*.symvers
|
||||
*.markers
|
||||
.*.o.d
|
||||
|
||||
README.html
|
||||
modules.order
|
||||
Module.markers
|
||||
build_tools/checkpatch.pl
|
||||
drivers/dahdi/xpp/*.verified
|
||||
drivers/dahdi/.tmp_versions/
|
||||
drivers/dahdi/Module.symvers
|
||||
drivers/dahdi/makefw
|
||||
drivers/dahdi/radfw.h
|
||||
drivers/dahdi/tor2fw.h
|
||||
drivers/dahdi/xpp/init_fxo_modes
|
||||
drivers/dahdi/xpp/print_fxo_modes
|
||||
drivers/dahdi/xpp/xpp_version.h
|
||||
include/dahdi/version.h
|
||||
drivers/dahdi/vpmadt032_loader/vpmadt032_loader.h
|
||||
drivers/dahdi/vpmadt032_loader/vpmadt032_x86_32.o_shipped
|
||||
drivers/dahdi/vpmadt032_loader/vpmadt032_x86_64.o_shipped
|
||||
drivers/dahdi/firmware/dahdi-fw-hx8.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-oct6114-064.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-oct6114-128.bin
|
||||
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
|
||||
39
Makefile
39
Makefile
@@ -47,6 +47,8 @@ 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
|
||||
@@ -62,7 +64,17 @@ ASCIIDOC_CMD:=$(ASCIIDOC) -n -a toc -a toclevels=4
|
||||
|
||||
GENERATED_DOCS:=README.html
|
||||
|
||||
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
|
||||
ifneq ($(wildcard .version),)
|
||||
DAHDIVERSION:=$(shell cat .version)
|
||||
else
|
||||
ifneq ($(wildcard .svn),)
|
||||
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
|
||||
else
|
||||
ifneq ($(wildcard .git),)
|
||||
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
all: modules
|
||||
|
||||
@@ -85,7 +97,7 @@ prereq: include/dahdi/version.h firmware-loaders
|
||||
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 +106,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)"
|
||||
@@ -102,6 +114,8 @@ install-modconf:
|
||||
/sbin/update-modules ; \
|
||||
fi
|
||||
|
||||
install-xpp-firm:
|
||||
$(MAKE) -C drivers/dahdi/xpp/firmwares install
|
||||
|
||||
install-firmware:
|
||||
ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
@@ -126,6 +140,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 \
|
||||
@@ -167,16 +189,12 @@ update:
|
||||
echo "Not under version control"; \
|
||||
fi
|
||||
|
||||
dist:
|
||||
@./build_tools/make_dist "dahdi-linux" "$(DAHDIVERSION)"
|
||||
|
||||
clean:
|
||||
ifneq (no,$(HAS_KSRC))
|
||||
$(KMAKE) clean
|
||||
endif
|
||||
@rm -f $(GENERATED_DOCS)
|
||||
$(MAKE) -C drivers/dahdi/firmware clean
|
||||
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x' clean
|
||||
|
||||
distclean: dist-clean
|
||||
|
||||
@@ -188,20 +206,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:
|
||||
|
||||
725
README
725
README
@@ -12,46 +12,42 @@ 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
|
||||
@@ -166,23 +162,197 @@ to the script:
|
||||
./build_tools/make_static_devs -d tmp/newroot/dev/dahdi
|
||||
|
||||
|
||||
DKMS
|
||||
~~~~
|
||||
DKMS, Dynamic Kernel Module Support, is a framework for building Linux
|
||||
kernel modules. It is used, among others, by several distributions that
|
||||
package the DAHDI kernel modules.
|
||||
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.
|
||||
|
||||
DKMS is designed to provide updates over drivers installed from original
|
||||
kernel modules tree. Thus it installed modules into /lib/modules/updates
|
||||
or /lib/modules/VERSION/updates . This is generally not an issue on
|
||||
normal operation. However if you try to install DAHDI from source on
|
||||
a system with DAHDI installed from DKMS this way (potentially of an
|
||||
older version), be sure to remove the DKMS-installed modules from the
|
||||
updates directory. If you're not sure, the following command will give
|
||||
you a clue of the versions installed:
|
||||
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.
|
||||
|
||||
find /lib/modules -name dahdi.ko
|
||||
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:
|
||||
|
||||
1. 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.
|
||||
|
||||
2. Edit drivers/dahdi/Kbuild and uncomment the two lines related to OSLEC.
|
||||
|
||||
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].
|
||||
|
||||
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
|
||||
@@ -250,17 +420,54 @@ reside directly under /sys/module/'module_name' .
|
||||
|
||||
Useful module parameters:
|
||||
|
||||
=== debug
|
||||
(most modules)
|
||||
debug (most modules)::
|
||||
Sets debug mode / debug level. With most modules 'debug' can be either
|
||||
disabled (0, the default value) or enabled (any other value).
|
||||
+
|
||||
+
|
||||
wctdm and wcte1xp print several extra debugging messages if the value
|
||||
of debug is more than 1.
|
||||
+
|
||||
+
|
||||
Some modules have "debugging flags" bits - the value of debug is a
|
||||
bitmask and several messages are printed if some bits are set:
|
||||
- wctdm24xxp:
|
||||
* 1: DEBUG_CARD
|
||||
* 2: DEBUG_ECHOCAN
|
||||
- wct4xxp:
|
||||
* 1: DEBUG_MAIN
|
||||
* 2: DEBUG_DTMF
|
||||
* 4: DEBUG_REGS
|
||||
* 8: DEBUG_TSI
|
||||
* 16: DEBUG_ECHOCAN
|
||||
* 32: DEBUG_RBS
|
||||
* 64: DEBUG_FRAMER
|
||||
- xpp: See also README.Astribank:
|
||||
* 1: GENERAL - General debug comments.
|
||||
* 2: PCM - PCM-related messages. Tend to flood logs.
|
||||
* 4: LEDS - Anything related to the LEDs status control. The driver
|
||||
produces a lot of messages when the option is enabled.
|
||||
* 8: SYNC - Synchronization related messages.
|
||||
* 16: SIGNAL - DAHDI signalling related messages.
|
||||
* 32: PROC - Messages related to the procfs interface.
|
||||
* 64: REGS - Reading and writing to chip registers. Tends to flood
|
||||
logs.
|
||||
* 128: DEVICES - Device instantiation, destruction and such.
|
||||
* 256 - COMMANDS - Protocol commands. Tends to flood logs.
|
||||
|
||||
Sets debug mode / debug level. With most modules 'debug' can be either
|
||||
disabled (0, the default value) or enabled (any other value).
|
||||
deftaps (dahdi)::
|
||||
The default size for the echo canceller. The number is in "taps", that
|
||||
is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms.
|
||||
+
|
||||
+
|
||||
Asterisk's chan_dahdi tends to pass its own value anyway, with a
|
||||
different default size. So normally setting this doesn't change
|
||||
anything.
|
||||
|
||||
wctdm and wcte1xp print several extra debugging messages if the value
|
||||
of debug is more than 1.
|
||||
|
||||
Some modules have "debugging flags" bits - the value of debug is a
|
||||
bitmask and several messages are printed if some bits are set:
|
||||
max_pseudo_channels (dahdi)::
|
||||
The maximum number of pseudo channels that dahdi will allow userspace to
|
||||
create. Pseudo channels are used when conferencing channels together.
|
||||
The default is 512.
|
||||
|
||||
To get a list of parameters supported by a module, use
|
||||
|
||||
@@ -268,188 +475,13 @@ To get a list of parameters supported by a module, use
|
||||
|
||||
Or, for a module you have just built:
|
||||
|
||||
modinfo ./drivers/dahdi/module_name.ko
|
||||
modinfo ./module_name.ko
|
||||
|
||||
For the xpp modules this will also include the description and default
|
||||
value of the module. You can find a list of useful xpp module parameters
|
||||
in README.Astribank .
|
||||
|
||||
|
||||
- wctdm24xxp:
|
||||
* 1: DEBUG_CARD
|
||||
* 2: DEBUG_ECHOCAN
|
||||
- wct4xxp:
|
||||
* 1: DEBUG_MAIN
|
||||
* 2: DEBUG_DTMF
|
||||
* 4: DEBUG_REGS
|
||||
* 8: DEBUG_TSI
|
||||
* 16: DEBUG_ECHOCAN
|
||||
* 32: DEBUG_RBS
|
||||
* 64: DEBUG_FRAMER
|
||||
- xpp: See also README.Astribank:
|
||||
* 1: GENERAL - General debug comments.
|
||||
* 2: PCM - PCM-related messages. Tend to flood logs.
|
||||
* 4: LEDS - Anything related to the LEDs status control. The driver
|
||||
produces a lot of messages when the option is enabled.
|
||||
* 8: SYNC - Synchronization related messages.
|
||||
* 16: SIGNAL - DAHDI signalling related messages.
|
||||
* 32: PROC - Messages related to the procfs interface.
|
||||
* 64: REGS - Reading and writing to chip registers. Tends to flood
|
||||
logs.
|
||||
* 128: DEVICES - Device instantiation, destruction and such.
|
||||
* 256 - COMMANDS - Protocol commands. Tends to flood logs.
|
||||
+
|
||||
+
|
||||
The script xpp_debug in the source tree can help settting them at run
|
||||
time.
|
||||
|
||||
=== deftaps
|
||||
(dahdi)
|
||||
|
||||
The default size for the echo canceller. The number is in "taps", that
|
||||
is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms.
|
||||
|
||||
Asterisk's chan_dahdi tends to pass its own value anyway, with a
|
||||
different default size. So normally setting this doesn't change
|
||||
anything.
|
||||
|
||||
=== max_pseudo_channels
|
||||
(dahdi)
|
||||
|
||||
The maximum number of pseudo channels that dahdi will allow userspace to
|
||||
create. Pseudo channels are used when conferencing channels together.
|
||||
The default is 512.
|
||||
|
||||
=== auto_assign_spans
|
||||
(dahdi)
|
||||
|
||||
See <<_span_assignments,Span Assignments>> below.
|
||||
|
||||
XPP (Astribank) module parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
==== debug
|
||||
(all modules) - see above.
|
||||
|
||||
==== 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).
|
||||
|
||||
==== initdir
|
||||
(xpp)
|
||||
|
||||
Deprecated. Setting both initdir and tools_rootdir will generate an error.
|
||||
|
||||
A directory under tools_rootdir containing the initialization scripts.
|
||||
The default is /usr/share/dahdi .
|
||||
Setting this value could be useful if that location is inconvenient for you.
|
||||
|
||||
==== rx_tasklet
|
||||
(xpp)
|
||||
|
||||
Enable (1) or disable (0) doing most of the packets processing in
|
||||
separate tasklets. This should probably help on higher-end systems with
|
||||
multiple Astribanks.
|
||||
|
||||
==== vmwi_ioctl
|
||||
(xpd_fxs)
|
||||
|
||||
Does userspace support VMWI notification via ioctl? Default: 1 (yes).
|
||||
|
||||
Disable this (0) to have the driver attempt to detect the voicemail
|
||||
message waiting indication status for this port from FSK messages
|
||||
userspace (Asterisk) sends. Set the ports to use AC neon-lamp style
|
||||
message waiting indication. The detection from the FSK messages takes
|
||||
extra CPU cycles but is required with e.g. Asterisk < 1.6.0 .
|
||||
|
||||
Also note that in order for this parameter to take effect, it must be
|
||||
set before the span is registered. This practically means that it
|
||||
should be set through modprobe.d files.
|
||||
|
||||
See also Voicemail Indication in README.Astribank.
|
||||
|
||||
==== usb1
|
||||
(xpp_usb)
|
||||
|
||||
Enable (1) or disable (0) support of USB1 devices. Disabled by default.
|
||||
|
||||
USB1 devices are not well-tested. It seems that they don't work at all
|
||||
for Astribank BRI. Generally they should work with the current code, but
|
||||
we expect the voice quality issues. Hence we would like to make it
|
||||
very clear that you if you have a USB1 port (rather than a USB2 one, as
|
||||
recommended) you will have to take an action to enable the device.
|
||||
|
||||
==== poll intervals
|
||||
(various)
|
||||
|
||||
There are various values which the driver occasionally polls the
|
||||
device for. For instance, the parameter poll_battery_interval for
|
||||
xpd_fxo to poll the battery, in order to know if the telco line is
|
||||
actually connected.
|
||||
|
||||
The value of those parameters is typically a number in milliseconds.
|
||||
0 is used to disable polling. Under normal operation there should be
|
||||
no reason to play with those parameters.
|
||||
|
||||
==== dtmf_detection
|
||||
(xpd_fxs)
|
||||
|
||||
Enable (1) or disable (0) support of hardware DTMF detection by the
|
||||
Astribank.
|
||||
|
||||
==== caller_id_style
|
||||
(xpd_fxo)
|
||||
|
||||
Various types of caller ID signalling styles require knowing the PCM
|
||||
even when the line is on-hook (which is usually a waste of CPU and
|
||||
bandwidth). This parameter allows fine-tuning the behaviour here:
|
||||
|
||||
* 0 (default) - Don't pass extra PCM when on-hook.
|
||||
* 1 ETSI-FSK: Wait for polarity reversal to come before a ring and
|
||||
then start passing PCM until the caller ID has been passed.
|
||||
* 2 ETSI-DTMF: Always pass PCM and generate a DTMF if polarity reversal is
|
||||
detected before ring.
|
||||
* 3 Passthrough: Always pass PCM as-is.
|
||||
|
||||
This parameter is read-only. It cannot be changed at run-time.
|
||||
|
||||
==== battery_threshold
|
||||
(xpd_fxo)
|
||||
|
||||
Minimum voltage that shows there is battery. Defaults to 3. Normally you
|
||||
should not need to change this, unless dealing with a funky PSTN
|
||||
provider.
|
||||
|
||||
==== battery_debounce
|
||||
(xpd_fxo)
|
||||
|
||||
Minimum interval (msec) for detection of battery off (as opposed to e.g.
|
||||
a temporary power denial to signal a hangup). Defaults to 1000. As with
|
||||
battery_threshold above, there's normally no need to tweak it.
|
||||
|
||||
==== use_polrev_firmware
|
||||
(xpd_fxo)
|
||||
|
||||
Enable (1, default) or disable (0) support for polarity reversal
|
||||
detection in the hardware. Only has effect with PIC_TYPE_2.hex rev. >=
|
||||
11039 and with the initialization changes (init_card_2_30) in rev.
|
||||
949aa49.
|
||||
|
||||
This parameter is read-only. It cannot be changed at run-time.
|
||||
|
||||
|
||||
Internals
|
||||
---------
|
||||
DAHDI Device Files
|
||||
@@ -461,14 +493,9 @@ or dynamically through the udev system.
|
||||
|
||||
* /dev/dahdi/ctl (196:0) - a general device file for various information and
|
||||
control operations on the DAHDI channels.
|
||||
* /dev/dahdi/chan/N/M - A device file for channel M in span N
|
||||
- Both N and M are zero padded 3 digit numbers
|
||||
- Both N and M start at 001
|
||||
- M is chanpos - numbering relative to the current span.
|
||||
* /dev/dahdi/NNN (196:NNN) - for NNN in the range 1-249. A device file for
|
||||
DAHDI channel NNN. It can be used to read data from the channel
|
||||
and write data to the channel. It is not generated by default but may
|
||||
be generated as a symlink using udev rules.
|
||||
and write data to the channel.
|
||||
* /dev/dahdi/transcode (196:250) - Used to connect to a DAHDI transcoding
|
||||
device.
|
||||
* /dev/dahdi/timer (196:253) - Allows setting timers. Used anywhere?
|
||||
@@ -511,7 +538,6 @@ timing device it will hang forever in the first cycle. Otherwise it will just
|
||||
give you in each cycle the percent of how close it was. Also try running it
|
||||
with the option -v for a verbose output.
|
||||
|
||||
|
||||
Spans and Channels
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
DAHDI provides telephony *channels* to the userspace applications.
|
||||
@@ -531,81 +557,6 @@ There are up to 128 spans and 1024 channels. This is a hard-wired limit
|
||||
number fits in a 16 bits number). Channel and span numbers start at 1.
|
||||
|
||||
|
||||
Span Assignments
|
||||
~~~~~~~~~~~~~~~~
|
||||
A DAHDI device (e.g. a PCI card) is represented within the DAHDI drivers
|
||||
as a 'DAHDI device'. Normally (with auto_assign_spans=1 in the module
|
||||
dahdi, which is the default), when a device is discovered and loaded,
|
||||
it registers with the DAHDI core and its spans automatically become
|
||||
available. However if you have more than one device, you may be
|
||||
interested to set explicit spans and channels numbers for them. To use
|
||||
manual span assigment, set 'auto_assign_spans' to 0 . e.g. in a file
|
||||
under /etc/modprobe.d/ include the following line:
|
||||
|
||||
options dahdi auto_assign_spans=0
|
||||
|
||||
You will then need to assign the spans manually at device startup. You
|
||||
will need to assign a span number and channel numbers for each
|
||||
available span on the system. On my test system I have one BRI PCI card
|
||||
and one Astribank BRI+FXS:
|
||||
|
||||
# grep . /sys/bus/dahdi_devices/devices/*/spantype
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:1:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:2:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:3:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:4:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:5:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:6:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:7:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:8:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:9:FXS
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:1:TE
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:2:TE
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:3:NT
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:4:NT
|
||||
|
||||
All spans here, except the FXS one, are BRI spans with 3 channels per span.
|
||||
|
||||
In order to assign a span, we write three numbers separated by colns to
|
||||
the file 'assign_span' in the SysFS node
|
||||
|
||||
local_num:span_num:base_chan_num
|
||||
|
||||
Thus:
|
||||
|
||||
echo 9:5:10 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
echo 2:8:40 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
|
||||
echo 1:1:1 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
echo 4:6:20 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
|
||||
echo 3:2:5 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
|
||||
As you can see, the order of span numbers or local span number is
|
||||
insignificant. However the order of channel numbers must be the same as
|
||||
that of span numbers.
|
||||
|
||||
Which indeed produced:
|
||||
|
||||
# head -n3 -q /proc/dahdi/*
|
||||
Span 1: XBUS-00/XPD-00 "Xorcom XPD [usb:LAB-0003].1: BRI_NT"
|
||||
|
||||
1 XPP_BRI_NT/00/00/0
|
||||
Span 2: XBUS-00/XPD-02 "Xorcom XPD [usb:LAB-0003].3: BRI_TE"
|
||||
|
||||
5 XPP_BRI_TE/00/02/0
|
||||
Span 5: XBUS-00/XPD-10 "Xorcom XPD [usb:LAB-0003].9: FXS" (MASTER)
|
||||
|
||||
10 XPP_FXS/00/10/0
|
||||
Span 6: B4/0/4 "B4XXP (PCI) Card 0 Span 4" RED
|
||||
|
||||
23 B4/0/4/1 YELLOW
|
||||
Span 8: B4/0/2 "B4XXP (PCI) Card 0 Span 2" RED
|
||||
|
||||
40 B4/0/2/1 RED
|
||||
|
||||
Likewise spans can be unassigned by writing to the 'unassign-span'
|
||||
"file".
|
||||
|
||||
|
||||
Dynamic Spans
|
||||
~~~~~~~~~~~~~
|
||||
Dynamic spans are spans that are not represented by real hardware.
|
||||
@@ -693,174 +644,6 @@ see an extra '(In use)':
|
||||
2 XPP_FXS/0/0/1 FXOLS (In use)
|
||||
|
||||
|
||||
SysFS Interface
|
||||
~~~~~~~~~~~~~~~
|
||||
DAHDI exposes several interfaces under the SysFS virtual file system.
|
||||
SysFS represents kernel objects in nodes - directories. There properties
|
||||
are often files. They may also contain other nodes or include symlinks
|
||||
to other nodes.
|
||||
|
||||
Class DAHDI
|
||||
^^^^^^^^^^^
|
||||
Under /sys/class/dadhi there exists a node for the non-channel DAHDI
|
||||
device file under /dev/dahdi. The name is 'dahdi!foo' for the file
|
||||
'/dev/dahdi/foo' (udev translates exclamation marks to slashes). Those
|
||||
nodes are not, for the most part, proper SysFS nodes, and don't include
|
||||
any interesting properties. The files in this class `ctl`, `timer`,
|
||||
`channel`, `pseudo` and (if exists) `transcode`.
|
||||
|
||||
|
||||
Devices Bus
|
||||
^^^^^^^^^^^
|
||||
Each DAHDI device (a physical device, such as a PCI card) is represented
|
||||
by a node under /sys/bus/dahdi_devices/devices named with the name of
|
||||
its device.
|
||||
|
||||
Its attributes include:
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/assgin-span
|
||||
Write-only attribute: this device's spans should now be assigned
|
||||
("registered"). See section about <<_span_assignments>>.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/auto-assign
|
||||
Write-only attribute. Spans in the device auto-assign ("register" as in
|
||||
the original interface). See section about <<_span_assignments>>.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/hardware_id
|
||||
A unique hardware-level identifier (e.g. serial number), if available.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/manufacturer
|
||||
The name of the manufacturer. Freeform-string.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/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
|
||||
it before span nodes are created.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
|
||||
Device type.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/unassign-span
|
||||
Write-only attribute: the span whose device-local number is written
|
||||
should now be unassigned ("unregistered"). See section about
|
||||
<<_span_assignments>>.
|
||||
|
||||
|
||||
Spans Bus
|
||||
^^^^^^^^^
|
||||
Each DAHDI span is represented by a node under
|
||||
/sys/bus/dahdi_spans/devices with the name 'span-N' (where N is the
|
||||
number of the span). Spans of each device also reside under the node of
|
||||
the device.
|
||||
|
||||
Useful attributes in the span node:
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/alarms
|
||||
The alarms of the span. Currently this is a numeric representation.
|
||||
This may change in the future.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/basechan
|
||||
The channel number of the first channel. The channel numbers of the
|
||||
following channels are guaranteed to follow it.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/channels
|
||||
The number of the channels in the span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/desc
|
||||
A free-form description of the span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/is_digital
|
||||
1 if the span is digital, 0 if it isn't.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/is_sync_master
|
||||
1 if the span is the sync master, 0 if it isn't.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/lbo
|
||||
LBO setting for the channel.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/lineconfig
|
||||
The framing and coding of the span, for a digital span. Textual
|
||||
represenation:
|
||||
|
||||
<B8ZS|AMI|HDB3>/<D4|ESF|CCS>[/CRC4]
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/local_spanno
|
||||
The number of the span within the DAHDI device.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/name
|
||||
A concise name for this span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/spantype
|
||||
A very short type string.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
|
||||
Current sync source.
|
||||
|
||||
==== 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
|
||||
^^^^^^^^^^^^
|
||||
Each DAHDI channel is represented by a node under
|
||||
/sys/bus/dahdi_channels/devices with the name 'dahdi!channels!N!M'
|
||||
(where N is the number of the span and M is the number of the channel
|
||||
in the span - chanpos). Channels of each span also reside under the node
|
||||
of the span.
|
||||
|
||||
Useful attributes in the channel node (All attributed listed below are
|
||||
read-only):
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/alarms
|
||||
List of names of the current active alarms (space separated). Normally
|
||||
(no alarms) empty. Example:
|
||||
|
||||
RED YELLOW
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/blocksize
|
||||
The block size set by userspace.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/channo
|
||||
The (global) channel number.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/chanpos
|
||||
The channel number within the span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/dev
|
||||
Major and minor device numbers.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/ec_factory
|
||||
The name of the echo canceller to be used in the channel, if one is
|
||||
configured. Example:
|
||||
|
||||
MG2
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/ec_state
|
||||
State of the echo canceller. ACTIVE: configured and inuse. INACTIVE
|
||||
otherwise.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/in_use
|
||||
1 if the channel is in use (was opepend by userspace), 0 otherwise.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/name
|
||||
A name string for the channel
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/sig
|
||||
The signalling types set for the channel. A space-separated list of
|
||||
signalling types.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/sigcap
|
||||
The signalling types this channel may be configured to handle. A space-
|
||||
separated list of signalling types.
|
||||
|
||||
|
||||
User-space Interface
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
User-space programs can only work with DAHDI channels. The basic
|
||||
@@ -938,7 +721,7 @@ standard HDLC rate of 64k).
|
||||
Low-Level Drivers
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Low-level drivers create spans ('struct dahdi_span'). They register the
|
||||
spans with the DAHDI core using 'dahdi_device_register()'.
|
||||
spans with the DAHDI core using 'dahdi_register()'.
|
||||
|
||||
'struct dahdi_span' has a number of informative members that are updated
|
||||
solely by the low-level driver:
|
||||
@@ -1246,5 +1029,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]
|
||||
|
||||
@@ -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
40
build_tools/genudevrules
Executable 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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -293,10 +293,6 @@ load)
|
||||
# TODO: A local copy of Asterisk, configured with dahdi_gnconf.
|
||||
# doable, but trickier.
|
||||
run_asterisk
|
||||
if [ "$LIVE_DAHDI_FREEPBXDB" = 'yes' ]; then
|
||||
GENCONF_PARAMETERS=$DESTDIR/etc/dahdi/genconf_parameters \
|
||||
dahdi_genconf freepbxdb
|
||||
fi
|
||||
;;
|
||||
genconf)
|
||||
genconf
|
||||
|
||||
@@ -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'"
|
||||
@@ -1,21 +1,118 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -f ${1}/.version ]; then
|
||||
cat ${1}/.version
|
||||
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 --long --always --tags --dirty=M 2> /dev/null`
|
||||
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
|
||||
pwd -P
|
||||
fi
|
||||
|
||||
@@ -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
|
||||
@@ -6,40 +6,20 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH) += dahdi_dynamic_eth.o
|
||||
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_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
|
||||
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_WCTE12XP) += wcte12xp/
|
||||
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
|
||||
|
||||
endif
|
||||
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
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/
|
||||
|
||||
@@ -51,15 +31,16 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_MG2) += dahdi_echocan_mg2.o
|
||||
|
||||
obj-m += $(DAHDI_MODULES_EXTRA)
|
||||
|
||||
# If you want to build OSLEC, include the code in the standard location:
|
||||
# drivers/staging/echo . The DAHDI OSLEC echo canceller will be built as
|
||||
# well:
|
||||
ifneq (,$(wildcard $(src)/../staging/echo/echo.c))
|
||||
obj-m += dahdi_echocan_oslec.o
|
||||
obj-m += ../staging/echo/echo.o
|
||||
endif
|
||||
# Only enable this if you think you know what you're doing. This is not
|
||||
# supported yet:
|
||||
#obj-m += dahdi_echocan_oslec.o
|
||||
#
|
||||
# A quick and dirty way to build OSLEC, if you happened to place it
|
||||
# yourself in the dahdi source tree. This is experimental. See README
|
||||
# regarding OSLEC.
|
||||
#obj-m += ../staging/echo/
|
||||
|
||||
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)))
|
||||
@@ -95,7 +76,7 @@ CFLAGS_dahdi_dynamic_ethmf.o := -DNEW_SKB_LINEARIZE
|
||||
endif
|
||||
endif
|
||||
|
||||
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-sysfs-chan.o dahdi-version.o
|
||||
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-version.o
|
||||
|
||||
###############################################################################
|
||||
# Find appropriate ARCH value for VPMADT032 and HPEC binary modules
|
||||
@@ -151,9 +132,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-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
|
||||
|
||||
@@ -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"
|
||||
|
||||
6
drivers/dahdi/Makefile
Normal file
6
drivers/dahdi/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,521 +0,0 @@
|
||||
/* dahdi-sysfs-chan.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, Xorcom
|
||||
* Copyright (C) 2011-2012, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#define DAHDI_PRINK_MACROS_USE_debug
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <dahdi/kernel.h>
|
||||
#include "dahdi.h"
|
||||
#include "dahdi-sysfs.h"
|
||||
|
||||
/* shortcuts, for code readability */
|
||||
#define MAKE_DAHDI_DEV(num, name) \
|
||||
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
|
||||
#define DEL_DAHDI_DEV(num) \
|
||||
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
|
||||
|
||||
static struct class *dahdi_class;
|
||||
|
||||
static dev_t dahdi_channels_devt; /*!< Device number of first channel */
|
||||
static struct cdev dahdi_channels_cdev; /*!< Channels chardev's */
|
||||
|
||||
/*
|
||||
* Flags to remember what initializations already
|
||||
* succeeded.
|
||||
*/
|
||||
static struct {
|
||||
u32 channel_driver:1;
|
||||
u32 channels_bus:1;
|
||||
u32 cdev:1;
|
||||
} should_cleanup;
|
||||
|
||||
#define chan_attr(field, format_string) \
|
||||
static BUS_ATTR_READER(field##_show, dev, buf) \
|
||||
{ \
|
||||
struct dahdi_chan *chan; \
|
||||
\
|
||||
chan = dev_to_chan(dev); \
|
||||
return sprintf(buf, format_string, chan->field); \
|
||||
}
|
||||
|
||||
chan_attr(name, "%s\n");
|
||||
chan_attr(channo, "%d\n");
|
||||
chan_attr(chanpos, "%d\n");
|
||||
chan_attr(blocksize, "%d\n");
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
chan_attr(chanmute, "%d\n");
|
||||
#endif
|
||||
|
||||
static BUS_ATTR_READER(sigcap_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len = 0;
|
||||
int i;
|
||||
uint sigtypes[] = {
|
||||
DAHDI_SIG_FXSLS,
|
||||
DAHDI_SIG_FXSGS,
|
||||
DAHDI_SIG_FXSKS,
|
||||
DAHDI_SIG_FXOLS,
|
||||
DAHDI_SIG_FXOGS,
|
||||
DAHDI_SIG_FXOKS,
|
||||
DAHDI_SIG_EM,
|
||||
DAHDI_SIG_CLEAR,
|
||||
DAHDI_SIG_HDLCRAW,
|
||||
DAHDI_SIG_HDLCFCS,
|
||||
DAHDI_SIG_HDLCNET,
|
||||
DAHDI_SIG_SLAVE,
|
||||
DAHDI_SIG_SF,
|
||||
DAHDI_SIG_CAS,
|
||||
DAHDI_SIG_EM_E1,
|
||||
DAHDI_SIG_DACS_RBS,
|
||||
DAHDI_SIG_HARDHDLC,
|
||||
DAHDI_SIG_MTP2,
|
||||
};
|
||||
chan = dev_to_chan(dev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sigtypes); i++) {
|
||||
uint x = chan->sigcap & sigtypes[i];
|
||||
if (x == sigtypes[i])
|
||||
len += sprintf(buf + len, "%s ", sigstr(x));
|
||||
}
|
||||
while (len > 0 && isspace(buf[len - 1])) /* trim */
|
||||
len--;
|
||||
len += sprintf(buf + len, "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(sig_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
return sprintf(buf, "%s\n", sigstr(chan->sig));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(in_use_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
return sprintf(buf, "%d\n", test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(alarms_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
len = fill_alarm_string(buf, PAGE_SIZE, chan->chan_alarms);
|
||||
buf[len++] = '\n';
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(ec_factory_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len = 0;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
if (chan->ec_factory)
|
||||
len += sprintf(buf, "%s", chan->ec_factory->get_name(chan));
|
||||
buf[len++] = '\n';
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(ec_state_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len = 0;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
if (chan->ec_factory)
|
||||
len += sprintf(buf, "%sACTIVE", (chan->ec_state) ? "" : "IN");
|
||||
buf[len++] = '\n';
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute chan_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(channo),
|
||||
__ATTR_RO(chanpos),
|
||||
__ATTR_RO(sig),
|
||||
__ATTR_RO(sigcap),
|
||||
__ATTR_RO(alarms),
|
||||
__ATTR_RO(ec_factory),
|
||||
__ATTR_RO(ec_state),
|
||||
__ATTR_RO(blocksize),
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
__ATTR_RO(chanmute),
|
||||
#endif
|
||||
__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)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
BUG_ON(!dev);
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
}
|
||||
|
||||
static int chan_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chan_remove(struct device *dev)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver chan_driver = {
|
||||
.name = "dahdi",
|
||||
.bus = &chan_bus_type,
|
||||
#ifndef OLD_HOTPLUG_SUPPORT
|
||||
.owner = THIS_MODULE,
|
||||
#endif
|
||||
.probe = chan_probe,
|
||||
.remove = chan_remove
|
||||
};
|
||||
|
||||
int chan_sysfs_create(struct dahdi_chan *chan)
|
||||
{
|
||||
struct device *dev;
|
||||
struct dahdi_span *span;
|
||||
int res;
|
||||
dev_t devt;
|
||||
|
||||
chan_dbg(DEVICES, chan, "Creating channel %d\n", chan->channo);
|
||||
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
return 0;
|
||||
span = chan->span;
|
||||
devt = MKDEV(MAJOR(dahdi_channels_devt), chan->channo);
|
||||
dev = &chan->chan_device;
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->devt = devt;
|
||||
dev->bus = &chan_bus_type;
|
||||
dev->parent = span->span_device;
|
||||
/*
|
||||
* FIXME: the name cannot be longer than KOBJ_NAME_LEN
|
||||
*/
|
||||
dev_set_name(dev, "dahdi!chan!%03d!%03d", span->spanno, chan->chanpos);
|
||||
dev_set_drvdata(dev, chan);
|
||||
dev->release = chan_release;
|
||||
res = device_register(dev);
|
||||
if (res) {
|
||||
chan_err(chan, "%s: device_register failed: %d\n",
|
||||
__func__, res);
|
||||
put_device(dev);
|
||||
return res;
|
||||
}
|
||||
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chan_sysfs_remove(struct dahdi_chan *chan)
|
||||
{
|
||||
struct device *dev = &chan->chan_device;
|
||||
|
||||
chan_dbg(DEVICES, chan, "Destroying channel %d\n", chan->channo);
|
||||
if (!dev_get_drvdata(dev))
|
||||
return;
|
||||
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
return;
|
||||
dev = &chan->chan_device;
|
||||
BUG_ON(dev_get_drvdata(dev) != chan);
|
||||
device_unregister(dev);
|
||||
/* FIXME: should have been done earlier in dahdi_chan_unreg */
|
||||
chan->channo = -1;
|
||||
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by dahdi_transcode.c
|
||||
*/
|
||||
int dahdi_register_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
static const char *DAHDI_STRING = "dahdi!";
|
||||
char *udevname;
|
||||
|
||||
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
|
||||
GFP_KERNEL);
|
||||
if (!udevname)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(udevname, DAHDI_STRING);
|
||||
strcat(udevname, dev->name);
|
||||
MAKE_DAHDI_DEV(dev->minor, udevname);
|
||||
kfree(udevname);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_register_chardev);
|
||||
|
||||
/*
|
||||
* Used by dahdi_transcode.c
|
||||
*/
|
||||
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
DEL_DAHDI_DEV(dev->minor);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_unregister_chardev);
|
||||
|
||||
/*--------- Sysfs Device handling ----*/
|
||||
|
||||
/*
|
||||
* Describe fixed device files and maintain their
|
||||
* pointer so fixed_devfiles_remove() can always be called
|
||||
* and work cleanly
|
||||
*/
|
||||
static struct {
|
||||
int minor;
|
||||
char *name;
|
||||
void *dev; /* FIXME: wrong type because of old kernels */
|
||||
} fixed_minors[] = {
|
||||
{ DAHDI_CTL, "dahdi!ctl", },
|
||||
{ DAHDI_TIMER, "dahdi!timer", },
|
||||
{ DAHDI_CHANNEL, "dahdi!channel",},
|
||||
{ DAHDI_PSEUDO, "dahdi!pseudo", },
|
||||
};
|
||||
|
||||
/*
|
||||
* Removes /dev/dahdi/{ctl,timer,channel,pseudo}
|
||||
*
|
||||
* It is safe to call it during initialization error handling,
|
||||
* as it skips non existing objects.
|
||||
*/
|
||||
static void fixed_devfiles_remove(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dahdi_class)
|
||||
return;
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
|
||||
void *d = fixed_minors[i].dev;
|
||||
if (d && !IS_ERR(d))
|
||||
dahdi_dbg(DEVICES, "Removing fixed device file %s\n",
|
||||
fixed_minors[i].name);
|
||||
DEL_DAHDI_DEV(fixed_minors[i].minor);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates /dev/dahdi/{ctl,timer,channel,pseudo}
|
||||
*/
|
||||
static int fixed_devfiles_create(void)
|
||||
{
|
||||
int i;
|
||||
int res = 0;
|
||||
|
||||
if (!dahdi_class) {
|
||||
dahdi_err("%s: dahdi_class is not initialized yet!\n",
|
||||
__func__);
|
||||
res = -ENODEV;
|
||||
goto cleanup;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
|
||||
char *name = fixed_minors[i].name;
|
||||
int minor = fixed_minors[i].minor;
|
||||
void *dummy;
|
||||
|
||||
dahdi_dbg(DEVICES, "Making fixed device file %s\n", name);
|
||||
dummy = (void *)MAKE_DAHDI_DEV(minor, name);
|
||||
if (IS_ERR(dummy)) {
|
||||
int res = PTR_ERR(dummy);
|
||||
|
||||
dahdi_err("%s: failed (%d: %s). Error: %d\n",
|
||||
__func__, minor, name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
fixed_minors[i].dev = dummy;
|
||||
}
|
||||
return 0;
|
||||
cleanup:
|
||||
fixed_devfiles_remove();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during driver unload and while handling any error during
|
||||
* driver load.
|
||||
* Always clean any (and only) objects that were initialized (invariant)
|
||||
*/
|
||||
static void sysfs_channels_cleanup(void)
|
||||
{
|
||||
if (should_cleanup.cdev) {
|
||||
dahdi_dbg(DEVICES, "removing channels cdev\n");
|
||||
cdev_del(&dahdi_channels_cdev);
|
||||
should_cleanup.cdev = 0;
|
||||
}
|
||||
if (dahdi_channels_devt) {
|
||||
dahdi_dbg(DEVICES, "unregistering chrdev_region\n");
|
||||
unregister_chrdev_region(dahdi_channels_devt,
|
||||
DAHDI_MAX_CHANNELS);
|
||||
}
|
||||
|
||||
fixed_devfiles_remove();
|
||||
if (dahdi_class) {
|
||||
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
|
||||
class_destroy(dahdi_class);
|
||||
dahdi_class = NULL;
|
||||
}
|
||||
if (should_cleanup.channel_driver) {
|
||||
dahdi_dbg(DEVICES, "Removing channel driver\n");
|
||||
driver_unregister(&chan_driver);
|
||||
should_cleanup.channel_driver = 0;
|
||||
}
|
||||
if (should_cleanup.channels_bus) {
|
||||
dahdi_dbg(DEVICES, "Removing channels bus\n");
|
||||
bus_unregister(&chan_bus_type);
|
||||
should_cleanup.channels_bus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int __init dahdi_sysfs_chan_init(const struct file_operations *fops)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
dahdi_dbg(DEVICES, "Registering channels bus\n");
|
||||
res = bus_register(&chan_bus_type);
|
||||
if (res) {
|
||||
dahdi_err("%s: bus_register(%s) failed. Error number %d\n",
|
||||
__func__, chan_bus_type.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.channels_bus = 1;
|
||||
|
||||
dahdi_dbg(DEVICES, "Registering channel driver\n");
|
||||
res = driver_register(&chan_driver);
|
||||
if (res) {
|
||||
dahdi_err("%s: driver_register(%s) failed. Error number %d",
|
||||
__func__, chan_driver.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.channel_driver = 1;
|
||||
|
||||
dahdi_class = class_create(THIS_MODULE, "dahdi");
|
||||
if (IS_ERR(dahdi_class)) {
|
||||
res = PTR_ERR(dahdi_class);
|
||||
dahdi_err("%s: class_create(dahi_chan) failed. Error: %d\n",
|
||||
__func__, res);
|
||||
goto cleanup;
|
||||
}
|
||||
res = fixed_devfiles_create();
|
||||
if (res)
|
||||
goto cleanup;
|
||||
dahdi_dbg(DEVICES, "allocating chrdev_region\n");
|
||||
res = alloc_chrdev_region(&dahdi_channels_devt,
|
||||
0,
|
||||
DAHDI_MAX_CHANNELS,
|
||||
"dahdi_channels");
|
||||
if (res) {
|
||||
dahdi_err("%s: Failed allocating chrdev for %d channels (%d)",
|
||||
__func__, DAHDI_MAX_CHANNELS, res);
|
||||
goto cleanup;
|
||||
}
|
||||
dahdi_dbg(DEVICES, "adding channels cdev\n");
|
||||
cdev_init(&dahdi_channels_cdev, fops);
|
||||
res = cdev_add(&dahdi_channels_cdev, dahdi_channels_devt,
|
||||
DAHDI_MAX_CHANNELS);
|
||||
if (res) {
|
||||
dahdi_err("%s: cdev_add() failed (%d)", __func__, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.cdev = 1;
|
||||
return 0;
|
||||
cleanup:
|
||||
sysfs_channels_cleanup();
|
||||
return res;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_chan_exit(void)
|
||||
{
|
||||
sysfs_channels_cleanup();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
#ifndef DAHDI_SYSFS_H
|
||||
#define DAHDI_SYSFS_H
|
||||
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count)
|
||||
#define BUS_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf)
|
||||
#define BUS_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count)
|
||||
|
||||
#define DRIVER_ATTR_READER(name, drv, buf) \
|
||||
ssize_t name(struct device_driver *drv, char * buf)
|
||||
|
||||
/* Device file creation macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, NULL, "%s", name)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, name)
|
||||
#else
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
class_device_create(class, NULL, devt, device, name)
|
||||
#endif
|
||||
|
||||
/* Device file destruction macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
device_destroy(class, devt)
|
||||
#else
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
class_device_destroy(class, devt)
|
||||
#endif
|
||||
|
||||
/* Global */
|
||||
int __init dahdi_sysfs_chan_init(const struct file_operations *fops);
|
||||
void dahdi_sysfs_chan_exit(void);
|
||||
|
||||
/* Channel Handling */
|
||||
int chan_sysfs_create(struct dahdi_chan *chan);
|
||||
void chan_sysfs_remove(struct dahdi_chan *chan);
|
||||
|
||||
#endif /* DAHDI_SYSFS_H */
|
||||
@@ -6,7 +6,6 @@
|
||||
*
|
||||
* Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
|
||||
* Copyright (C) 2011, Xorcom
|
||||
* Copyright (C) 2011, Digium, Inc
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -35,28 +34,4 @@ void span_sysfs_remove(struct dahdi_span *span);
|
||||
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops);
|
||||
void dahdi_sysfs_exit(void);
|
||||
|
||||
void dahdi_sysfs_init_device(struct dahdi_device *ddev);
|
||||
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent);
|
||||
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev);
|
||||
|
||||
int dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
|
||||
unsigned int basechan, int prefmaster);
|
||||
int dahdi_unassign_span(struct dahdi_span *span);
|
||||
int dahdi_assign_device_spans(struct dahdi_device *ddev);
|
||||
|
||||
static inline int get_span(struct dahdi_span *span)
|
||||
{
|
||||
return try_module_get(span->ops->owner);
|
||||
}
|
||||
|
||||
static inline void put_span(struct dahdi_span *span)
|
||||
{
|
||||
module_put(span->ops->owner);
|
||||
}
|
||||
|
||||
static inline int local_spanno(struct dahdi_span *span)
|
||||
{
|
||||
return span->offset + 1;
|
||||
}
|
||||
|
||||
#endif /* _DAHDI_H */
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* Converted to use HighResTimers on i386 by Jeffery Palmer <jeff@triggerinc.com>
|
||||
*
|
||||
* Copyright (C) 2002, Hermes Softlab
|
||||
* Copyright (C) 2004-2012, Digium, Inc.
|
||||
* Copyright (C) 2004-2009, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -53,7 +53,7 @@
|
||||
#if defined(USE_HIGHRESTIMER)
|
||||
#include <linux/hrtimer.h>
|
||||
#else
|
||||
#include <linux/timer.h>
|
||||
#include <linux/time.h>
|
||||
#endif
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
@@ -75,7 +75,6 @@ static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
|
||||
#endif
|
||||
|
||||
struct dahdi_dummy {
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan _chan;
|
||||
struct dahdi_chan *chan;
|
||||
@@ -157,7 +156,7 @@ static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1)
|
||||
return ms;
|
||||
}
|
||||
|
||||
static void dahdi_dummy_timer(struct timer_timer *unused)
|
||||
static void dahdi_dummy_timer(unsigned long param)
|
||||
{
|
||||
unsigned long ms_since_start;
|
||||
struct timespec now;
|
||||
@@ -206,44 +205,37 @@ static const struct dahdi_span_ops dummy_ops = {
|
||||
|
||||
static int dahdi_dummy_initialize(struct dahdi_dummy *ztd)
|
||||
{
|
||||
int res = 0;
|
||||
/* DAHDI stuff */
|
||||
ztd->ddev = dahdi_create_device();
|
||||
if (!ztd->ddev)
|
||||
return -ENOMEM;
|
||||
dev_set_name(&ztd->ddev->dev, "dahdi_dummy");
|
||||
ztd->chan = &ztd->_chan;
|
||||
sprintf(ztd->span.name, "DAHDI_DUMMY/1");
|
||||
snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1);
|
||||
sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0);
|
||||
ztd->ddev->devicetype = "DAHDI Dummy Timing";
|
||||
strlcpy(ztd->span.devicetype, "DAHDI Dummy Timing",
|
||||
sizeof(ztd->span.devicetype));
|
||||
ztd->chan->chanpos = 1;
|
||||
ztd->span.chans = &ztd->chan;
|
||||
ztd->span.channels = 0; /* no channels on our span */
|
||||
ztd->span.deflaw = DAHDI_LAW_MULAW;
|
||||
ztd->chan->pvt = ztd;
|
||||
ztd->span.ops = &dummy_ops;
|
||||
list_add_tail(&ztd->span.device_node, &ztd->ddev->spans);
|
||||
res = dahdi_register_device(ztd->ddev, NULL);
|
||||
return res;
|
||||
if (dahdi_register(&ztd->span, 0)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int res;
|
||||
ztd = kzalloc(sizeof(*ztd), GFP_KERNEL);
|
||||
if (ztd == NULL) {
|
||||
printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = dahdi_dummy_initialize(ztd);
|
||||
if (res) {
|
||||
printk(KERN_ERR
|
||||
"dahdi_dummy: Unable to intialize DAHDI driver (%d)\n",
|
||||
res);
|
||||
if (dahdi_dummy_initialize(ztd)) {
|
||||
printk(KERN_ERR "dahdi_dummy: Unable to intialize DAHDI driver\n");
|
||||
kfree(ztd);
|
||||
return res;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#if defined(USE_HIGHRESTIMER)
|
||||
@@ -258,10 +250,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);
|
||||
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)
|
||||
@@ -279,8 +273,7 @@ void cleanup_module(void)
|
||||
atomic_set(&shutdown, 1);
|
||||
del_timer_sync(&timer);
|
||||
#endif
|
||||
dahdi_unregister_device(ztd->ddev);
|
||||
dahdi_free_device(ztd->ddev);
|
||||
dahdi_unregister(&ztd->span);
|
||||
kfree(ztd);
|
||||
if (debug)
|
||||
printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Written by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* Copyright (C) 2001-2012, Digium, Inc.
|
||||
* Copyright (C) 2001-2010, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -88,8 +88,6 @@ static int txerrors;
|
||||
static struct tasklet_struct dahdi_dynamic_tlet;
|
||||
|
||||
static void dahdi_dynamic_tasklet(unsigned long data);
|
||||
#else
|
||||
static struct tasklet_struct dahdi_dynamic_flush_tlet;
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(dspan_mutex);
|
||||
@@ -201,9 +199,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) {
|
||||
@@ -212,25 +208,12 @@ static void __dahdi_dynamic_run(void)
|
||||
dahdi_dynamic_sendmessage(d);
|
||||
}
|
||||
|
||||
#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
|
||||
* of the dynamic spans need to call functions that require interrupts
|
||||
* to be enabled but dahdi_transmit / ...sendmessage needs to be called
|
||||
* each time the masterspan is processed which happens with interrupts
|
||||
* disabled.
|
||||
*
|
||||
*/
|
||||
tasklet_hi_schedule(&dahdi_dynamic_flush_tlet);
|
||||
#endif
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -402,18 +385,32 @@ static void dahdi_dynamic_release(struct kref *kref)
|
||||
|
||||
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
|
||||
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
__module_get(d->driver->owner);
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(d->msgbuf);
|
||||
|
||||
for (x = 0; x < d->span.channels; x++)
|
||||
kfree(d->chans[x]);
|
||||
|
||||
dahdi_free_device(d->ddev);
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
static inline int dynamic_put(struct dahdi_dynamic *d)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
|
||||
kref_put(&d->kref, dahdi_dynamic_release);
|
||||
return 1;
|
||||
#else
|
||||
return kref_put(&d->kref, dahdi_dynamic_release);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void dynamic_get(struct dahdi_dynamic *d)
|
||||
@@ -467,30 +464,12 @@ 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;
|
||||
}
|
||||
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
if (!try_module_get(d->driver->owner)) {
|
||||
/* The driver for this device is in the
|
||||
* process of unloading. Leave this dynamic on
|
||||
* the list so it's cleaned up when the driver
|
||||
* unregisters. */
|
||||
dynamic_put(d);
|
||||
return -ENXIO;
|
||||
}
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
d->pvt = NULL;
|
||||
}
|
||||
|
||||
dahdi_unregister_device(d->ddev);
|
||||
dahdi_unregister(&d->span);
|
||||
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
@@ -599,8 +578,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
kref_init(&d->kref);
|
||||
d->ddev = dahdi_create_device();
|
||||
|
||||
for (x = 0; x < dds->numchans; x++) {
|
||||
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
||||
@@ -625,21 +604,16 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
strlcpy(d->dname, dds->driver, sizeof(d->dname));
|
||||
strlcpy(d->addr, dds->addr, sizeof(d->addr));
|
||||
d->timing = dds->timing;
|
||||
snprintf(d->span.name, sizeof(d->span.name), "DYN/%s/%s",
|
||||
dds->driver, dds->addr);
|
||||
snprintf(d->span.desc, sizeof(d->span.desc),
|
||||
"Dynamic '%s' span at '%s'", dds->driver, dds->addr);
|
||||
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
|
||||
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
|
||||
dds->driver, dds->addr);
|
||||
d->span.deflaw = DAHDI_LAW_MULAW;
|
||||
d->span.flags |= DAHDI_FLAG_RBS;
|
||||
d->span.chans = d->chans;
|
||||
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 |
|
||||
@@ -683,12 +657,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return res;
|
||||
}
|
||||
|
||||
d->ddev->devicetype = d->span.name;
|
||||
d->ddev->hardware_id = d->span.name;
|
||||
dev_set_name(&d->ddev->dev, "dynamic:%s:%d", dds->driver, dtd->id++);
|
||||
list_add_tail(&d->span.device_node, &d->ddev->spans);
|
||||
/* Whee! We're created. Now register the span */
|
||||
if (dahdi_register_device(d->ddev, d->dev)) {
|
||||
if (dahdi_register(&d->span, 0)) {
|
||||
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
||||
d->span.name);
|
||||
dynamic_put(d);
|
||||
@@ -729,20 +699,6 @@ static void dahdi_dynamic_tasklet(unsigned long data)
|
||||
}
|
||||
taskletpending = 0;
|
||||
}
|
||||
#else
|
||||
static void dahdi_dynamic_flush_tasklet(unsigned long data)
|
||||
{
|
||||
struct dahdi_dynamic_driver *drv;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(drv, &driver_list, list) {
|
||||
/* Flush any traffic still pending in the driver */
|
||||
if (drv->flush) {
|
||||
drv->flush();
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data)
|
||||
@@ -805,17 +761,19 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
|
||||
list_for_each_entry_safe(d, n, &dspan_list, list) {
|
||||
if (d->driver == dri) {
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy)
|
||||
if (d->driver && d->driver->destroy) {
|
||||
__module_get(d->driver->owner);
|
||||
d->driver->destroy(d);
|
||||
else
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
dahdi_unregister_device(d->ddev);
|
||||
dahdi_unregister(&d->span);
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||
synchronize_rcu();
|
||||
d->driver = NULL;
|
||||
dynamic_put(d);
|
||||
}
|
||||
}
|
||||
@@ -831,7 +789,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;
|
||||
@@ -859,44 +817,33 @@ static void check_for_red_alarm(TIMER_DATA_TYPE unused)
|
||||
mod_timer(&alarmcheck, jiffies + 1 * HZ);
|
||||
}
|
||||
|
||||
static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = dahdi_dynamic_ioctl,
|
||||
};
|
||||
|
||||
static int dahdi_dynamic_init(void)
|
||||
{
|
||||
dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl);
|
||||
|
||||
/* Start process to check for RED ALARM */
|
||||
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
|
||||
tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
|
||||
#else
|
||||
tasklet_init(&dahdi_dynamic_flush_tlet, dahdi_dynamic_flush_tasklet, 0);
|
||||
#endif
|
||||
dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
|
||||
|
||||
printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dahdi_dynamic_cleanup(void)
|
||||
{
|
||||
dahdi_set_dynamic_ops(NULL);
|
||||
|
||||
#ifdef ENABLE_TASKLETS
|
||||
if (taskletpending) {
|
||||
tasklet_disable(&dahdi_dynamic_tlet);
|
||||
tasklet_kill(&dahdi_dynamic_tlet);
|
||||
}
|
||||
#else
|
||||
tasklet_disable(&dahdi_dynamic_flush_tlet);
|
||||
tasklet_kill(&dahdi_dynamic_flush_tlet);
|
||||
#endif
|
||||
del_timer_sync(&alarmcheck);
|
||||
/* Must call again in case it was running before and rescheduled
|
||||
* itself. */
|
||||
dahdi_set_dynamic_ioctl(NULL);
|
||||
del_timer(&alarmcheck);
|
||||
printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Written by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* Copyright (C) 2001-2012, Digium, Inc.
|
||||
* Copyright (C) 2001-2008, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -71,12 +71,14 @@ static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short sub
|
||||
if (z)
|
||||
span = z->span;
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
|
||||
return NULL;
|
||||
return span;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
|
||||
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
|
||||
#else
|
||||
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
struct ztdeth_header *zh;
|
||||
@@ -85,7 +87,11 @@ static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
|
||||
#else
|
||||
zh = (struct ztdeth_header *)skb->nh.raw;
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
|
||||
span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
|
||||
#else
|
||||
span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr);
|
||||
#endif
|
||||
if (span) {
|
||||
skb_pull(skb, sizeof(struct ztdeth_header));
|
||||
#ifdef NEW_SKB_LINEARIZE
|
||||
@@ -146,7 +152,7 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
|
||||
spin_lock_irqsave(&zlock, flags);
|
||||
z = dyn->pvt;
|
||||
if (z && z->dev) {
|
||||
if (z->dev) {
|
||||
/* Copy fields to local variables to remove spinlock ASAP */
|
||||
dev = z->dev;
|
||||
memcpy(addr, z->addr, sizeof(z->addr));
|
||||
@@ -185,16 +191,15 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ztdeth_flush - Flush all pending transactions.
|
||||
*
|
||||
* This function is always called in softirq context.
|
||||
*/
|
||||
|
||||
static int ztdeth_flush(void)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
while ((skb = skb_dequeue(&skbs)))
|
||||
|
||||
/* Handle all transmissions now */
|
||||
while ((skb = skb_dequeue(&skbs))) {
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -266,7 +271,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) {
|
||||
@@ -281,10 +285,7 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
|
||||
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);
|
||||
}
|
||||
@@ -410,22 +411,20 @@ static struct notifier_block ztdeth_nblock = {
|
||||
|
||||
static int __init ztdeth_init(void)
|
||||
{
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
dev_add_pack(&ztdeth_ptype);
|
||||
register_netdevice_notifier(&ztdeth_nblock);
|
||||
dahdi_dynamic_register_driver(&ztd_eth);
|
||||
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ztdeth_exit(void)
|
||||
{
|
||||
dahdi_dynamic_unregister_driver(&ztd_eth);
|
||||
unregister_netdevice_notifier(&ztdeth_nblock);
|
||||
dev_remove_pack(&ztdeth_ptype);
|
||||
|
||||
skb_queue_purge(&skbs);
|
||||
unregister_netdevice_notifier(&ztdeth_nblock);
|
||||
dahdi_dynamic_unregister_driver(&ztd_eth);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support");
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
/**
|
||||
* Undefine USE_PROC_FS, if you do not want the /proc/dahdi/dynamic-ethmf
|
||||
@@ -225,8 +224,13 @@ static inline int ethmf_trx_spans_ready(unsigned int addr_hash, struct ztdeth *(
|
||||
/**
|
||||
* Ethernet receiving side processing function.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
||||
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev)
|
||||
#else
|
||||
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt)
|
||||
#endif
|
||||
{
|
||||
int num_spans = 0, span_index = 0;
|
||||
unsigned char *data;
|
||||
@@ -263,8 +267,13 @@ static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
|
||||
find_ethmf(eth_hdr(skb)->h_source,
|
||||
htons(span_index), &z, &span);
|
||||
#else
|
||||
find_ethmf(skb->mac.ethernet->h_source,
|
||||
htons(span_index), &z, &span);
|
||||
#endif
|
||||
if (unlikely(!z || !span)) {
|
||||
/* The recv'd span does not belong to us */
|
||||
/* ethmf_errors_inc(); */
|
||||
@@ -387,6 +396,10 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
struct net_device *dev;
|
||||
unsigned char addr[ETH_ALEN];
|
||||
int spans_ready = 0, index = 0;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
unsigned long flags;
|
||||
#endif
|
||||
|
||||
if (atomic_read(&shutdown))
|
||||
return;
|
||||
@@ -398,12 +411,24 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
return;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
|
||||
if (!atomic_read(&z->ready)) {
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
atomic_inc(&z->ready);
|
||||
if (1 == atomic_read(&z->ready)) {
|
||||
memcpy(z->msgbuf, msg, msglen);
|
||||
z->msgbuf_len = msglen;
|
||||
}
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
}
|
||||
#else
|
||||
if (!atomic_read(&z->ready)) {
|
||||
if (atomic_inc_return(&z->ready) == 1) {
|
||||
memcpy(z->msgbuf, msg, msglen);
|
||||
z->msgbuf_len = msglen;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
spans_ready = ethmf_trx_spans_ready(z->addr_hash, &ready_spans);
|
||||
if (spans_ready) {
|
||||
@@ -681,88 +706,96 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PROC_FS
|
||||
static struct proc_dir_entry *proc_entry;
|
||||
static const char *ztdethmf_procname = "dahdi/dynamic-ethmf";
|
||||
|
||||
static int ztdethmf_proc_show(struct seq_file *sfile, void *not_used)
|
||||
static int ztdethmf_proc_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
{
|
||||
struct ztdeth *z = NULL;
|
||||
int i = 0;
|
||||
int len = 0, i = 0;
|
||||
unsigned int group = 0, c = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
seq_printf(sfile, "Errors: %d\n\n", atomic_read(&errcount));
|
||||
len += sprintf(page + len, "Errors: %d\n\n", atomic_read(&errcount));
|
||||
|
||||
for (group = 0; group < ETHMF_MAX_GROUPS; ++group) {
|
||||
if (atomic_read(&(ethmf_groups[group].spans))) {
|
||||
seq_printf(sfile, "Group #%d (0x%x)\n", i++,
|
||||
ethmf_groups[group].hash_addr);
|
||||
seq_printf(sfile, "Spans: %d\n",
|
||||
atomic_read(&(ethmf_groups[group].spans)));
|
||||
len += sprintf(page + len, "Group #%d (0x%x)\n", i++, ethmf_groups[group].hash_addr);
|
||||
len += sprintf(page + len, " Spans: %d\n",
|
||||
atomic_read(&(ethmf_groups[group].spans)));
|
||||
|
||||
c = 1;
|
||||
list_for_each_entry_rcu(z, ðmf_list, list) {
|
||||
if (z->addr_hash == ethmf_groups[group].hash_addr) {
|
||||
if (c == 1) {
|
||||
seq_printf(sfile,
|
||||
len += sprintf(page + len,
|
||||
" Device: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x)\n",
|
||||
z->ethdev,
|
||||
z->addr[0], z->addr[1], z->addr[2],
|
||||
z->addr[3], z->addr[4], z->addr[5]);
|
||||
}
|
||||
seq_printf(sfile, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
|
||||
len += sprintf(page + len, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
|
||||
c++, ntohs(z->subaddr),
|
||||
atomic_read(&z->ready), atomic_read(&z->delay),
|
||||
z->real_channels, atomic_read(&z->no_front_padding));
|
||||
}
|
||||
}
|
||||
seq_printf(sfile, " Device UPs: %u\n",
|
||||
len += sprintf(page + len, " Device UPs: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].devupcount)));
|
||||
seq_printf(sfile, " Device DOWNs: %u\n",
|
||||
len += sprintf(page + len, " Device DOWNs: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].devdowncount)));
|
||||
seq_printf(sfile, " Rx Frames: %u\n",
|
||||
len += sprintf(page + len, " Rx Frames: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].rxframecount)));
|
||||
seq_printf(sfile, " Tx Frames: %u\n",
|
||||
len += sprintf(page + len, " Tx Frames: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].txframecount)));
|
||||
seq_printf(sfile, " Rx Bytes: %u\n",
|
||||
len += sprintf(page + len, " Rx Bytes: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].rxbytecount)));
|
||||
seq_printf(sfile, " Tx Bytes: %u\n",
|
||||
len += sprintf(page + len, " Tx Bytes: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].txbytecount)));
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
}
|
||||
if (len > off+count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ztdethmf_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, ztdethmf_proc_show, NULL);
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
}
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations ztdethmf_proc_fops = {
|
||||
.open = ztdethmf_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
#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);
|
||||
@@ -771,8 +804,8 @@ static int __init ztdethmf_init(void)
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
#ifdef USE_PROC_FS
|
||||
proc_entry = proc_create_data(ztdethmf_procname, 0444, NULL,
|
||||
&ztdethmf_proc_fops, NULL);
|
||||
proc_entry = create_proc_read_entry(ztdethmf_procname, 0444, NULL,
|
||||
ztdethmf_proc_read, NULL);
|
||||
if (!proc_entry) {
|
||||
printk(KERN_ALERT "create_proc_read_entry failed.\n");
|
||||
}
|
||||
|
||||
@@ -78,11 +78,10 @@ static LIST_HEAD(dynamic_local_list);
|
||||
static void
|
||||
dahdi_dynamic_local_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
{
|
||||
struct dahdi_dynamic_local *d;
|
||||
struct dahdi_dynamic_local *const d = dyn->pvt;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&local_lock, flags);
|
||||
d = dyn->pvt;
|
||||
if (d && d->peer && d->peer->span) {
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->peer->span->flags))
|
||||
dahdi_dynamic_receive(d->peer->span, msg, msglen);
|
||||
@@ -131,12 +130,11 @@ static int digit2int(char d)
|
||||
|
||||
static void dahdi_dynamic_local_destroy(struct dahdi_dynamic *dyn)
|
||||
{
|
||||
struct dahdi_dynamic_local *d;
|
||||
struct dahdi_dynamic_local *d = dyn->pvt;
|
||||
unsigned long flags;
|
||||
struct dahdi_dynamic_local *cur;
|
||||
|
||||
spin_lock_irqsave(&local_lock, flags);
|
||||
d = dyn->pvt;
|
||||
list_for_each_entry(cur, &dynamic_local_list, node) {
|
||||
if (cur->peer == d)
|
||||
cur->peer = NULL;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* This "echo can" will completely hose your audio.
|
||||
* Don't use it unless you're absolutely sure you know what you're doing.
|
||||
*
|
||||
* Copyright (C) 2007-2012, Digium, Inc.
|
||||
* Copyright (C) 2007-2008, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -38,6 +38,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
|
||||
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Based upon mec2.h
|
||||
*
|
||||
* Copyright (C) 2002-2012, Digium, Inc.
|
||||
* Copyright (C) 2002, Digium, Inc.
|
||||
*
|
||||
* Additional background on the techniques used in this code can be found in:
|
||||
*
|
||||
@@ -44,6 +44,9 @@
|
||||
static int debug;
|
||||
static int aggressive;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */
|
||||
/* #define MEC2_STATS 4000 */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Based upon kb1ec.h and mec2.h
|
||||
*
|
||||
* Copyright (C) 2002-2012, Digium, Inc.
|
||||
* Copyright (C) 2002, Digium, Inc.
|
||||
*
|
||||
* Additional background on the techniques used in this code can be found in:
|
||||
*
|
||||
@@ -44,6 +44,9 @@
|
||||
static int debug;
|
||||
static int aggressive;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#define ABS(a) abs(a!=-32768?a:-32767)
|
||||
|
||||
#define RESTORE_COEFFS {\
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
|
||||
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
|
||||
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#include "arith.h"
|
||||
|
||||
#ifndef NULL
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#include "fir.h"
|
||||
|
||||
#ifndef NULL
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
#
|
||||
@@ -22,29 +22,16 @@
|
||||
|
||||
.PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object firmware-loaders
|
||||
|
||||
OCT6114_032_VERSION:=1.05.01
|
||||
OCT6114_064_VERSION:=1.05.01
|
||||
OCT6114_128_VERSION:=1.05.01
|
||||
OCT6114_256_VERSION:=1.05.01
|
||||
TC400M_VERSION:=MR6.12
|
||||
VPMADT032_VERSION:=1.25.0
|
||||
HX8_VERSION:=2.06
|
||||
VPMOCT032_VERSION:=1.12.0
|
||||
WCT820_VERSION:=1.76
|
||||
TE133_VERSION:=7a001e
|
||||
TE134_VERSION:=780017
|
||||
TE435_VERSION:=13001e
|
||||
TE436_VERSION:=10017
|
||||
A8A_VERSION:=1d0017
|
||||
A8B_VERSION:=1f001e
|
||||
A4A_VERSION:=a0017
|
||||
A4B_VERSION:=d001e
|
||||
VPMOCT032_VERSION:=1.11.0
|
||||
|
||||
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-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032
|
||||
|
||||
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
|
||||
# First example: dahdi-fw-oct6114-064-1.05.01
|
||||
@@ -53,39 +40,23 @@ ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435
|
||||
# This means this is version MR5.6 of the tc400m firmware
|
||||
|
||||
# Build a list of firmware package filenames we need
|
||||
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
|
||||
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-HX8=dahdi-fw-hx8-$(HX8_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
|
||||
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
|
||||
|
||||
# Build a list of object files if hotplug will not be used
|
||||
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032.o)
|
||||
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-HX8=dahdi-fw-hx8.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
|
||||
|
||||
# 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 +82,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 +101,61 @@ $(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-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-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
|
||||
|
||||
# Uninstall any installed dahdi firmware images from hotplug firmware directories
|
||||
hotplug-uninstall:
|
||||
@@ -163,11 +174,6 @@ make_firmware_object: make_firmware_object.in ../dahdi-base.o
|
||||
sed -e s/BFDNAME/$${BFDNAME}/ -e s/BFDARCH/$${BFDARCH}/ $< > $@
|
||||
@chmod +x $@
|
||||
|
||||
# Build object file of an oct6114 032 firmware image for linking
|
||||
dahdi-fw-oct6114-032.o: dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz dahdi-fw-oct6114-032.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-032.bin
|
||||
./make_firmware_object dahdi-fw-oct6114-032.bin $@
|
||||
|
||||
# Build object file of an oct6114 064 firmware image for linking
|
||||
dahdi-fw-oct6114-064.o: dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz dahdi-fw-oct6114-064.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-064.bin
|
||||
@@ -178,17 +184,7 @@ dahdi-fw-oct6114-128.o: dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz dahdi
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-128.bin
|
||||
./make_firmware_object dahdi-fw-oct6114-128.bin $@
|
||||
|
||||
# Build object file of an oct6114 256 firmware image for linking
|
||||
dahdi-fw-oct6114-256.o: dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz dahdi-fw-oct6114-256.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-256.bin
|
||||
./make_firmware_object dahdi-fw-oct6114-256.bin $@
|
||||
|
||||
# Build object file of a TC400M firmware image for linking
|
||||
dahdi-fw-tc400m.o: dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz dahdi-fw-tc400m.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-tc400m.bin
|
||||
./make_firmware_object dahdi-fw-tc400m.bin $@
|
||||
|
||||
# Build object file of a VPMOCT032 firmware image for linking
|
||||
dahdi-fw-vpmoct032.o: dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz dahdi-fw-vpmoct032.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-vpmoct032.bin
|
||||
./make_firmware_object dahdi-fw-vpmoct032.bin $@
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* DAHDI Telephony Interface to Digium High-Performance Echo Canceller
|
||||
*
|
||||
* Copyright (C) 2006-2012 Digium, Inc.
|
||||
* Copyright (C) 2006-2008 Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#include "hpec_user.h"
|
||||
#include "hpec.h"
|
||||
|
||||
@@ -72,9 +75,18 @@ static int __attribute__((regparm(0), format(printf, 1, 2))) logger(const char *
|
||||
int res;
|
||||
va_list args;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
|
||||
va_start(args, format);
|
||||
res = vprintk(format, args);
|
||||
va_end(args);
|
||||
#else
|
||||
char buf[256];
|
||||
|
||||
va_start(args, format);
|
||||
res = vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
printk(KERN_INFO "%s" buf);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -1,30 +1,38 @@
|
||||
#
|
||||
# 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
|
||||
CFLAGS=-V3.4 -ffunction-sections -I/lib/modules/$(shell uname -r)/build/include -Iinclude -Ioctdeviceapi -Ioctdeviceapi/oct6100api -DGFP_ATOMIC=0 -Dkmalloc=calloc -Dkfree=free
|
||||
LDFLAGS=-V3.4 -Wl,-Map -Wl,test.map -Wl,--gc-sections
|
||||
|
||||
# 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
|
||||
lib-y := $(octapi_files)
|
||||
APIDIR=octdeviceapi/oct6100api/oct6100_api
|
||||
|
||||
OCTASIC_OBJS=$(APIDIR)/oct6100_adpcm_chan.o \
|
||||
$(APIDIR)/oct6100_channel.o \
|
||||
$(APIDIR)/oct6100_chip_open.o \
|
||||
$(APIDIR)/oct6100_chip_stats.o \
|
||||
$(APIDIR)/oct6100_conf_bridge.o \
|
||||
$(APIDIR)/oct6100_debug.o \
|
||||
$(APIDIR)/oct6100_events.o \
|
||||
$(APIDIR)/oct6100_interrupts.o \
|
||||
$(APIDIR)/oct6100_memory.o \
|
||||
$(APIDIR)/oct6100_miscellaneous.o \
|
||||
$(APIDIR)/oct6100_mixer.o \
|
||||
$(APIDIR)/oct6100_phasing_tsst.o \
|
||||
$(APIDIR)/oct6100_playout_buf.o \
|
||||
$(APIDIR)/oct6100_remote_debug.o \
|
||||
$(APIDIR)/oct6100_tlv.o \
|
||||
$(APIDIR)/oct6100_tone_detection.o \
|
||||
$(APIDIR)/oct6100_tsi_cnct.o \
|
||||
$(APIDIR)/oct6100_tsst.o \
|
||||
$(APIDIR)/oct6100_user.o \
|
||||
apilib/bt/octapi_bt0.o \
|
||||
apilib/largmath/octapi_largmath.o \
|
||||
apilib/llman/octapi_llman.o
|
||||
|
||||
|
||||
all: test
|
||||
|
||||
test.o: test.c
|
||||
|
||||
test: test.o $(OCTASIC_OBJS)
|
||||
|
||||
clean:
|
||||
rm -rf test test.o
|
||||
rm -rf $(OCTASIC_OBJS)
|
||||
|
||||
@@ -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_
|
||||
{
|
||||
|
||||
@@ -397,7 +397,7 @@ $Octasic_Revision: 171 $
|
||||
|
||||
/* Max defines.*/
|
||||
#ifndef cOCT6100_MAX_ECHO_CHANNELS
|
||||
#define cOCT6100_MAX_ECHO_CHANNELS 256
|
||||
#define cOCT6100_MAX_ECHO_CHANNELS 128
|
||||
#endif
|
||||
#define cOCT6100_MAX_TSI_CNCTS 1530
|
||||
#define cOCT6100_MAX_CALLER_ID_PLAYOUT_BUFFERS ( 3328 + 6 )
|
||||
|
||||
@@ -1,210 +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 <dahdi/kernel.h>
|
||||
|
||||
#include "oct612x.h"
|
||||
|
||||
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
|
||||
{
|
||||
/* Why couldn't they just take a timeval like everyone else? */
|
||||
struct timeval tv;
|
||||
unsigned long long total_usecs;
|
||||
unsigned int mask = ~0;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
|
||||
(((unsigned long long)(tv.tv_usec)));
|
||||
f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
|
||||
f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern,
|
||||
UINT32 f_ulLength)
|
||||
{
|
||||
memset(f_pAddress, f_ulPattern, f_ulLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource,
|
||||
UINT32 f_ulLength)
|
||||
{
|
||||
memcpy(f_pDestination, f_pSource, f_ulLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserCreateSerializeObject(
|
||||
tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
|
||||
{
|
||||
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");
|
||||
@@ -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__ */
|
||||
1889
drivers/dahdi/pciradio.c
Normal file
1889
drivers/dahdi/pciradio.c
Normal file
File diff suppressed because it is too large
Load Diff
10531
drivers/dahdi/pciradio.rbt
Normal file
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
186
drivers/dahdi/tor2-hw.h
Normal 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 */
|
||||
|
||||
1545
drivers/dahdi/tor2.c
Normal file
1545
drivers/dahdi/tor2.c
Normal file
File diff suppressed because it is too large
Load Diff
17482
drivers/dahdi/tormenta2.rbt
Normal file
17482
drivers/dahdi/tormenta2.rbt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1560,7 +1560,7 @@ gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap(
|
||||
if (DspStatus != 0)
|
||||
return (RmmFailure);
|
||||
|
||||
for (i = 0; i < MemoryLength_Word16; i++)
|
||||
for (i = 0; i < MemoryLength_Word16; i++)
|
||||
pDest[i] = (short int) MsgBuffer[2 + i];
|
||||
|
||||
|
||||
@@ -1636,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);
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
#include <dahdi/user.h>
|
||||
@@ -127,8 +126,8 @@ static int vpmadt032_getreg_full_return(struct vpmadt032 *vpm, int pagechange,
|
||||
unsigned long ret;
|
||||
BUG_ON(!cmd);
|
||||
|
||||
/* We'll wait for 2s */
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ*2);
|
||||
/* We'll wait for 200ms */
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ/5);
|
||||
if (unlikely(!ret)) {
|
||||
spin_lock_irqsave(&vpm->list_lock, flags);
|
||||
list_del(&cmd->node);
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#ifndef _GPAKCUST_H /* prevent multiple inclusion */
|
||||
#define _GPAKCUST_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
@@ -2,17 +2,4 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += dahdi_voicebus.o
|
||||
|
||||
dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o voicebus_net.o vpmoct.o
|
||||
|
||||
FIRM_DIR := ../firmware
|
||||
|
||||
ifneq ($(HOTPLUG_FIRMWARE),yes)
|
||||
dahdi_voicebus-objs += $(FIRM_DIR)/dahdi-fw-vpmoct032.o
|
||||
$(warning WARNING: You are compiling firmware into voicebus.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
|
||||
else
|
||||
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-vpmoct032.o: $(obj)/voicebus.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-vpmoct032.o
|
||||
|
||||
EXTRA_CFLAGS := -I$(src)/.. -Wno-undef
|
||||
|
||||
6
drivers/dahdi/voicebus/Makefile
Normal file
6
drivers/dahdi/voicebus/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
@@ -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);
|
||||
@@ -1747,17 +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
|
||||
@@ -1800,7 +1800,9 @@ __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)
|
||||
@@ -1883,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");
|
||||
@@ -2028,7 +2030,7 @@ static int __init voicebus_module_init(void)
|
||||
* defined, but it will make sure that this module is a dependency of
|
||||
* dahdi.ko, so that when it is being unloded, this module will be
|
||||
* unloaded as well. */
|
||||
dahdi_register_device(NULL, NULL);
|
||||
dahdi_register(NULL, 0);
|
||||
spin_lock_init(&loader_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,15 +57,6 @@
|
||||
* (and not tasklet). */
|
||||
#define CONFIG_VOICEBUS_INTERRUPT
|
||||
|
||||
/*
|
||||
* Enable the following definition in order to disable Active-State Power
|
||||
* Management on the PCIe bridge for PCIe cards. This has been known to work
|
||||
* around issues where the BIOS enables it on the cards even though the
|
||||
* platform does not support it.
|
||||
*
|
||||
*/
|
||||
#undef CONFIG_VOICEBUS_DISABLE_ASPM
|
||||
|
||||
/* Define this to use a FIFO for the software echocan reference.
|
||||
* (experimental) */
|
||||
#undef CONFIG_VOICEBUS_ECREFERENCE
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -207,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);
|
||||
|
||||
@@ -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"
|
||||
@@ -73,7 +72,7 @@ static int _vpmoct_read(struct vpmoct *vpm, u8 address,
|
||||
list_del(&cmd->node);
|
||||
spin_unlock_irqrestore(&vpm->list_lock, flags);
|
||||
kfree(cmd);
|
||||
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out\n");
|
||||
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out :O(\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -444,47 +443,6 @@ static void vpmoct_set_defaults(struct vpmoct *vpm)
|
||||
vpmoct_write_dword(vpm, 0x30, 0);
|
||||
}
|
||||
|
||||
static const char *const FIRMWARE_NAME = "dahdi-fw-vpmoct032.bin";
|
||||
#if defined(HOTPLUG_FIRMWARE)
|
||||
static int
|
||||
vpmoct_request_firmware(const struct firmware **fw, struct device *dev)
|
||||
{
|
||||
return request_firmware(fw, FIRMWARE_NAME, dev);
|
||||
}
|
||||
|
||||
static void vpmoct_release_firmware(const struct firmware *fw)
|
||||
{
|
||||
release_firmware(fw);
|
||||
}
|
||||
#else
|
||||
static int
|
||||
vpmoct_request_firmware(const struct firmware **fw_p, struct device *dev)
|
||||
{
|
||||
struct firmware *fw;
|
||||
extern void _binary_dahdi_fw_vpmoct032_bin_size;
|
||||
extern u8 _binary_dahdi_fw_vpmoct032_bin_start[];
|
||||
|
||||
*fw_p = fw = kzalloc(sizeof(*fw), GFP_KERNEL);
|
||||
if (!fw)
|
||||
return -ENOMEM;
|
||||
|
||||
fw->data = _binary_dahdi_fw_vpmoct032_bin_start;
|
||||
/* Yes... this is weird. objcopy gives us a symbol containing
|
||||
the size of the firmware, not a pointer a variable containing the
|
||||
size. The only way we can get the value of the symbol is to take
|
||||
its address, so we define it as a pointer and then cast that value
|
||||
to the proper type. */
|
||||
fw->size = (size_t) &_binary_dahdi_fw_vpmoct032_bin_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vpmoct_release_firmware(const struct firmware *fw)
|
||||
{
|
||||
kfree(fw);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vpmoct_load_flash - Check the current flash version and possibly load.
|
||||
* @vpm: The VPMOCT032 module to check / load.
|
||||
@@ -505,9 +463,10 @@ static void vpmoct_load_flash(struct work_struct *data)
|
||||
const struct firmware *fw;
|
||||
const struct vpmoct_header *header;
|
||||
char serial[VPMOCT_SERIAL_SIZE+1];
|
||||
const char *const FIRMWARE_NAME = "dahdi-fw-vpmoct032.bin";
|
||||
int i;
|
||||
|
||||
res = vpmoct_request_firmware(&fw, vpm->dev);
|
||||
res = request_firmware(&fw, FIRMWARE_NAME, vpm->dev);
|
||||
if (res) {
|
||||
dev_warn(vpm->dev,
|
||||
"vpmoct: Failed to load firmware from userspace! %d\n",
|
||||
@@ -546,7 +505,7 @@ static void vpmoct_load_flash(struct work_struct *data)
|
||||
FIRMWARE_NAME);
|
||||
|
||||
/* Just use the old version of the fimware. */
|
||||
vpmoct_release_firmware(fw);
|
||||
release_firmware(fw);
|
||||
vpmoct_set_defaults(vpm);
|
||||
vpmoct_load_complete(work, true);
|
||||
return;
|
||||
@@ -555,7 +514,7 @@ static void vpmoct_load_flash(struct work_struct *data)
|
||||
if (vpm->minor == header->minor &&
|
||||
vpm->major == header->major) {
|
||||
/* Proper version is running */
|
||||
vpmoct_release_firmware(fw);
|
||||
release_firmware(fw);
|
||||
vpmoct_set_defaults(vpm);
|
||||
vpmoct_load_complete(work, true);
|
||||
return;
|
||||
@@ -589,14 +548,14 @@ static void vpmoct_load_flash(struct work_struct *data)
|
||||
if (vpmoct_check_firmware_crc(vpm, fw->size-VPMOCT_FIRM_HEADER_LEN*2,
|
||||
header->major, header->minor))
|
||||
goto error;
|
||||
vpmoct_release_firmware(fw);
|
||||
release_firmware(fw);
|
||||
vpmoct_set_defaults(vpm);
|
||||
vpmoct_load_complete(work, true);
|
||||
return;
|
||||
|
||||
error:
|
||||
dev_info(vpm->dev, "Unable to load firmware\n");
|
||||
vpmoct_release_firmware(fw);
|
||||
release_firmware(fw);
|
||||
/* TODO: Should we disable module if the firmware doesn't load? */
|
||||
vpmoct_load_complete(work, false);
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* DAHDI Telephony Interface to VPMADT032 Firmware Loader
|
||||
*
|
||||
* Copyright (C) 2008-2012 Digium, Inc. All rights reserved.
|
||||
* Copyright (C) 2008-2011 Digium, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -39,9 +38,18 @@ logger(const char *format, ...)
|
||||
int res;
|
||||
va_list args;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
|
||||
va_start(args, format);
|
||||
res = vprintk(format, args);
|
||||
va_end(args);
|
||||
#else
|
||||
char buf[256];
|
||||
|
||||
va_start(args, format);
|
||||
res = vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
printk(KERN_INFO "%s" buf);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
7
drivers/dahdi/wcb4xxp/Makefile
Normal file
7
drivers/dahdi/wcb4xxp/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
else
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -248,8 +248,8 @@
|
||||
#define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */
|
||||
#define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */
|
||||
#define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */
|
||||
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data 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
|
||||
|
||||
@@ -386,7 +376,6 @@
|
||||
#define HFC_T1 0
|
||||
#define HFC_T2 1
|
||||
#define HFC_T3 2
|
||||
#define HFC_T4 3
|
||||
|
||||
#define MAX_SPANS_PER_CARD 8
|
||||
|
||||
@@ -395,8 +384,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];
|
||||
@@ -408,8 +396,8 @@ struct b4xxp_span {
|
||||
unsigned long alarmtimer;
|
||||
|
||||
int te_mode; /* 1=TE, 0=NT */
|
||||
unsigned long hfc_timers[4]; /* T1, T2, T3, Fake T4 */
|
||||
int hfc_timer_on[4]; /* 1=timer active */
|
||||
unsigned long hfc_timers[WCB4XXP_CHANNELS_PER_SPAN]; /* T1, T2, T3 */
|
||||
int hfc_timer_on[WCB4XXP_CHANNELS_PER_SPAN]; /* 1=timer active */
|
||||
int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */
|
||||
|
||||
/* HDLC controller fields */
|
||||
@@ -437,9 +425,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 */
|
||||
@@ -488,7 +474,6 @@ struct b4xxp {
|
||||
/* Flags for our bottom half */
|
||||
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
|
||||
struct tasklet_struct b4xxp_tlet;
|
||||
struct dahdi_device *ddev;
|
||||
};
|
||||
|
||||
/* CPLD access bits */
|
||||
|
||||
1082
drivers/dahdi/wcfxo.c
Normal file
1082
drivers/dahdi/wcfxo.c
Normal file
File diff suppressed because it is too large
Load Diff
1440
drivers/dahdi/wct1xxp.c
Normal file
1440
drivers/dahdi/wct1xxp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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,11 +14,10 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
wct4xxp-objs := base.o vpm450m.o
|
||||
wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x)
|
||||
|
||||
ifneq ($(HOTPLUG_FIRMWARE),yes)
|
||||
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o
|
||||
$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
|
||||
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o
|
||||
endif
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
|
||||
@@ -26,6 +25,3 @@ $(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o
|
||||
|
||||
8
drivers/dahdi/wct4xxp/Makefile
Normal file
8
drivers/dahdi/wct4xxp/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
|
||||
else
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Digium, Inc.
|
||||
* Copyright (C) 2005-2006 Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
@@ -19,74 +19,110 @@
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
#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)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
|
||||
/* API for Octasic access */
|
||||
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
|
||||
{
|
||||
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,17 +172,15 @@ 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];
|
||||
UINT32 aulEchoChanHndl[128];
|
||||
int chanflags[128];
|
||||
int ecmode[128];
|
||||
int numchans;
|
||||
};
|
||||
|
||||
#define FLAG_DTMF (1 << 0)
|
||||
#define FLAG_MUTE (1 << 1)
|
||||
#define FLAG_ECHO (1 << 2)
|
||||
#define FLAG_ALAW (1 << 3)
|
||||
|
||||
static unsigned int tones[] = {
|
||||
SOUT_DTMF_1,
|
||||
@@ -186,52 +220,6 @@ static unsigned int tones[] = {
|
||||
ROUT_G168_1100GB_ON,
|
||||
};
|
||||
|
||||
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
|
||||
bool alaw)
|
||||
{
|
||||
tOCT6100_CHANNEL_MODIFY *modify;
|
||||
UINT32 ulResult;
|
||||
UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW :
|
||||
cOCT6100_PCM_U_LAW;
|
||||
|
||||
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
|
||||
pr_err("Channel out of bounds in %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
/* If we're already in this companding mode, no need to do anything. */
|
||||
if (alaw == ((vpm450m->chanflags[channel] & FLAG_ALAW) > 0))
|
||||
return;
|
||||
|
||||
modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
|
||||
if (!modify) {
|
||||
pr_notice("Unable to allocate memory for setec!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Oct6100ChannelModifyDef(modify);
|
||||
modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel];
|
||||
modify->fTdmConfigModified = TRUE;
|
||||
modify->TdmConfig.ulSinPcmLaw = law_to_use;
|
||||
modify->TdmConfig.ulRinPcmLaw = law_to_use;
|
||||
modify->TdmConfig.ulSoutPcmLaw = law_to_use;
|
||||
modify->TdmConfig.ulRoutPcmLaw = law_to_use;
|
||||
ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify);
|
||||
if (ulResult != GENERIC_OK) {
|
||||
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");
|
||||
}
|
||||
if (alaw)
|
||||
vpm450m->chanflags[channel] |= FLAG_ALAW;
|
||||
else
|
||||
vpm450m->chanflags[channel] &= ~(FLAG_ALAW);
|
||||
}
|
||||
kfree(modify);
|
||||
}
|
||||
|
||||
static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode)
|
||||
{
|
||||
tOCT6100_CHANNEL_MODIFY *modify;
|
||||
@@ -239,7 +227,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;
|
||||
@@ -264,12 +252,7 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
|
||||
tOCT6100_CHANNEL_MODIFY *modify;
|
||||
UINT32 ulResult;
|
||||
|
||||
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
|
||||
pr_err("Channel out of bounds in %s\n", __func__);
|
||||
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;
|
||||
@@ -307,11 +290,6 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
|
||||
|
||||
void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen)
|
||||
{
|
||||
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
|
||||
pr_err("Channel out of bounds in %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eclen) {
|
||||
vpm450m->chanflags[channel] |= FLAG_ECHO;
|
||||
vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
|
||||
@@ -417,18 +395,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,39 +416,35 @@ 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;
|
||||
tOCT6100_CHANNEL_OPEN *ChannelOpen;
|
||||
UINT32 ulResult;
|
||||
const unsigned int mask = (8 == numspans) ? 0x7 : 0x3;
|
||||
unsigned int sout_stream, rout_stream;
|
||||
struct vpm450m *vpm450m;
|
||||
int x,y,law;
|
||||
|
||||
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 +457,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;
|
||||
@@ -497,22 +467,15 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
|
||||
ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB;
|
||||
ChipOpen->ulNumMemoryChips = 1;
|
||||
ChipOpen->ulMaxTdmStreams = 4;
|
||||
ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ;
|
||||
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
|
||||
ChipOpen->ulMaxFlexibleConfParticipants = 0;
|
||||
ChipOpen->ulMaxConfBridges = 0;
|
||||
ChipOpen->ulMaxRemoteDebugSessions = 0;
|
||||
ChipOpen->fEnableChannelRecording = FALSE;
|
||||
ChipOpen->ulSoftToneEventsBufSize = 64;
|
||||
|
||||
if (vpm450m->numchans <= 128) {
|
||||
ChipOpen->ulMaxTdmStreams = 4;
|
||||
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
|
||||
} else {
|
||||
ChipOpen->ulMaxTdmStreams = 32;
|
||||
ChipOpen->fEnableFastH100Mode = TRUE;
|
||||
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_RISING_EDGE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ChipOpen->fEnableAcousticEcho = TRUE;
|
||||
#endif
|
||||
@@ -544,11 +507,7 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
kfree(ChannelOpen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sout_stream = (8 == numspans) ? 29 : 2;
|
||||
rout_stream = (8 == numspans) ? 24 : 3;
|
||||
|
||||
for (x = 0; x < ((8 == numspans) ? 256 : 128); x++) {
|
||||
for (x = 0; x < ARRAY_SIZE(vpm450m->aulEchoChanHndl); x++) {
|
||||
/* execute this loop always on 4 span cards but
|
||||
* on 2 span cards only execute for the channels related to our spans */
|
||||
if (( numspans > 2) || ((x & 0x03) <2)) {
|
||||
@@ -556,13 +515,10 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
* therefore, the lower 2 bits tell us which span this
|
||||
* timeslot/channel
|
||||
*/
|
||||
if (isalaw[x & mask]) {
|
||||
if (isalaw[x & 0x03])
|
||||
law = cOCT6100_PCM_A_LAW;
|
||||
vpm450m->chanflags[x] |= FLAG_ALAW;
|
||||
} else {
|
||||
else
|
||||
law = cOCT6100_PCM_U_LAW;
|
||||
vpm450m->chanflags[x] &= ~(FLAG_ALAW);
|
||||
}
|
||||
Oct6100ChannelOpenDef(ChannelOpen);
|
||||
ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x];
|
||||
ChannelOpen->ulUserChanId = x;
|
||||
@@ -573,13 +529,11 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
ChannelOpen->TdmConfig.ulSinStream = 1;
|
||||
ChannelOpen->TdmConfig.ulSinTimeslot = x;
|
||||
ChannelOpen->TdmConfig.ulSoutPcmLaw = law;
|
||||
ChannelOpen->TdmConfig.ulSoutStream = sout_stream;
|
||||
ChannelOpen->TdmConfig.ulSoutStream = 2;
|
||||
ChannelOpen->TdmConfig.ulSoutTimeslot = x;
|
||||
#if 1
|
||||
ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
|
||||
ChannelOpen->TdmConfig.ulRoutStream = rout_stream;
|
||||
ChannelOpen->TdmConfig.ulRoutStream = 3;
|
||||
ChannelOpen->TdmConfig.ulRoutTimeslot = x;
|
||||
#endif
|
||||
ChannelOpen->VqeConfig.fEnableNlp = TRUE;
|
||||
ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
|
||||
ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
|
||||
@@ -589,7 +543,7 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
|
||||
ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen);
|
||||
if (ulResult != GENERIC_OK) {
|
||||
printk(KERN_NOTICE "Failed to open channel %d %x!\n", x, ulResult);
|
||||
printk(KERN_NOTICE "Failed to open channel %d!\n", x);
|
||||
continue;
|
||||
}
|
||||
for (y = 0; y < ARRAY_SIZE(tones); y++) {
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
struct t4;
|
||||
struct vpm450m;
|
||||
|
||||
/* From driver */
|
||||
@@ -33,17 +32,12 @@ 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);
|
||||
int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start);
|
||||
void release_vpm450m(struct vpm450m *instance);
|
||||
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
|
||||
int channel, bool alaw);
|
||||
|
||||
extern int debug;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -54,12 +54,6 @@
|
||||
#define FRMR_SIC3 0x40
|
||||
#define FRMR_CMR1 0x44
|
||||
#define FRMR_CMR2 0x45
|
||||
/* OctalFALC Only */
|
||||
#define FRMR_CMR4 0x41
|
||||
#define FRMR_CMR5 0x42
|
||||
#define FRMR_CMR6 0x43
|
||||
#define FRMR_GPC2 0x8a
|
||||
/* End Octal */
|
||||
#define FRMR_GCR 0x46
|
||||
#define FRMR_ISR0 0x68
|
||||
#define FRMR_ISR0_RME 0x80
|
||||
@@ -82,13 +76,6 @@
|
||||
#define FRMR_CIS_GIS2 0x02
|
||||
#define FRMR_CIS_GIS3 0x04
|
||||
#define FRMR_CIS_GIS4 0x08
|
||||
|
||||
/* CIS - Octal falc bits */
|
||||
#define FRMR_CIS_GIS5 0x10
|
||||
#define FRMR_CIS_GIS6 0x20
|
||||
#define FRMR_CIS_GIS7 0x40
|
||||
#define FRMR_CIS_GIS8 0x80
|
||||
|
||||
#define FRMR_CMDR 0x02
|
||||
#define FRMR_CMDR_SRES 0x01
|
||||
#define FRMR_CMDR_XRES 0x10
|
||||
@@ -126,12 +113,12 @@ struct t4_regs {
|
||||
unsigned char regs[NUM_REGS];
|
||||
};
|
||||
|
||||
struct t4_reg {
|
||||
unsigned int reg;
|
||||
unsigned int val;
|
||||
};
|
||||
#define T4_CHECK_VPM 0
|
||||
#define T4_LOADING_FW 1
|
||||
#define T4_STOP_DMA 2
|
||||
#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)
|
||||
#define WCT4_GET_REGS _IOW (DAHDI_CODE, 60, struct t4_regs)
|
||||
|
||||
|
||||
7
drivers/dahdi/wctc4xxp/Makefile
Normal file
7
drivers/dahdi/wctc4xxp/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
else
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
2858
drivers/dahdi/wctdm.c
Normal file
2858
drivers/dahdi/wctdm.c
Normal file
File diff suppressed because it is too large
Load Diff
6
drivers/dahdi/wctdm24xxp/Makefile
Normal file
6
drivers/dahdi/wctdm24xxp/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@
|
||||
* \brief Default ringer debounce (in ms)
|
||||
*/
|
||||
#define DEFAULT_RING_DEBOUNCE 1024
|
||||
|
||||
#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */
|
||||
|
||||
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
|
||||
@@ -84,6 +85,7 @@
|
||||
|
||||
#define NUM_CAL_REGS 12
|
||||
|
||||
#define ISR_COMMANDS 2
|
||||
#define QRV_DEBOUNCETIME 20
|
||||
|
||||
#define VPM150M_HPI_CONTROL 0x00
|
||||
@@ -105,32 +107,10 @@ struct calregs {
|
||||
|
||||
enum battery_state {
|
||||
BATTERY_UNKNOWN = 0,
|
||||
BATTERY_DEBOUNCING_PRESENT,
|
||||
BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM,
|
||||
BATTERY_DEBOUNCING_PRESENT_ALARM,
|
||||
BATTERY_PRESENT,
|
||||
BATTERY_DEBOUNCING_LOST,
|
||||
BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM,
|
||||
BATTERY_DEBOUNCING_LOST_ALARM,
|
||||
BATTERY_LOST,
|
||||
};
|
||||
|
||||
enum ring_detector_state {
|
||||
RINGOFF = 0,
|
||||
DEBOUNCING_RINGING_POSITIVE,
|
||||
DEBOUNCING_RINGING_NEGATIVE,
|
||||
RINGING,
|
||||
DEBOUNCING_RINGOFF,
|
||||
};
|
||||
|
||||
enum polarity_state {
|
||||
UNKNOWN_POLARITY = 0,
|
||||
POLARITY_DEBOUNCE_POSITIVE,
|
||||
POLARITY_POSITIVE,
|
||||
POLARITY_DEBOUNCE_NEGATIVE,
|
||||
POLARITY_NEGATIVE,
|
||||
};
|
||||
|
||||
struct wctdm_cmd {
|
||||
struct list_head node;
|
||||
struct completion *complete;
|
||||
@@ -166,26 +146,29 @@ struct wctdm_chan {
|
||||
};
|
||||
|
||||
struct fxo {
|
||||
enum ring_detector_state ring_state:4;
|
||||
enum battery_state battery_state:4;
|
||||
enum polarity_state polarity_state:4;
|
||||
u8 ring_polarity_change_count:4;
|
||||
u8 hook_ring_shadow;
|
||||
s8 line_voltage_status;
|
||||
int wasringing;
|
||||
int lastrdtx;
|
||||
int lastrdtx_count;
|
||||
int ringdebounce;
|
||||
int offhook;
|
||||
int battdebounce;
|
||||
int battalarm;
|
||||
enum battery_state battery;
|
||||
int lastpol;
|
||||
int polarity;
|
||||
int polaritydebounce;
|
||||
int neonmwi_state;
|
||||
int neonmwi_last_voltage;
|
||||
unsigned int neonmwi_debounce;
|
||||
unsigned int neonmwi_offcounter;
|
||||
unsigned long display_fxovoltage;
|
||||
unsigned long ringdebounce_timer;
|
||||
unsigned long battdebounce_timer;
|
||||
unsigned long poldebounce_timer;
|
||||
};
|
||||
|
||||
struct fxs {
|
||||
u8 oht_active:1;
|
||||
u8 off_hook:1;
|
||||
int oldrxhook;
|
||||
int debouncehook;
|
||||
int lastrxhook;
|
||||
int debounce;
|
||||
int ohttimer;
|
||||
int idletxhookstate; /* IDLE changing hook state */
|
||||
/* lasttxhook reflects the last value written to the proslic's reg
|
||||
* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last
|
||||
@@ -197,18 +180,13 @@ struct fxs {
|
||||
* voicebus ISR.
|
||||
*/
|
||||
int lasttxhook;
|
||||
u8 linefeed_control_shadow;
|
||||
u8 hook_state_shadow;
|
||||
int oppending_ms;
|
||||
int palarms;
|
||||
struct dahdi_vmwi_info vmwisetting;
|
||||
int vmwi_active_messages;
|
||||
int vmwi_linereverse;
|
||||
int reversepolarity; /* polarity reversal */
|
||||
struct calregs calregs;
|
||||
unsigned long check_alarm;
|
||||
unsigned long check_proslic;
|
||||
unsigned long oppending_timeout;
|
||||
unsigned long ohttimer;
|
||||
};
|
||||
|
||||
struct qrv {
|
||||
@@ -225,7 +203,6 @@ struct qrv {
|
||||
int radmode;
|
||||
signed short rxgain;
|
||||
signed short txgain;
|
||||
u8 isrshadow[3];
|
||||
};
|
||||
|
||||
enum module_type {
|
||||
@@ -238,7 +215,7 @@ enum module_type {
|
||||
};
|
||||
|
||||
struct wctdm_module {
|
||||
union modtypes {
|
||||
union {
|
||||
struct fxo fxo;
|
||||
struct fxs fxs;
|
||||
struct qrv qrv;
|
||||
@@ -250,6 +227,7 @@ struct wctdm_module {
|
||||
struct list_head active_cmds;
|
||||
u8 offsets[3];
|
||||
u8 subaddr;
|
||||
u8 isrshadow[ISR_COMMANDS];
|
||||
u8 card;
|
||||
|
||||
enum module_type type;
|
||||
@@ -264,7 +242,7 @@ struct wctdm {
|
||||
spinlock_t frame_list_lock;
|
||||
struct list_head frame_list;
|
||||
|
||||
unsigned long framecount;
|
||||
unsigned int intcount;
|
||||
unsigned char txident;
|
||||
unsigned char rxident;
|
||||
|
||||
@@ -299,7 +277,6 @@ struct wctdm {
|
||||
int not_ready; /* 0 when the entire card is ready to go */
|
||||
unsigned long checkflag; /* Internal state flags and task bits */
|
||||
int companding;
|
||||
struct dahdi_device *ddev;
|
||||
};
|
||||
|
||||
static inline bool is_initialized(struct wctdm *wc)
|
||||
|
||||
@@ -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>
|
||||
@@ -2151,9 +2150,7 @@ static int b400m_set_ntte(struct b400m_span *bspan, int te_mode, int term_on)
|
||||
int all_modes = 0, all_terms = 0;
|
||||
int i;
|
||||
|
||||
bspan->wspan->span.spantype = (te_mode > 0)
|
||||
? SPANTYPE_DIGITAL_BRI_TE
|
||||
: SPANTYPE_DIGITAL_BRI_NT;
|
||||
bspan->wspan->span.spantype = (te_mode > 0) ? "TE" : "NT";
|
||||
|
||||
bspan->te_mode = te_mode;
|
||||
bspan->term_on = term_on;
|
||||
|
||||
1632
drivers/dahdi/wcte11xp.c
Normal file
1632
drivers/dahdi/wcte11xp.c
Normal file
File diff suppressed because it is too large
Load Diff
5
drivers/dahdi/wcte12xp/Kbuild
Normal file
5
drivers/dahdi/wcte12xp/Kbuild
Normal file
@@ -0,0 +1,5 @@
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp.o
|
||||
|
||||
EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
|
||||
|
||||
wcte12xp-objs := base.o
|
||||
6
drivers/dahdi/wcte12xp/Makefile
Normal file
6
drivers/dahdi/wcte12xp/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
2813
drivers/dahdi/wcte12xp/base.c
Normal file
2813
drivers/dahdi/wcte12xp/base.c
Normal file
File diff suppressed because it is too large
Load Diff
163
drivers/dahdi/wcte12xp/wcte12xp.h
Normal file
163
drivers/dahdi/wcte12xp/wcte12xp.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define TYPE_T1 1
|
||||
#define TYPE_E1 2
|
||||
|
||||
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 */
|
||||
int spantype;
|
||||
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
|
||||
unsigned long bit_flags;
|
||||
unsigned long alarmtimer;
|
||||
unsigned char ledstate;
|
||||
unsigned char vpm_check_count;
|
||||
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
1057
drivers/dahdi/wcxb.c
1057
drivers/dahdi/wcxb.c
File diff suppressed because it is too large
Load Diff
@@ -1,204 +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
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
/* The is_pcie member was backported but I'm not sure in which version. */
|
||||
# ifndef RHEL_RELEASE_VERSION
|
||||
#define WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
|
||||
# endif
|
||||
#else
|
||||
#endif
|
||||
|
||||
struct wcxb;
|
||||
|
||||
struct wcxb_operations {
|
||||
void (*handle_receive)(struct wcxb *xb, void *frame);
|
||||
void (*handle_transmit)(struct wcxb *xb, void *frame);
|
||||
void (*handle_error)(struct wcxb *xb);
|
||||
void (*handle_interrupt)(struct wcxb *xb, u32 pending);
|
||||
};
|
||||
|
||||
struct wcxb_meta_desc;
|
||||
struct wcxb_hw_desc;
|
||||
|
||||
/**
|
||||
* struct wcxb - 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;
|
||||
#ifdef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
|
||||
u32 is_pcie:1;
|
||||
#endif
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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_*
|
||||
@@ -58,7 +69,7 @@ FXO_MODES = $(src)/../fxo_modes.h
|
||||
FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
|
||||
|
||||
hostprogs-y := print_fxo_modes
|
||||
always := $(xpp_verified)
|
||||
always := $(xpp_verified) xpp_version.h
|
||||
print_fxo_modes-objs := print_fxo_modes.o
|
||||
HOSTCFLAGS_print_fxo_modes.o += -include $(FXO_MODES)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum bri_opcodes {
|
||||
XPROTO_NAME(BRI, SET_LED) = 0x33,
|
||||
XPROTO_NAME(BRI, SET_LED) = 0x33,
|
||||
};
|
||||
|
||||
#endif /* CARD_BRI_H */
|
||||
#endif /* CARD_BRI_H */
|
||||
|
||||
@@ -42,33 +42,36 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||
static bool echo_packet_is_valid(xpacket_t *pack);
|
||||
static void echo_packet_dump(const char *msg, xpacket_t *pack);
|
||||
|
||||
DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];);
|
||||
DEF_RPACKET_DATA(ECHO, SET,
|
||||
byte timeslots[ECHO_TIMESLOTS];
|
||||
);
|
||||
|
||||
DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;);
|
||||
DEF_RPACKET_DATA(ECHO, SET_REPLY,
|
||||
byte status;
|
||||
byte reserved;
|
||||
);
|
||||
|
||||
struct ECHO_priv_data {
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(ECHO);
|
||||
static xproto_table_t PROTO_TABLE(ECHO);
|
||||
|
||||
/*---------------- ECHO: Methods -------------------------------------------*/
|
||||
|
||||
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
const xproto_table_t *proto_table, byte subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels = 0;
|
||||
|
||||
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 = 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 +84,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,23 +116,25 @@ 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;
|
||||
|
||||
if ((rate_limit++ % 1003) < 5)
|
||||
notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
|
||||
notify_bad_xpd(__func__, xbus, addr,
|
||||
orig_xpd->xpdname);
|
||||
return -EPROTO;
|
||||
}
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
/* Update /proc info only if reply related to last reg read request */
|
||||
if (REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
REG_FIELD(info, regnum)
|
||||
&& REG_FIELD(&xpd->requested_reply, do_subreg) ==
|
||||
REG_FIELD(info, do_subreg)
|
||||
&& REG_FIELD(&xpd->requested_reply, subreg) ==
|
||||
REG_FIELD(info, subreg)) {
|
||||
if (
|
||||
REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
REG_FIELD(info, regnum) &&
|
||||
REG_FIELD(&xpd->requested_reply, do_subreg) ==
|
||||
REG_FIELD(info, do_subreg) &&
|
||||
REG_FIELD(&xpd->requested_reply, subreg) ==
|
||||
REG_FIELD(info, subreg)) {
|
||||
xpd->last_reply = *info;
|
||||
}
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
@@ -141,7 +146,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
static /* 0x39 */ HOSTCMD(ECHO, SET)
|
||||
{
|
||||
struct xbus_echo_state *es;
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
int ret;
|
||||
@@ -167,7 +172,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
|
||||
{
|
||||
int ts_number;
|
||||
int ts_mask;
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
|
||||
ts = xpd->xbus->echo_state.timeslots;
|
||||
/*
|
||||
@@ -193,7 +198,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
|
||||
ts[ts_number] &= ~ts_mask;
|
||||
}
|
||||
LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
|
||||
__func__, on, ts_number, ts_mask);
|
||||
__func__, on, ts_number, ts_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -202,7 +207,7 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
|
||||
int ts_number;
|
||||
int ts_mask;
|
||||
int is_on;
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
|
||||
ts = xpd->xbus->echo_state.timeslots;
|
||||
ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2; /* Which bit? */
|
||||
@@ -215,14 +220,14 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
|
||||
}
|
||||
#if 0
|
||||
LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
|
||||
is_on, ts_number, ts_mask);
|
||||
is_on, ts_number, ts_mask);
|
||||
#endif
|
||||
return is_on;
|
||||
}
|
||||
|
||||
static void ECHO_ec_dump(xbus_t *xbus)
|
||||
{
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
int i;
|
||||
|
||||
ts = xbus->echo_state.timeslots;
|
||||
@@ -231,11 +236,12 @@ static void ECHO_ec_dump(xbus_t *xbus)
|
||||
"EC-DUMP[%03d]: "
|
||||
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
|
||||
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
|
||||
i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3],
|
||||
ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8],
|
||||
ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12],
|
||||
ts[i + 13], ts[i + 14], ts[i + 15]
|
||||
);
|
||||
i,
|
||||
ts[i+0], ts[i+1], ts[i+2], ts[i+3], ts[i+4], ts[i+5],
|
||||
ts[i+6], ts[i+7],
|
||||
ts[i+8], ts[i+9], ts[i+10], ts[i+11], ts[i+12],
|
||||
ts[i+13], ts[i+14], ts[i+15]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +255,7 @@ static int ECHO_ec_update(xbus_t *xbus)
|
||||
/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
|
||||
HANDLER_DEF(ECHO, SET_REPLY)
|
||||
{
|
||||
__u8 status;
|
||||
byte status;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
|
||||
@@ -257,26 +263,26 @@ HANDLER_DEF(ECHO, SET_REPLY)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xops echo_xops = {
|
||||
.card_new = ECHO_card_new,
|
||||
.card_init = ECHO_card_init,
|
||||
.card_remove = ECHO_card_remove,
|
||||
.card_tick = ECHO_card_tick,
|
||||
.card_register_reply = ECHO_card_register_reply,
|
||||
static const struct xops echo_xops = {
|
||||
.card_new = ECHO_card_new,
|
||||
.card_init = ECHO_card_init,
|
||||
.card_remove = ECHO_card_remove,
|
||||
.card_tick = ECHO_card_tick,
|
||||
.card_register_reply = ECHO_card_register_reply,
|
||||
};
|
||||
|
||||
static const struct echoops echoops = {
|
||||
.ec_set = ECHO_ec_set,
|
||||
.ec_get = ECHO_ec_get,
|
||||
.ec_update = ECHO_ec_update,
|
||||
.ec_dump = ECHO_ec_dump,
|
||||
static const struct echoops echoops = {
|
||||
.ec_set = ECHO_ec_set,
|
||||
.ec_get = ECHO_ec_get,
|
||||
.ec_update = ECHO_ec_update,
|
||||
.ec_dump = ECHO_ec_dump,
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(ECHO) = {
|
||||
.owner = THIS_MODULE,
|
||||
.entries = {
|
||||
/* Table Card Opcode */
|
||||
XENTRY( ECHO, ECHO, SET_REPLY ),
|
||||
/* Table Card Opcode */
|
||||
XENTRY(ECHO, ECHO, SET_REPLY),
|
||||
},
|
||||
.name = "ECHO",
|
||||
.ports_per_subunit = 1,
|
||||
@@ -289,7 +295,7 @@ static xproto_table_t PROTO_TABLE(ECHO) = {
|
||||
|
||||
static bool echo_packet_is_valid(xpacket_t *pack)
|
||||
{
|
||||
const xproto_entry_t *xe = NULL;
|
||||
const xproto_entry_t *xe = NULL;
|
||||
// DBG(GENERAL, "\n");
|
||||
xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
|
||||
return xe != NULL;
|
||||
@@ -303,14 +309,14 @@ static void echo_packet_dump(const char *msg, xpacket_t *pack)
|
||||
/*------------------------- sysfs stuff --------------------------------*/
|
||||
static int echo_xpd_probe(struct device *dev)
|
||||
{
|
||||
xpd_t *ec_xpd;
|
||||
int ret = 0;
|
||||
xpd_t *ec_xpd;
|
||||
int ret = 0;
|
||||
|
||||
ec_xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (ec_xpd->xpd_type != XPD_TYPE_ECHO) {
|
||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
ec_xpd->xpd_type);
|
||||
if (ec_xpd->type != XPD_TYPE_ECHO) {
|
||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n",
|
||||
dev_name(dev), ec_xpd->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||
@@ -319,20 +325,23 @@ static int echo_xpd_probe(struct device *dev)
|
||||
|
||||
static int echo_xpd_remove(struct device *dev)
|
||||
{
|
||||
xpd_t *ec_xpd;
|
||||
xpd_t *ec_xpd;
|
||||
|
||||
ec_xpd = dev_to_xpd(dev);
|
||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xpd_driver echo_driver = {
|
||||
.xpd_type = XPD_TYPE_ECHO,
|
||||
.driver = {
|
||||
.name = "echo",
|
||||
.owner = THIS_MODULE,
|
||||
.probe = echo_xpd_probe,
|
||||
.remove = echo_xpd_remove}
|
||||
static struct xpd_driver echo_driver = {
|
||||
.type = XPD_TYPE_ECHO,
|
||||
.driver = {
|
||||
.name = "echo",
|
||||
#ifndef OLD_HOTPLUG_SUPPORT
|
||||
.owner = THIS_MODULE,
|
||||
#endif
|
||||
.probe = echo_xpd_probe,
|
||||
.remove = echo_xpd_remove
|
||||
}
|
||||
};
|
||||
|
||||
static int __init card_echo_startup(void)
|
||||
@@ -342,6 +351,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 +367,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);
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum echo_opcodes {
|
||||
XPROTO_NAME(ECHO, SET) = 0x39,
|
||||
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
|
||||
XPROTO_NAME(ECHO, SET) = 0x39,
|
||||
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
|
||||
};
|
||||
|
||||
#endif /* CARD_ECHO_H */
|
||||
#endif /* CARD_ECHO_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,16 +25,18 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum fxo_opcodes {
|
||||
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, /**/
|
||||
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
|
||||
/**/
|
||||
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, XPD_STATE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
||||
};
|
||||
|
||||
|
||||
DEF_RPACKET_DATA(FXO, SIG_CHANGED,
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
|
||||
#endif /* CARD_FXO_H */
|
||||
#endif /* CARD_FXO_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,15 +25,18 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum fxs_opcodes {
|
||||
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
||||
/**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
||||
/**/
|
||||
XPROTO_NAME(FXS, XPD_STATE) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
||||
};
|
||||
|
||||
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
|
||||
#endif /* CARD_FXS_H */
|
||||
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
|
||||
#endif /* CARD_FXS_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user