Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1d867b8b7 | ||
|
|
1ff5629078 |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,14 +1,10 @@
|
||||
# Files that are generated as part of the build process which we do not want git
|
||||
# to track.
|
||||
|
||||
/.pc
|
||||
|
||||
.cache.mk
|
||||
*.[oa]
|
||||
*.mod
|
||||
*.mod.[oc]
|
||||
*.ko
|
||||
*.ko.unsigned
|
||||
*.cmd
|
||||
*.order
|
||||
*.tar.gz
|
||||
@@ -17,7 +13,6 @@ cscope.*
|
||||
*.symvers
|
||||
*.markers
|
||||
.*.o.d
|
||||
*.ur-safe
|
||||
|
||||
README.html
|
||||
modules.order
|
||||
@@ -43,12 +38,4 @@ drivers/dahdi/firmware/dahdi-fw-oct6114-256.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-tc400m.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-te820.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-vpmoct032.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-a4a.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-a4b.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-a8a.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-a8b.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-oct6114-032.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-te133.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-te134.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-te435.bin
|
||||
drivers/dahdi/firmware/make_firmware_object
|
||||
|
||||
36
Makefile
36
Makefile
@@ -47,13 +47,15 @@ ifeq (yes,$(HAS_KSRC))
|
||||
HOTPLUG_FIRMWARE:=$(shell if grep -q '^CONFIG_FW_LOADER=[ym]' $(KCONFIG); then echo "yes"; else echo "no"; fi)
|
||||
endif
|
||||
|
||||
UDEV_DIR:=/etc/udev/rules.d
|
||||
|
||||
MODULE_ALIASES:=wcfxs wctdm8xxp wct2xxp
|
||||
|
||||
INST_HEADERS:=kernel.h user.h fasthdlc.h wctdm_user.h dahdi_config.h
|
||||
|
||||
DAHDI_BUILD_ALL:=m
|
||||
|
||||
KMAKE=+$(MAKE) -C $(KSRC) M=$(PWD)/drivers/dahdi DAHDI_INCLUDE=$(PWD)/include DAHDI_MODULES_EXTRA="$(DAHDI_MODULES_EXTRA)" HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE)
|
||||
KMAKE=+$(MAKE) -C $(KSRC) SUBDIRS=$(PWD)/drivers/dahdi DAHDI_INCLUDE=$(PWD)/include DAHDI_MODULES_EXTRA="$(DAHDI_MODULES_EXTRA)" HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE)
|
||||
|
||||
ROOT_PREFIX:=
|
||||
|
||||
@@ -80,12 +82,12 @@ include/dahdi/version.h: FORCE
|
||||
fi
|
||||
@rm -f $@.tmp
|
||||
|
||||
prereq: include/dahdi/version.h firmware-loaders
|
||||
prereq: include/dahdi/version.h firmware-loaders oct612x-lib
|
||||
|
||||
stackcheck: $(CHECKSTACK) modules
|
||||
objdump -d drivers/dahdi/*.ko drivers/dahdi/*/*.ko | $(CHECKSTACK)
|
||||
|
||||
install: all install-modules install-include install-firmware install-xpp-firm
|
||||
install: all install-modules install-devices install-include install-firmware install-xpp-firm
|
||||
@echo "###################################################"
|
||||
@echo "###"
|
||||
@echo "### DAHDI installed successfully."
|
||||
@@ -94,7 +96,7 @@ install: all install-modules install-include install-firmware install-xpp-firm
|
||||
@echo "###"
|
||||
@echo "###################################################"
|
||||
|
||||
uninstall: uninstall-modules uninstall-include uninstall-firmware
|
||||
uninstall: uninstall-modules uninstall-devices uninstall-include uninstall-firmware
|
||||
|
||||
install-modconf:
|
||||
build_tools/genmodconf $(BUILDVER) "$(ROOT_PREFIX)" "$(filter-out dahdi dahdi_dummy xpp dahdi_transcode dahdi_dynamic,$(BUILD_MODULES)) $(MODULE_ALIASES)"
|
||||
@@ -105,7 +107,6 @@ install-modconf:
|
||||
install-xpp-firm:
|
||||
$(MAKE) -C drivers/dahdi/xpp/firmwares install
|
||||
|
||||
|
||||
install-firmware:
|
||||
ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
$(MAKE) -C drivers/dahdi/firmware hotplug-install DESTDIR=$(DESTDIR) HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE)
|
||||
@@ -117,6 +118,13 @@ uninstall-firmware:
|
||||
firmware-loaders:
|
||||
$(MAKE) -C drivers/dahdi/firmware firmware-loaders
|
||||
|
||||
oct612x-lib:
|
||||
ifeq (no,$(HAS_KSRC))
|
||||
@echo "You do not appear to have the sources for the $(KVERS) kernel installed."
|
||||
@exit 1
|
||||
endif
|
||||
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x'
|
||||
|
||||
install-include:
|
||||
for hdr in $(INST_HEADERS); do \
|
||||
install -D -m 644 include/dahdi/$$hdr $(DESTDIR)/usr/include/dahdi/$$hdr; \
|
||||
@@ -129,6 +137,14 @@ uninstall-include:
|
||||
done
|
||||
-rmdir $(DESTDIR)/usr/include/dahdi
|
||||
|
||||
install-devices:
|
||||
install -d $(DESTDIR)$(UDEV_DIR)
|
||||
build_tools/genudevrules > $(DESTDIR)$(UDEV_DIR)/dahdi.rules
|
||||
install -m 644 drivers/dahdi/xpp/xpp.rules $(DESTDIR)$(UDEV_DIR)/
|
||||
|
||||
uninstall-devices:
|
||||
rm -f $(DESTDIR)$(UDEV_DIR)/dahdi.rules
|
||||
|
||||
install-modules: modules
|
||||
ifndef DESTDIR
|
||||
@if modinfo zaptel > /dev/null 2>&1; then \
|
||||
@@ -170,9 +186,6 @@ update:
|
||||
echo "Not under version control"; \
|
||||
fi
|
||||
|
||||
dist:
|
||||
@./build_tools/make_dist "dahdi-linux" "$(DAHDIVERSION)"
|
||||
|
||||
clean:
|
||||
ifneq (no,$(HAS_KSRC))
|
||||
$(KMAKE) clean
|
||||
@@ -191,20 +204,17 @@ dist-clean: clean
|
||||
firmware-download:
|
||||
@$(MAKE) -C drivers/dahdi/firmware all
|
||||
|
||||
ifneq (,$(wildcard test-script))
|
||||
test:
|
||||
./test-script $(DESTDIR)/lib/modules/$(KVERS) dahdi
|
||||
endif
|
||||
|
||||
docs: $(GENERATED_DOCS)
|
||||
|
||||
README.html: README
|
||||
date=`stat -c "%y" $<`
|
||||
$(ASCIIDOC_CMD) -a revdate="$$date" -o $@ $<
|
||||
$(ASCIIDOC_CMD) -o $@ $<
|
||||
|
||||
dahdi-api.html: drivers/dahdi/dahdi-base.c
|
||||
build_tools/kernel-doc --kernel $(KSRC) $^ >$@
|
||||
|
||||
.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders dist
|
||||
.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders
|
||||
|
||||
FORCE:
|
||||
|
||||
278
README
278
README
@@ -12,46 +12,43 @@ Supported Hardware
|
||||
------------------
|
||||
Digital Cards
|
||||
~~~~~~~~~~~~~
|
||||
- wcte43x:
|
||||
* Digium TE435: PCI express quad-port T1/E1/J1
|
||||
* Digium TE436: PCI quad-port T1/E1/J1
|
||||
* Digium TE235: PCI express dual-port T1/E1/J1
|
||||
* Digium TE236: PCI dual-port T1/E1/J1
|
||||
- wcte13xp:
|
||||
* Digium TE131: PCI express single-port T1/E1/J1
|
||||
* Digium TE133: PCI express single-port T1/E1/J1 with echocan
|
||||
* Digium TE132: PCI single-port T1/E1/J1
|
||||
* Digium TE134: PCI single-port T1/E1/J1 with echocan
|
||||
- wct4xxp:
|
||||
* Digium TE205P/TE207P/TE210P/TE212P: PCI dual-port T1/E1/J1
|
||||
* Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1
|
||||
* Digium TE220: PCI-Express dual-port T1/E1/J1
|
||||
* Digium TE420: PCI-Express quad-port T1/E1/J1
|
||||
* Digium TE820: PCI-Express eight-port T1/E1/J1
|
||||
- wcte12xp:
|
||||
* Digium TE120P: PCI single-port T1/E1/J1
|
||||
* Digium TE121: PCI-Express single-port T1/E1/J1
|
||||
* Digium TE122: PCI single-port T1/E1/J1
|
||||
- wcte11xp:
|
||||
* Digium TE110P: PCI single-port T1/E1/J1
|
||||
- wct1xxp:
|
||||
* Digium T100P: PCI single-port T1
|
||||
* Digium E100P: PCI single-port E1
|
||||
- wcb4xxp:
|
||||
* Digium B410: PCI quad-port BRI
|
||||
* Digium B233: PCI-Express dual-port BRI with echo can
|
||||
* Digium B234: PCI dual-port dual-port BRI with echo can
|
||||
* Digium B433: PCI-Express quad-port BRI with echo can
|
||||
* Digium B434: PCI quad-port BRI with echo can
|
||||
- tor2: Tormenta quad-span T1/E1 card from the Zapata Telephony project
|
||||
|
||||
|
||||
Analog Cards
|
||||
~~~~~~~~~~~~
|
||||
- wcaxx:
|
||||
* Digium A8A: PCI up to 8 mixed FXS/FXO ports
|
||||
* Digium A8B: PCI express up to 8 mixed FXS/FXO ports
|
||||
* Digium A4A: PCI up to 4 mixed FXS/FXO ports
|
||||
* Digium A4B: PCI express up to 4 mixed FXS/FXO ports
|
||||
- wctdm24xxp:
|
||||
* Digium TDM2400P/AEX2400: up to 24 analog ports
|
||||
* Digium TDM800P/AEX800: up to 8 analog ports
|
||||
* Digium TDM410P/AEX410: up to 4 analog ports
|
||||
* Digium Hx8 Series: Up to 8 analog or BRI ports
|
||||
- wctdm:
|
||||
* Digium TDM400P: up to 4 analog ports
|
||||
- xpp: Xorcom Astribank: a USB connected unit of up to 32 ports
|
||||
(including the digital BRI and E1/T1 modules)
|
||||
- wcfxo: X100P, similar and clones. A simple single-port FXO card
|
||||
|
||||
|
||||
Other Drivers
|
||||
~~~~~~~~~~~~~
|
||||
- pciradio: Zapata Telephony PCI Quad Radio Interface
|
||||
- wctc4xxp: Digium hardware transcoder cards (also need dahdi_transcode)
|
||||
- dahdi_dynamic_eth: TDM over Ethernet (TDMoE) driver. Requires dahdi_dynamic
|
||||
- dahdi_dynamic_loc: Mirror a local span. Requires dahdi_dynamic
|
||||
@@ -184,6 +181,204 @@ you a clue of the versions installed:
|
||||
find /lib/modules -name dahdi.ko
|
||||
|
||||
|
||||
Installing the B410P drivers with mISDN
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
DAHDI includes the wcb4xxp driver for the B410P, however, support for the
|
||||
B410P was historically provided by mISDN. If you would like to use the mISDN
|
||||
driver with the B410P, please comment out the wcb4xxp line in /etc/dahdi/modules.
|
||||
This will prevent DAHDI from loading wcb4xxp which will conflict with the mISDN
|
||||
driver.
|
||||
|
||||
To install the mISDN driver for the B410P, please see http://www.misdn.org for
|
||||
more information, but the following sequence of steps is roughly equivalent to
|
||||
'make b410p' from previous releases.
|
||||
|
||||
wget http://www.misdn.org/downloads/releases/mISDN-1_1_8.tar.gz
|
||||
wget http://www.misdn.org/downloads/releases/mISDNuser-1_1_8.tar.gz
|
||||
tar xfz mISDN-1_1_8.tar.gz
|
||||
tar xfz mISDNuser-1_1_8.tar.gz
|
||||
pushd mISDN-1_1_8
|
||||
make install
|
||||
popd
|
||||
pushd mISDNuser-1_1_8
|
||||
make install
|
||||
popd
|
||||
/usr/sbin/misdn-init config
|
||||
|
||||
You will then also want to make sure /etc/init.d/misdn-init is started
|
||||
automatically with either 'chkconfig --add misdn-init' or 'update-rc.d
|
||||
misdn-init defaults 15 30' depending on your distribution.
|
||||
|
||||
NOTE: At the time this was written, misdn-1.1.8 is not compatible the
|
||||
2.6.25 kernel. Please use a kernel version 2.6.25 or earlier.
|
||||
|
||||
|
||||
OSLEC
|
||||
~~~~~
|
||||
http://www.rowetel.com/ucasterisk/oslec.html[OSLEC] is an
|
||||
Open Source Line Echo Canceller. It is currently in the staging subtree
|
||||
of the mainline kernel and will hopefully be fully merged at around
|
||||
version 2.6.29. The echo canceller module dahdi_echocan_oslec
|
||||
provides a DAHDI echo canceller module that uses the code from OSLEC. As
|
||||
OSLEC has not been accepted into mainline yet, its interface is not set
|
||||
in stone and thus this driver may need to change. Thus it is not
|
||||
built by default.
|
||||
|
||||
Luckily the structure of the dahdi-linux tree matches that of the kernel
|
||||
tree. Hence you can basically copy drivers/staging/echo and place it
|
||||
under driver/staging/echo . In fact, dahdi_echocan_oslec assumes that
|
||||
this is where the oslec code lies. If it is elsewhere you'll need to fix
|
||||
the #include line.
|
||||
|
||||
Thus for the moment, the simplest way to build OSLEC with dahdi is to
|
||||
copy the directory `drivers/staging/echo` from a recent kernel tree (at
|
||||
least 2.6.28-rc1) to the a subdirectory with the same name in the
|
||||
dahdi-linux tree.
|
||||
|
||||
After doing that, you'll see the following when building (running
|
||||
'make')
|
||||
|
||||
...
|
||||
CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/dahdi_echocan_oslec.o
|
||||
CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/../staging/echo/echo.o
|
||||
...
|
||||
|
||||
As this is an experimental driver, problems building and using it should
|
||||
be reported on the
|
||||
https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing
|
||||
list].
|
||||
|
||||
Alternatively you can also get the OSLEC code from the dahdi-linux-extra
|
||||
GIT repository:
|
||||
|
||||
git clone git://gitorious.org/dahdi-extra/dahdi-linux-extra.git
|
||||
cd dahdi-linux-extra
|
||||
git archive extra-2.6 drivers/staging | (cd ..; tar xf -)
|
||||
cd ..; rm -rf dahdi-linux-extra
|
||||
|
||||
|
||||
Live Install
|
||||
~~~~~~~~~~~~
|
||||
In many cases you already have DAHDI installed on your system but would
|
||||
like to try a different version. E.g. in order to check if the latest
|
||||
version fixes a bug that your current system happens to have.
|
||||
|
||||
DAHDI-linux includes a script to automate the task of installing DAHDI
|
||||
to a subtree and using it instead of the system copy. Module loading
|
||||
through modprobe cannot be used. Thus the script pre-loads the required
|
||||
modules with insmod (which requires some quesswork as for which modules
|
||||
to load). It also sets PATH and other environment variables to make all
|
||||
the commands do the right thing.
|
||||
|
||||
There is an extra mode of operation to copy all the required files to a
|
||||
remote host and run things there, for those who don't like to test code
|
||||
on thir build system.
|
||||
|
||||
Live Install: The Basics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Basic operation is through running
|
||||
|
||||
./build_tools/live_dahdi
|
||||
|
||||
from the root directory of the dahdi-linux tree. Using DAHDI requires
|
||||
dahdi-tools as well, and the script builds and installs dahdi-tools. By
|
||||
default it assumes the tree of dahdi-tools is in the directory
|
||||
'dahdi-tools' alongside the dahdi-linux tree. If you want to checkout
|
||||
the trunks from SVN, use:
|
||||
|
||||
svn checkout http://svn.asterisk.org/svn/dahdi/linux/trunk dahdi-linux
|
||||
svn checkout http://svn.asterisk.org/svn/dahdi/tools/trunk dahdi-tools
|
||||
cd dahdi-linux
|
||||
|
||||
If the tools directory resides elsewhere, you'll need to edit
|
||||
live/live.conf (see later on). The usage message of live_dahdi:
|
||||
|
||||
Usage: equivalent of:
|
||||
live_dahdi configure ./configure
|
||||
live_dahdi install make install
|
||||
live_dahdi config make config
|
||||
live_dahdi unload /etc/init.d/dahdi stop
|
||||
live_dahdi load /etc/init.d/dahdi start
|
||||
live_dahdi reload /etc/init.d/dahdi restart
|
||||
live_dahdi xpp-firm (Reset and load xpp firmware)
|
||||
live_dahdi rsync TARGET (copy filea to /tmp/live in host TARGET)
|
||||
live_dahdi exec COMMAND (Run COMMAND in 'live' environment)
|
||||
|
||||
Normally you should run:
|
||||
|
||||
./build_tools/live_dahdi configure
|
||||
./build_tools/live_dahdi install
|
||||
./build_tools/live_dahdi config
|
||||
|
||||
to build and install everything. Up until now no real change was done.
|
||||
This could actually be run by a non-root user. All files are installed
|
||||
under the subdirectory live/ .
|
||||
|
||||
Reloading the modules (and restarting Asterisk) is done by:
|
||||
|
||||
./build_tools/live_dahdi reload
|
||||
|
||||
Note: this stops Asterisk, unloads the DAHDI modules, loads the DAHDI
|
||||
modules from the live/ subdirectory, configures the system and re-starts
|
||||
Asterisk. This *can* do damage to your system. Furthermore, the DAHDI
|
||||
configuration is generated by dahdi_genconf. It can be influenced by
|
||||
a genconf_parameters file. But it may or may not be what you want.
|
||||
|
||||
If you want to run a command in the environment of the live system, use
|
||||
the command 'exec':
|
||||
|
||||
./build_tools/live_dahdi lsdahdi
|
||||
./build_tools/live_dahdi dahdi_hardware -v
|
||||
|
||||
Note however:
|
||||
|
||||
./build_tools/live_dahdi dahdi_cfg -c live/etc/dahdi/system.conf
|
||||
|
||||
Live Install Remote
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
As mentioned above, live_dahdi can also copy all the live system files
|
||||
to a remote system and run from there. This requires rsync installed on
|
||||
both system and assumes you can connect to the remove system through
|
||||
ssh.
|
||||
|
||||
tzafrir@hilbert $ ./build_tools/live_dahdi rsync root@david
|
||||
root@david's password:
|
||||
<f+++++++++ live_dahdi
|
||||
cd+++++++++ live/
|
||||
<f+++++++++ live/live.conf
|
||||
cd+++++++++ live/dev/
|
||||
cd+++++++++ live/dev/dahdi/
|
||||
cd+++++++++ live/etc/
|
||||
cd+++++++++ live/etc/asterisk/
|
||||
cd+++++++++ live/etc/dahdi/
|
||||
<f+++++++++ live/etc/dahdi/genconf_parameters
|
||||
<f+++++++++ live/etc/dahdi/init.conf
|
||||
...
|
||||
|
||||
As you can see, it copies the script itselfand the whole live/
|
||||
subdirectory. The target directory is /tmp/live on the target directory
|
||||
(changing it should probably be simple, but I never needed that).
|
||||
|
||||
Then, on the remove computer:
|
||||
|
||||
root@david:/tmp# ./live_dahdi reload
|
||||
|
||||
|
||||
Configuring a Live Install
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
The live_dahdi script reads a configuration file in 'live/live.conf' if
|
||||
it exists. This file has the format of a shell script snippet:
|
||||
|
||||
var1=value # a '#' sign begins a comment
|
||||
var2='value'
|
||||
|
||||
# comments and empty lines are ignored
|
||||
var3="value"
|
||||
|
||||
The variables below can also be overriden from the environment:
|
||||
|
||||
var1='value' ./build_tools/live_dahdi
|
||||
|
||||
===== LINUX_DIR
|
||||
The relative path to the dahdi-linux tree. The default is '.' and normally
|
||||
there's no reason to override it.
|
||||
@@ -333,26 +528,16 @@ XPP (Astribank) module parameters
|
||||
==== dahdi_autoreg
|
||||
(xpp)
|
||||
|
||||
Deprecated. See dahdi.<<_auto_assign_spans,auto_assign_spans>> above.
|
||||
|
||||
Originally had a somewhat similar (but xpp-specific and more limited)
|
||||
role to auto_assign_spans. For backward compatibility this variable is
|
||||
still kept, but its value is unused. Astribanks will auto-register
|
||||
with dahdi if auto_assign_spans is not set.
|
||||
|
||||
==== tools_rootdir
|
||||
(xpp)
|
||||
|
||||
Defaults to /. Passed (as the variable DAHDI_TOOLS_ROOTDIR) to generated
|
||||
events (which can be used in udev hooks). Also serves as the base of
|
||||
the variable DAHDI_INIT_DIR (by default: $DAHDI_TOOLS_DIR/usr/share/dahdi).
|
||||
Register spans automatically (1) or not (0). Default: 0.
|
||||
Setting it simplifies operations with a single Astribank and no other
|
||||
DAHDI hardware. However if you have such systems, automatic
|
||||
registration can cause the order of spans to be unpredictable.
|
||||
The standard startup scripts use 'dahdi_registration on' instead of this.
|
||||
|
||||
==== initdir
|
||||
(xpp)
|
||||
|
||||
Deprecated. Setting both initdir and tools_rootdir will generate an error.
|
||||
|
||||
A directory under tools_rootdir containing the initialization scripts.
|
||||
This is the directory containing the initialization scripts.
|
||||
The default is /usr/share/dahdi .
|
||||
Setting this value could be useful if that location is inconvenient for you.
|
||||
|
||||
@@ -702,12 +887,11 @@ to other nodes.
|
||||
|
||||
Class DAHDI
|
||||
^^^^^^^^^^^
|
||||
Under /sys/class/dadhi there exists a node for the non-channel DAHDI
|
||||
device file under /dev/dahdi. The name is 'dahdi!foo' for the file
|
||||
'/dev/dahdi/foo' (udev translates exclamation marks to slashes). Those
|
||||
nodes are not, for the most part, proper SysFS nodes, and don't include
|
||||
any interesting properties. The files in this class `ctl`, `timer`,
|
||||
`channel`, `pseudo` and (if exists) `transcode`.
|
||||
under /sys/class/dadhi there exists a node for each DAHDI device file
|
||||
under /dev/dahdi. The name is 'dahdi!foo' for the file '/dev/dahdi/foo'
|
||||
(udev translates exclamation marks to slashes). Those nodes are not, for
|
||||
the most part, proper SysFS nodes, and don't include any interesting
|
||||
properties.
|
||||
|
||||
|
||||
Devices Bus
|
||||
@@ -732,10 +916,6 @@ A unique hardware-level identifier (e.g. serial number), if available.
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/manufacturer
|
||||
The name of the manufacturer. Freeform-string.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/registration_time
|
||||
The time at which the device registered with the DAHDI core. Example
|
||||
value: "0005634136.941901429".
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
|
||||
A line for each available span: <num>:<type>. This has to be provided
|
||||
here as in the case of manual assignment, userspace may need to know
|
||||
@@ -800,12 +980,6 @@ A very short type string.
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
|
||||
Current sync source.
|
||||
|
||||
==== sys/bus/dahdi_spans/drivers/generic_lowlevel/master_span
|
||||
All spans in the bus are handled by a single driver. The driver has one
|
||||
non-standard attribute: master_span. printing it shows the current DAHDI
|
||||
master span writing a number to it forces setting this span as the master
|
||||
span.
|
||||
|
||||
|
||||
Channels Bus
|
||||
^^^^^^^^^^^^
|
||||
@@ -1246,5 +1420,7 @@ http://issues.asterisk.org in the "DAHDI-linux" category.
|
||||
Links
|
||||
-----
|
||||
- http://asterisk.org/[] - The Asterisk PBX
|
||||
- http://voip-info.org/[]
|
||||
- http://voip-info.org/wiki/view/DAHDI[]
|
||||
- http://docs.tzafrir.org.il/dahdi-linux/README.html[Up-to-date HTML version
|
||||
of this file]
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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'"
|
||||
@@ -2,18 +2,119 @@
|
||||
|
||||
if [ -f ${1}/.version ]; then
|
||||
cat ${1}/.version
|
||||
elif [ -f ${1}/.svnrevision ]; then
|
||||
echo SVN-`cat ${1}/.svnbranch`-r`cat ${1}/.svnrevision`
|
||||
elif [ -d ${1}/.svn ]; then
|
||||
PARTS=`LANG=C svn info ${1} | grep URL | awk '{print $2;}' | sed -e s:^.*/svn/${2}/:: | sed -e 's:/: :g'`
|
||||
BRANCH=0
|
||||
TEAM=0
|
||||
|
||||
REV=`svnversion -c ${1} | cut -d: -f2`
|
||||
|
||||
if [ "${PARTS}" = "trunk" ]
|
||||
then
|
||||
echo SVN-'trunk'-r${REV}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for PART in $PARTS
|
||||
do
|
||||
if [ ${BRANCH} != 0 ]
|
||||
then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
break
|
||||
fi
|
||||
|
||||
if [ ${TEAM} != 0 ]
|
||||
then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "branches" ]
|
||||
then
|
||||
BRANCH=1
|
||||
RESULT="branch"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "tags" ]
|
||||
then
|
||||
BRANCH=1
|
||||
RESULT="tag"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "team" ]
|
||||
then
|
||||
TEAM=1
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
echo SVN-${RESULT##-}-r${REV}
|
||||
elif [ -d ${1}/.git ]; then
|
||||
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
|
||||
if [ $? -ne 0 ]; then
|
||||
MODIFIED=""
|
||||
# If the first log commit messages indicates that this is checked into
|
||||
# subversion, we'll just use the SVN- form of the revision.
|
||||
MODIFIED=""
|
||||
SVN_REV=`git log --pretty=full -1 | grep -F "git-svn-id:" | sed -e "s/.*\@\([^\s]*\)\s.*/\1/g"`
|
||||
if [ -z "$SVN_REV" ]; then
|
||||
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
|
||||
if [ $? -ne 0 ]; then
|
||||
if [ "`git ls-files -m | wc -l`" != "0" ]; then
|
||||
MODIFIED="M"
|
||||
fi
|
||||
# Some older versions of git do not support all the above
|
||||
# options.
|
||||
VERSION=GIT-`git rev-parse --short --verify HEAD`${MODIFIED}
|
||||
fi
|
||||
echo ${VERSION}
|
||||
else
|
||||
PARTS=`LANG=C git log --pretty=full | grep -F "git-svn-id:" | head -1 | awk '{print $2;}' | sed -e s:^.*/svn/$2/:: | sed -e 's:/: :g' | sed -e 's/@.*$//g'`
|
||||
BRANCH=0
|
||||
TEAM=0
|
||||
|
||||
if [ "`git ls-files -m | wc -l`" != "0" ]; then
|
||||
MODIFIED="M"
|
||||
fi
|
||||
# Some older versions of git do not support all the above
|
||||
# options.
|
||||
VERSION=GIT-`git rev-parse --short --verify HEAD`${MODIFIED}
|
||||
|
||||
if [ "${PARTS}" = "trunk" ]; then
|
||||
echo SVN-'trunk'-r${SVN_REV}${MODIFIED}
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for PART in $PARTS
|
||||
do
|
||||
if [ ${BRANCH} != 0 ]; then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
break
|
||||
fi
|
||||
|
||||
if [ ${TEAM} != 0 ]; then
|
||||
RESULT="${RESULT}-${PART}"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "branches" ]; then
|
||||
BRANCH=1
|
||||
RESULT="branch"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "tags" ]; then
|
||||
BRANCH=1
|
||||
RESULT="tag"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${PART}" = "team" ]; then
|
||||
TEAM=1
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
echo SVN-${RESULT##-}-r${SVN_REV}${MODIFIED}
|
||||
fi
|
||||
echo ${VERSION}
|
||||
else
|
||||
# Use the directory information in the absence of any other version
|
||||
# information
|
||||
|
||||
@@ -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
|
||||
@@ -1,57 +0,0 @@
|
||||
version: '3'
|
||||
services:
|
||||
|
||||
test-centos7:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: test/docker/centos7
|
||||
volumes:
|
||||
- ./:/source
|
||||
network_mode: "host"
|
||||
security_opt:
|
||||
- label=type:container_runtime_t
|
||||
tty: true
|
||||
|
||||
test-centos6:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: test/docker/centos6
|
||||
volumes:
|
||||
- ./:/source
|
||||
network_mode: "host"
|
||||
security_opt:
|
||||
- label=type:container_runtime_t
|
||||
tty: true
|
||||
|
||||
test-debianstable:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: test/docker/debianstable
|
||||
volumes:
|
||||
- ./:/source
|
||||
network_mode: "host"
|
||||
security_opt:
|
||||
- label=type:container_runtime_t
|
||||
tty: true
|
||||
|
||||
test-debiantesting:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: test/docker/debiantesting
|
||||
volumes:
|
||||
- ./:/source
|
||||
network_mode: "host"
|
||||
security_opt:
|
||||
- label=type:container_runtime_t
|
||||
tty: true
|
||||
|
||||
test-fedorarawhide:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: test/docker/fedorarawhide
|
||||
volumes:
|
||||
- ./:/source
|
||||
network_mode: "host"
|
||||
security_opt:
|
||||
- label=type:container_runtime_t
|
||||
tty: true
|
||||
@@ -7,38 +7,28 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF) += dahdi_dynamic_ethmf.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o
|
||||
|
||||
ifdef CONFIG_PCI
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) += oct612x/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
|
||||
|
||||
wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o
|
||||
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
|
||||
wcte13xp-objs := wcte13xp-base.o oct612x/lib.a
|
||||
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
|
||||
ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE43X) += wcte43x.o
|
||||
|
||||
wcte43x-objs := wcte43x-base.o wcxb_spi.o wcxb.o wcxb_flash.o
|
||||
CFLAGS_wcte43x-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
|
||||
ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
CFLAGS_wcte43x-base.o += -DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCAXX) += wcaxx.o
|
||||
|
||||
wcaxx-objs := wcaxx-base.o wcxb_spi.o wcxb.o wcxb_flash.o
|
||||
CFLAGS_wcaxx-base.o += -I$(src)/oct612x/ -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
|
||||
ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
CFLAGS_wcaxx-base.o += -DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/
|
||||
@@ -59,7 +49,7 @@ obj-m += dahdi_echocan_oslec.o
|
||||
obj-m += ../staging/echo/echo.o
|
||||
endif
|
||||
|
||||
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src) -Wno-format-truncation
|
||||
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src)
|
||||
|
||||
ifndef HOTPLUG_FIRMWARE
|
||||
ifneq (,$(filter y m,$(CONFIG_FW_LOADER)))
|
||||
@@ -127,7 +117,6 @@ dahdi_vpmadt032_loader-objs := vpmadt032_loader/dahdi_vpmadt032_loader.o
|
||||
|
||||
ifneq ($(DAHDI_ARCH),)
|
||||
ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_$(DAHDI_ARCH).o_shipped),)
|
||||
$(shell touch $(KBUILD_EXTMOD)/vpmadt032_loader/.vpmadt032_$(DAHDI_ARCH).o.cmd)
|
||||
VPMADT032_LOADER_PRESENT=yes
|
||||
dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_$(DAHDI_ARCH).o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o
|
||||
@@ -152,9 +141,15 @@ ifeq ($(HPEC_PRESENT),yes)
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_HPEC) += dahdi_echocan_hpec.o
|
||||
endif
|
||||
|
||||
$(obj)/pciradio.o: $(obj)/radfw.h
|
||||
$(obj)/tor2.o: $(obj)/tor2fw.h
|
||||
|
||||
hostprogs := makefw
|
||||
hostprogs-y := makefw
|
||||
|
||||
$(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw
|
||||
$(obj)/makefw $< tor2fw > $@
|
||||
|
||||
$(obj)/radfw.h: $(src)/pciradio.rbt $(obj)/makefw
|
||||
$(obj)/makefw $< radfw > $@
|
||||
|
||||
clean-files := radfw.h
|
||||
clean-files := radfw.h tor2fw.h
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -50,8 +50,10 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
|
||||
#include <linux/smp_lock.h>
|
||||
#endif
|
||||
|
||||
#include <linux/ppp_defs.h>
|
||||
|
||||
@@ -62,11 +64,6 @@
|
||||
/* Grab fasthdlc with tables */
|
||||
#define FAST_HDLC_NEED_TABLES
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
#include "ecdis.h"
|
||||
#include "dahdi.h"
|
||||
|
||||
@@ -99,7 +96,7 @@
|
||||
#define chan_to_netdev(h) ((h)->hdlcnetdev->netdev)
|
||||
|
||||
/* macro-oni for determining a unit (channel) number */
|
||||
#define UNIT(file) MINOR(file->f_path.dentry->d_inode->i_rdev)
|
||||
#define UNIT(file) MINOR(file->f_dentry->d_inode->i_rdev)
|
||||
|
||||
EXPORT_SYMBOL(dahdi_transcode_fops);
|
||||
EXPORT_SYMBOL(dahdi_init_tone_state);
|
||||
@@ -176,7 +173,7 @@ static sumtype *conf_sums_next;
|
||||
static sumtype *conf_sums;
|
||||
static sumtype *conf_sums_prev;
|
||||
|
||||
static struct dahdi_span *master_span;
|
||||
static struct dahdi_span *master;
|
||||
struct file_operations *dahdi_transcode_fops = NULL;
|
||||
|
||||
|
||||
@@ -194,7 +191,7 @@ static int maxlinks;
|
||||
|
||||
static struct core_timer {
|
||||
struct timer_list timer;
|
||||
ktime_t start_interval;
|
||||
struct timespec start_interval;
|
||||
unsigned long interval;
|
||||
int dahdi_receive_used;
|
||||
atomic_t count;
|
||||
@@ -614,7 +611,7 @@ void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec)
|
||||
/* Is this span our syncronization master? */
|
||||
int dahdi_is_sync_master(const struct dahdi_span *span)
|
||||
{
|
||||
return span == master_span;
|
||||
return span == master;
|
||||
}
|
||||
|
||||
static inline void rotate_sums(void)
|
||||
@@ -735,8 +732,6 @@ enum spantypes dahdi_str2spantype(const char *name)
|
||||
return SPANTYPE_DIGITAL_BRI_TE;
|
||||
else if (strcasecmp("BRI_SOFT", name) == 0)
|
||||
return SPANTYPE_DIGITAL_BRI_SOFT;
|
||||
else if (strcasecmp("DYNAMIC", name) == 0)
|
||||
return SPANTYPE_DIGITAL_DYNAMIC;
|
||||
else
|
||||
return SPANTYPE_INVALID;
|
||||
}
|
||||
@@ -754,7 +749,6 @@ const char *dahdi_spantype2str(enum spantypes st)
|
||||
case SPANTYPE_DIGITAL_BRI_NT: return "BRI_NT";
|
||||
case SPANTYPE_DIGITAL_BRI_TE: return "BRI_TE";
|
||||
case SPANTYPE_DIGITAL_BRI_SOFT: return "BRI_SOFT";
|
||||
case SPANTYPE_DIGITAL_DYNAMIC: return "DYNAMIC";
|
||||
default:
|
||||
case SPANTYPE_INVALID: return "INVALID";
|
||||
};
|
||||
@@ -793,7 +787,6 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
|
||||
int crc4_bit = 0;
|
||||
int len = 0;
|
||||
int bit;
|
||||
bool written = false;
|
||||
|
||||
for (bit = 4; bit <= 12; bit++) {
|
||||
int mask = (1 << bit);
|
||||
@@ -805,10 +798,8 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
|
||||
case DAHDI_CONFIG_AMI:
|
||||
case DAHDI_CONFIG_HDB3:
|
||||
framing_bit = bit;
|
||||
len += snprintf(buf + len, size, "%s%s",
|
||||
(written) ? "/" : "",
|
||||
len += snprintf(buf + len, size, "%s/",
|
||||
dahdi_lineconfig_bit_name(bit));
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
if (!coding_bit) {
|
||||
@@ -817,18 +808,14 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
|
||||
case DAHDI_CONFIG_D4:
|
||||
case DAHDI_CONFIG_CCS:
|
||||
coding_bit = bit;
|
||||
len += snprintf(buf + len, size, "%s%s",
|
||||
(written) ? "/" : "",
|
||||
len += snprintf(buf + len, size, "%s",
|
||||
dahdi_lineconfig_bit_name(bit));
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
if (!crc4_bit && mask == DAHDI_CONFIG_CRC4) {
|
||||
crc4_bit = bit;
|
||||
len += snprintf(buf + len, size, "%s%s",
|
||||
(written) ? "/" : "",
|
||||
len += snprintf(buf + len, size, "/%s",
|
||||
dahdi_lineconfig_bit_name(bit));
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
@@ -992,13 +979,10 @@ static int dahdi_seq_show(struct seq_file *sfile, void *data)
|
||||
|
||||
seq_fill_alarm_string(sfile, chan->chan_alarms);
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
if (chan->ec_factory) {
|
||||
if (chan->ec_factory)
|
||||
seq_printf(sfile, "(EC: %s - %s) ",
|
||||
chan->ec_factory->get_name(chan),
|
||||
chan->ec_state ? "ACTIVE" : "INACTIVE");
|
||||
}
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
seq_printf(sfile, "\n");
|
||||
}
|
||||
@@ -1011,14 +995,6 @@ static int dahdi_proc_open(struct inode *inode, struct file *file)
|
||||
return single_open(file, dahdi_seq_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops dahdi_proc_ops = {
|
||||
.proc_open = dahdi_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations dahdi_proc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dahdi_proc_open,
|
||||
@@ -1026,7 +1002,6 @@ static const struct file_operations dahdi_proc_ops = {
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1502,13 +1477,14 @@ static const struct dahdi_echocan_factory hwec_factory = {
|
||||
static int dahdi_enable_hw_preechocan(struct dahdi_chan *chan)
|
||||
{
|
||||
int res;
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (chan->ec_factory != &hwec_factory)
|
||||
res = -ENODEV;
|
||||
else
|
||||
res = 0;
|
||||
mutex_unlock(&chan->mutex);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
if (-ENODEV == res)
|
||||
return 0;
|
||||
@@ -1821,17 +1797,6 @@ static int start_tone(struct dahdi_chan *chan, int tone)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* stop_tone - Stops any tones on a channel.
|
||||
*
|
||||
* Must be called with chan->lock held.
|
||||
*
|
||||
*/
|
||||
static inline int stop_tone(struct dahdi_chan *chan)
|
||||
{
|
||||
return start_tone(chan, -1);
|
||||
}
|
||||
|
||||
static int set_tone_zone(struct dahdi_chan *chan, int zone)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -1859,9 +1824,6 @@ static int set_tone_zone(struct dahdi_chan *chan, int zone)
|
||||
return -ENODATA;
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
|
||||
stop_tone(chan);
|
||||
|
||||
if (chan->curzone) {
|
||||
struct dahdi_zone *zone = chan->curzone;
|
||||
chan->curzone = NULL;
|
||||
@@ -1910,7 +1872,6 @@ static void __dahdi_init_chan(struct dahdi_chan *chan)
|
||||
might_sleep();
|
||||
|
||||
spin_lock_init(&chan->lock);
|
||||
mutex_init(&chan->mutex);
|
||||
init_waitqueue_head(&chan->waitq);
|
||||
if (!chan->master)
|
||||
chan->master = chan;
|
||||
@@ -1974,10 +1935,12 @@ static inline void print_debug_writebuf(struct dahdi_chan* ss, struct sk_buff *s
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DAHDI_NET
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
|
||||
static inline struct net_device_stats *hdlc_stats(struct net_device *dev)
|
||||
{
|
||||
return &dev->stats;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dahdi_net_open(struct net_device *dev)
|
||||
{
|
||||
@@ -2327,10 +2290,10 @@ static void dahdi_chan_unreg(struct dahdi_chan *chan)
|
||||
*/
|
||||
}
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
release_echocan(chan->ec_factory);
|
||||
chan->ec_factory = NULL;
|
||||
mutex_unlock(&chan->mutex);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
#ifdef CONFIG_DAHDI_NET
|
||||
if (dahdi_have_netdev(chan)) {
|
||||
@@ -2413,9 +2376,6 @@ static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf,
|
||||
if (unlikely(count < 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)))
|
||||
return -ENODEV;
|
||||
|
||||
for (;;) {
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (chan->eventinidx != chan->eventoutidx) {
|
||||
@@ -2533,9 +2493,6 @@ static ssize_t dahdi_chan_write(struct file *file, const char __user *usrbuf,
|
||||
if (unlikely(count < 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)))
|
||||
return -ENODEV;
|
||||
|
||||
for (;;) {
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if ((chan->curtone || chan->pdialcount) && !is_pseudo_chan(chan)) {
|
||||
@@ -3085,64 +3042,57 @@ static const struct file_operations dahdi_chan_fops;
|
||||
|
||||
static int dahdi_specchan_open(struct file *file)
|
||||
{
|
||||
int res = -ENXIO;
|
||||
int res = 0;
|
||||
struct dahdi_chan *const chan = chan_from_file(file);
|
||||
|
||||
if (!chan || !chan->sig)
|
||||
return -ENXIO;
|
||||
|
||||
/* Make sure we're not already open, a net device, or a slave
|
||||
* device */
|
||||
if (dahdi_have_netdev(chan))
|
||||
res = -EBUSY;
|
||||
else if (chan->master != chan)
|
||||
res = -EBUSY;
|
||||
else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
|
||||
res = -EBUSY;
|
||||
else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
|
||||
unsigned long flags;
|
||||
const struct dahdi_span_ops *const ops =
|
||||
(!is_pseudo_chan(chan)) ? chan->span->ops : NULL;
|
||||
|
||||
if (ops && !try_module_get(ops->owner)) {
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
res = initialize_channel(chan);
|
||||
if (res) {
|
||||
/* Reallocbufs must have failed */
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (is_pseudo_chan(chan))
|
||||
chan->flags |= DAHDI_FLAG_AUDIO;
|
||||
chan->file = file;
|
||||
file->private_data = chan;
|
||||
/* Since we know we're a channel now, we can
|
||||
* update the f_op pointer and bypass a few of
|
||||
* the checks on the minor number. */
|
||||
file->f_op = &dahdi_chan_fops;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
if (ops && ops->open) {
|
||||
res = ops->open(chan);
|
||||
if (chan && chan->sig) {
|
||||
/* Make sure we're not already open, a net device, or a slave device */
|
||||
if (dahdi_have_netdev(chan))
|
||||
res = -EBUSY;
|
||||
else if (chan->master != chan)
|
||||
res = -EBUSY;
|
||||
else if ((chan->sig & __DAHDI_SIG_DACS) == __DAHDI_SIG_DACS)
|
||||
res = -EBUSY;
|
||||
else if (!test_and_set_bit(DAHDI_FLAGBIT_OPEN, &chan->flags)) {
|
||||
unsigned long flags;
|
||||
res = initialize_channel(chan);
|
||||
if (res) {
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
chan->file = NULL;
|
||||
file->private_data = NULL;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
module_put(ops->owner);
|
||||
close_channel(chan);
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN,
|
||||
&chan->flags);
|
||||
/* Reallocbufs must have failed */
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
return res;
|
||||
}
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (is_pseudo_chan(chan))
|
||||
chan->flags |= DAHDI_FLAG_AUDIO;
|
||||
if (chan->span) {
|
||||
const struct dahdi_span_ops *const ops =
|
||||
chan->span->ops;
|
||||
if (!try_module_get(ops->owner)) {
|
||||
res = -ENXIO;
|
||||
} else if (ops->open) {
|
||||
res = ops->open(chan);
|
||||
if (res)
|
||||
module_put(ops->owner);
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
chan->file = file;
|
||||
file->private_data = chan;
|
||||
/* Since we know we're a channel now, we can
|
||||
* update the f_op pointer and bypass a few of
|
||||
* the checks on the minor number. */
|
||||
file->f_op = &dahdi_chan_fops;
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
close_channel(chan);
|
||||
clear_bit(DAHDI_FLAGBIT_OPEN, &chan->flags);
|
||||
}
|
||||
} else {
|
||||
res = -EBUSY;
|
||||
}
|
||||
} else {
|
||||
res = -EBUSY;
|
||||
}
|
||||
} else
|
||||
res = -ENXIO;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3883,31 +3833,6 @@ void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms)
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
}
|
||||
|
||||
struct dahdi_span *get_master_span(void)
|
||||
{
|
||||
return master_span;
|
||||
}
|
||||
|
||||
void set_master_span(int spanno)
|
||||
{
|
||||
struct dahdi_span *s;
|
||||
unsigned long flags;
|
||||
struct dahdi_span *old_master;
|
||||
|
||||
spin_lock_irqsave(&chan_lock, flags);
|
||||
old_master = master_span;
|
||||
list_for_each_entry(s, &span_list, spans_node) {
|
||||
if (spanno == s->spanno) {
|
||||
master_span = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&chan_lock, flags);
|
||||
if ((debug & DEBUG_MAIN) && (old_master != master_span))
|
||||
module_printk(KERN_NOTICE, "Master span is set to %d (%s)\n",
|
||||
master_span->spanno, master_span->name);
|
||||
}
|
||||
|
||||
static void __dahdi_find_master_span(void)
|
||||
{
|
||||
struct dahdi_span *s;
|
||||
@@ -3915,7 +3840,7 @@ static void __dahdi_find_master_span(void)
|
||||
struct dahdi_span *old_master;
|
||||
|
||||
spin_lock_irqsave(&chan_lock, flags);
|
||||
old_master = master_span;
|
||||
old_master = master;
|
||||
list_for_each_entry(s, &span_list, spans_node) {
|
||||
if (s->alarms && old_master)
|
||||
continue;
|
||||
@@ -3925,23 +3850,31 @@ static void __dahdi_find_master_span(void)
|
||||
continue;
|
||||
if (!can_provide_timing(s))
|
||||
continue;
|
||||
if (master_span == s)
|
||||
if (master == s)
|
||||
continue;
|
||||
|
||||
master_span = s;
|
||||
master = s;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&chan_lock, flags);
|
||||
|
||||
if ((debug & DEBUG_MAIN) && (old_master != master_span))
|
||||
if ((debug & DEBUG_MAIN) && (old_master != master))
|
||||
module_printk(KERN_NOTICE, "Master changed to %s\n", s->name);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void _dahdi_find_master_span(void *work)
|
||||
{
|
||||
__dahdi_find_master_span();
|
||||
}
|
||||
static DECLARE_WORK(find_master_work, _dahdi_find_master_span, NULL);
|
||||
#else
|
||||
static void _dahdi_find_master_span(struct work_struct *work)
|
||||
{
|
||||
__dahdi_find_master_span();
|
||||
}
|
||||
static DECLARE_WORK(find_master_work, _dahdi_find_master_span);
|
||||
#endif
|
||||
|
||||
static void dahdi_find_master_span(void)
|
||||
{
|
||||
@@ -3966,7 +3899,7 @@ void dahdi_alarm_notify(struct dahdi_span *span)
|
||||
dahdi_alarm_channel(span->chans[x], span->alarms);
|
||||
|
||||
/* If we're going into or out of alarm we should try to find a
|
||||
* new master_span that may be a better fit. */
|
||||
* new master that may be a better fit. */
|
||||
dahdi_find_master_span();
|
||||
|
||||
/* Report more detailed alarms */
|
||||
@@ -4065,6 +3998,14 @@ dahdi_timer_unlocked_ioctl(struct file *file, unsigned int cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_UNLOCKED_IOCTL
|
||||
static int dahdi_timer_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long data)
|
||||
{
|
||||
return dahdi_timer_unlocked_ioctl(file, cmd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dahdi_ioctl_getgains(struct file *file, unsigned long data)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -4953,6 +4894,9 @@ static int dahdi_ioctl_chanconfig(struct file *file, unsigned long data)
|
||||
chan->hdlcnetdev->netdev = alloc_hdlcdev(chan->hdlcnetdev);
|
||||
if (chan->hdlcnetdev->netdev) {
|
||||
chan->hdlcnetdev->chan = chan;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
SET_MODULE_OWNER(chan->hdlcnetdev->netdev);
|
||||
#endif
|
||||
chan->hdlcnetdev->netdev->tx_queue_len = 50;
|
||||
#ifdef HAVE_NET_DEVICE_OPS
|
||||
chan->hdlcnetdev->netdev->netdev_ops = &dahdi_netdev_ops;
|
||||
@@ -5185,7 +5129,7 @@ static int dahdi_ioctl_startup(struct file *file, unsigned long data)
|
||||
}
|
||||
|
||||
/* Now that this span is running, it might be selected as the
|
||||
* master_span */
|
||||
* master span */
|
||||
__dahdi_find_master_span();
|
||||
}
|
||||
put_span(s);
|
||||
@@ -5245,6 +5189,7 @@ static bool dahdi_is_hwec_available(const struct dahdi_chan *chan)
|
||||
|
||||
static int dahdi_ioctl_attach_echocan(unsigned long data)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct dahdi_chan *chan;
|
||||
struct dahdi_attach_echocan ae;
|
||||
const struct dahdi_echocan_factory *new = NULL, *old;
|
||||
@@ -5286,10 +5231,10 @@ static int dahdi_ioctl_attach_echocan(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
old = chan->ec_factory;
|
||||
chan->ec_factory = new;
|
||||
mutex_unlock(&chan->mutex);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
|
||||
if (old)
|
||||
release_echocan(old);
|
||||
@@ -5689,9 +5634,9 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
|
||||
}
|
||||
/* if changing confs, clear last added info */
|
||||
if (conf.confno != chan->confna) {
|
||||
memset(chan->conflast, 0, sizeof(chan->conflast));
|
||||
memset(chan->conflast1, 0, sizeof(chan->conflast1));
|
||||
memset(chan->conflast2, 0, sizeof(chan->conflast2));
|
||||
memset(chan->conflast, 0, DAHDI_MAX_CHUNKSIZE);
|
||||
memset(chan->conflast1, 0, DAHDI_MAX_CHUNKSIZE);
|
||||
memset(chan->conflast2, 0, DAHDI_MAX_CHUNKSIZE);
|
||||
}
|
||||
oldconf = chan->confna; /* save old conference number */
|
||||
chan->confna = conf.confno; /* set conference number */
|
||||
@@ -6349,7 +6294,6 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
|
||||
if (ecp->tap_length == 0) {
|
||||
/* disable mode, don't need to inspect params */
|
||||
mutex_lock(&chan->mutex);
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
ec_state = chan->ec_state;
|
||||
chan->ec_state = NULL;
|
||||
@@ -6360,7 +6304,7 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
ec_state->ops->echocan_free(chan, ec_state);
|
||||
release_echocan(ec_current);
|
||||
}
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6377,7 +6321,6 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
goto exit_with_free;
|
||||
}
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
/* free any echocan that may be on the channel already */
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
ec_state = chan->ec_state;
|
||||
@@ -6448,7 +6391,6 @@ ioctl_echocancel(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
}
|
||||
|
||||
exit_with_free:
|
||||
mutex_unlock(&chan->mutex);
|
||||
kfree(params);
|
||||
|
||||
return ret;
|
||||
@@ -6999,6 +6941,25 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef HAVE_UNLOCKED_IOCTL
|
||||
static int dahdi_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long data)
|
||||
{
|
||||
return dahdi_unlocked_ioctl(file, cmd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_IOCTL
|
||||
static long dahdi_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
if (cmd == DAHDI_SFCONFIG)
|
||||
return -ENOTTY; /* Not supported yet */
|
||||
|
||||
return dahdi_unlocked_ioctl(file, cmd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* _get_next_channo - Return the next taken channel number from the span list.
|
||||
* @span: The span with which to start the search.
|
||||
@@ -7233,7 +7194,7 @@ EXPORT_SYMBOL(dahdi_init_span);
|
||||
* @spanno: The span number we would like assigned. If 0, the first
|
||||
* available spanno/basechan will be used.
|
||||
* @basechan: The base channel number we would like. Ignored if spanno is 0.
|
||||
* @prefmaster: will the new span be preferred as a master_span?
|
||||
* @prefmaster: will the new span be preferred as a master?
|
||||
*
|
||||
* Assigns a span for usage with DAHDI. All the channel numbers in it will
|
||||
* have their numbering started at basechan.
|
||||
@@ -7252,7 +7213,6 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
|
||||
{
|
||||
int res = 0;
|
||||
unsigned int x;
|
||||
unsigned long flags;
|
||||
|
||||
if (!span || !span->ops || !span->ops->owner)
|
||||
return -EFAULT;
|
||||
@@ -7264,16 +7224,6 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via
|
||||
* sysfs, so when the span is being reassigned we should make sure it's
|
||||
* cleared. This eliminates the need for board drivers to re-report
|
||||
* their alarm states on span reassignment. */
|
||||
|
||||
spin_lock_irqsave(&span->lock, flags);
|
||||
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
|
||||
dahdi_alarm_notify(span);
|
||||
spin_unlock_irqrestore(&span->lock, flags);
|
||||
|
||||
if (span->ops->enable_hw_preechocan ||
|
||||
span->ops->disable_hw_preechocan) {
|
||||
if ((NULL == span->ops->enable_hw_preechocan) ||
|
||||
@@ -7380,15 +7330,6 @@ int dahdi_assign_device_spans(struct dahdi_device *ddev)
|
||||
static int auto_assign_spans = 1;
|
||||
static const char *UNKNOWN = "";
|
||||
|
||||
/**
|
||||
* dahdi_auto_assign_spans - is the parameter auto_assign_spans set?
|
||||
*/
|
||||
int dahdi_get_auto_assign_spans(void)
|
||||
{
|
||||
return auto_assign_spans;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_get_auto_assign_spans);
|
||||
|
||||
/**
|
||||
* _dahdi_register_device - Registers a DAHDI device and assign its spans.
|
||||
* @ddev: the DAHDI device
|
||||
@@ -7416,7 +7357,6 @@ static int _dahdi_register_device(struct dahdi_device *ddev,
|
||||
__dahdi_init_span(s);
|
||||
}
|
||||
|
||||
ddev->registration_time = ktime_get();
|
||||
ret = dahdi_sysfs_add_device(ddev, parent);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -7532,8 +7472,8 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
|
||||
for (x=0;x<span->channels;x++)
|
||||
dahdi_chan_unreg(span->chans[x]);
|
||||
|
||||
new_master = master_span; /* FIXME: locking */
|
||||
if (master_span == span)
|
||||
new_master = master; /* FIXME: locking */
|
||||
if (master == span)
|
||||
new_master = NULL;
|
||||
|
||||
spin_lock_irqsave(&chan_lock, flags);
|
||||
@@ -7544,13 +7484,13 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&chan_lock, flags);
|
||||
if (master_span != new_master) {
|
||||
if (master != new_master) {
|
||||
if (debug & DEBUG_MAIN) {
|
||||
module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__,
|
||||
(new_master)? new_master->name: "no master");
|
||||
}
|
||||
}
|
||||
master_span = new_master;
|
||||
master = new_master;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7921,7 +7861,7 @@ static inline void __dahdi_process_getaudio_chunk(struct dahdi_chan *ss, unsigne
|
||||
memset(getlin, 0, DAHDI_CHUNKSIZE * sizeof(short));
|
||||
txb[0] = DAHDI_LIN2X(0, ms);
|
||||
memset(txb + 1, txb[0], DAHDI_CHUNKSIZE - 1);
|
||||
/* fallthrough */
|
||||
/* fall through to normal conf mode */
|
||||
case DAHDI_CONF_CONF: /* Normal conference mode */
|
||||
if (is_pseudo_chan(ms)) /* if pseudo-channel */
|
||||
{
|
||||
@@ -8484,7 +8424,7 @@ static void __dahdi_hooksig_pvt(struct dahdi_chan *chan, enum dahdi_rxsig rxsig)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* fallthrough */
|
||||
/* fall through intentionally */
|
||||
case DAHDI_SIG_FXSGS: /* FXS Groundstart */
|
||||
if (rxsig == DAHDI_RXSIG_ONHOOK) {
|
||||
chan->ringdebtimer = RING_DEBOUNCE_TIME;
|
||||
@@ -8503,7 +8443,7 @@ static void __dahdi_hooksig_pvt(struct dahdi_chan *chan, enum dahdi_rxsig rxsig)
|
||||
chan->gotgs = 1;
|
||||
}
|
||||
}
|
||||
/* fallthrough */
|
||||
/* fall through intentionally */
|
||||
case DAHDI_SIG_FXOLS: /* FXO Loopstart */
|
||||
case DAHDI_SIG_FXOKS: /* FXO Kewlstart */
|
||||
switch(rxsig) {
|
||||
@@ -9345,7 +9285,11 @@ that the waitqueue is empty. */
|
||||
#ifdef CONFIG_DAHDI_NET
|
||||
if (skb && dahdi_have_netdev(ms))
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
|
||||
skb->mac.raw = skb->data;
|
||||
#else
|
||||
skb_reset_mac_header(skb);
|
||||
#endif
|
||||
skb->dev = chan_to_netdev(ms);
|
||||
#ifdef DAHDI_HDLC_TYPE_TRANS
|
||||
skb->protocol = hdlc_type_trans(skb,
|
||||
@@ -10003,22 +9947,40 @@ static void coretimer_cleanup(void)
|
||||
|
||||
#else
|
||||
|
||||
static unsigned long core_diff_ms(struct timespec *t0, struct timespec *t1)
|
||||
{
|
||||
long nanosec, sec;
|
||||
unsigned long ms;
|
||||
sec = (t1->tv_sec - t0->tv_sec);
|
||||
nanosec = (t1->tv_nsec - t0->tv_nsec);
|
||||
while (nanosec >= NSEC_PER_SEC) {
|
||||
nanosec -= NSEC_PER_SEC;
|
||||
++sec;
|
||||
}
|
||||
while (nanosec < 0) {
|
||||
nanosec += NSEC_PER_SEC;
|
||||
--sec;
|
||||
}
|
||||
ms = (sec * 1000) + (nanosec / 1000000L);
|
||||
return ms;
|
||||
}
|
||||
|
||||
static inline unsigned long msecs_processed(const struct core_timer *const ct)
|
||||
{
|
||||
return atomic_read(&ct->count) * DAHDI_MSECS_PER_CHUNK;
|
||||
}
|
||||
|
||||
static void coretimer_func(TIMER_DATA_TYPE unused)
|
||||
static void coretimer_func(unsigned long param)
|
||||
{
|
||||
unsigned long flags;
|
||||
long ms_since_start;
|
||||
ktime_t now;
|
||||
unsigned long ms_since_start;
|
||||
struct timespec now;
|
||||
const unsigned long MAX_INTERVAL = 100000L;
|
||||
const unsigned long ONESEC_INTERVAL = HZ;
|
||||
const long MS_LIMIT = 3000;
|
||||
long difference;
|
||||
|
||||
now = ktime_get();
|
||||
ktime_get_ts(&now);
|
||||
|
||||
if (atomic_read(&core_timer.count) ==
|
||||
atomic_read(&core_timer.last_count)) {
|
||||
@@ -10036,7 +9998,7 @@ static void coretimer_func(TIMER_DATA_TYPE unused)
|
||||
core_timer.interval);
|
||||
}
|
||||
|
||||
ms_since_start = ktime_ms_delta(now, core_timer.start_interval);
|
||||
ms_since_start = core_diff_ms(&core_timer.start_interval, &now);
|
||||
|
||||
/*
|
||||
* If the system time has changed, it is possible for us to be
|
||||
@@ -10089,14 +10051,16 @@ static void coretimer_func(TIMER_DATA_TYPE unused)
|
||||
|
||||
static void coretimer_init(void)
|
||||
{
|
||||
timer_setup(&core_timer.timer, coretimer_func, 0);
|
||||
core_timer.start_interval = ktime_get();
|
||||
init_timer(&core_timer.timer);
|
||||
core_timer.timer.function = coretimer_func;
|
||||
ktime_get_ts(&core_timer.start_interval);
|
||||
atomic_set(&core_timer.count, 0);
|
||||
atomic_set(&core_timer.shutdown, 0);
|
||||
core_timer.interval = max(msecs_to_jiffies(DAHDI_MSECS_PER_CHUNK), 1UL);
|
||||
if (core_timer.interval < (HZ/250))
|
||||
core_timer.interval = (HZ/250);
|
||||
mod_timer(&core_timer.timer, jiffies + core_timer.interval);
|
||||
core_timer.timer.expires = jiffies + core_timer.interval;
|
||||
add_timer(&core_timer.timer);
|
||||
}
|
||||
|
||||
static void coretimer_cleanup(void)
|
||||
@@ -10236,35 +10200,33 @@ MODULE_PARM_DESC(auto_assign_spans,
|
||||
"channel numbers assigned by the driver. If 0, user space "
|
||||
"will need to assign them via /sys/bus/dahdi_devices.");
|
||||
|
||||
|
||||
static ssize_t dahdi_no_read(struct file *file, char __user *usrbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static ssize_t dahdi_no_write(struct file *file, const char __user *usrbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static const struct file_operations dahdi_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dahdi_open,
|
||||
.release = dahdi_release,
|
||||
#ifdef HAVE_UNLOCKED_IOCTL
|
||||
.unlocked_ioctl = dahdi_unlocked_ioctl,
|
||||
#ifdef HAVE_COMPAT_IOCTL
|
||||
.compat_ioctl = dahdi_ioctl_compat,
|
||||
#endif
|
||||
#else
|
||||
.ioctl = dahdi_ioctl,
|
||||
#endif
|
||||
.poll = dahdi_poll,
|
||||
.read = dahdi_no_read,
|
||||
.write = dahdi_no_write,
|
||||
};
|
||||
|
||||
static const struct file_operations dahdi_timer_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.release = dahdi_timer_release,
|
||||
#ifdef HAVE_UNLOCKED_IOCTL
|
||||
.unlocked_ioctl = dahdi_timer_unlocked_ioctl,
|
||||
#ifdef HAVE_COMPAT_IOCTL
|
||||
.compat_ioctl = dahdi_timer_unlocked_ioctl,
|
||||
#endif
|
||||
#else
|
||||
.ioctl = dahdi_timer_ioctl,
|
||||
#endif
|
||||
.poll = dahdi_timer_poll,
|
||||
.read = dahdi_no_read,
|
||||
.write = dahdi_no_write,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -10324,9 +10286,35 @@ nodev_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data)
|
||||
return nodev_common("ioctl");
|
||||
}
|
||||
|
||||
#ifndef HAVE_UNLOCKED_IOCTL
|
||||
static int nodev_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long data)
|
||||
{
|
||||
return nodev_unlocked_ioctl(file, cmd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_IOCTL
|
||||
static long nodev_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
if (cmd == DAHDI_SFCONFIG)
|
||||
return -ENOTTY; /* Not supported yet */
|
||||
|
||||
return nodev_unlocked_ioctl(file, cmd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct file_operations nodev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef HAVE_UNLOCKED_IOCTL
|
||||
.unlocked_ioctl = nodev_unlocked_ioctl,
|
||||
#ifdef HAVE_COMPAT_IOCTL
|
||||
.compat_ioctl = nodev_ioctl_compat,
|
||||
#endif
|
||||
#else
|
||||
.ioctl = nodev_ioctl,
|
||||
#endif
|
||||
.read = nodev_chan_read,
|
||||
.write = nodev_chan_write,
|
||||
.poll = nodev_chan_poll,
|
||||
@@ -10336,7 +10324,14 @@ static const struct file_operations dahdi_chan_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dahdi_open,
|
||||
.release = dahdi_release,
|
||||
#ifdef HAVE_UNLOCKED_IOCTL
|
||||
.unlocked_ioctl = dahdi_unlocked_ioctl,
|
||||
#ifdef HAVE_COMPAT_IOCTL
|
||||
.compat_ioctl = dahdi_ioctl_compat,
|
||||
#endif
|
||||
#else
|
||||
.ioctl = dahdi_ioctl,
|
||||
#endif
|
||||
.read = dahdi_chan_read,
|
||||
.write = dahdi_chan_write,
|
||||
.poll = dahdi_chan_poll,
|
||||
@@ -10345,7 +10340,7 @@ static const struct file_operations dahdi_chan_fops = {
|
||||
#ifdef CONFIG_DAHDI_WATCHDOG
|
||||
static struct timer_list watchdogtimer;
|
||||
|
||||
static void watchdog_check(TIMER_DATA_TYPE ignored)
|
||||
static void watchdog_check(unsigned long ignored)
|
||||
{
|
||||
unsigned long flags;
|
||||
static int wdcheck=0;
|
||||
@@ -10386,7 +10381,10 @@ static void watchdog_check(TIMER_DATA_TYPE ignored)
|
||||
|
||||
static int __init watchdog_init(void)
|
||||
{
|
||||
timer_setup(&watchdogtimer, watchdog_check, 0);
|
||||
init_timer(&watchdogtimer);
|
||||
watchdogtimer.expires = 0;
|
||||
watchdogtimer.data =0;
|
||||
watchdogtimer.function = watchdog_check;
|
||||
/* Run every couple of jiffy or so */
|
||||
mod_timer(&watchdogtimer, jiffies + 2);
|
||||
return 0;
|
||||
@@ -10442,10 +10440,35 @@ failed_driver_init:
|
||||
return res;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
|
||||
#ifdef CONFIG_PCI
|
||||
void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state)
|
||||
{
|
||||
u16 reg16;
|
||||
int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
||||
state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
|
||||
PCIE_LINK_STATE_CLKPM);
|
||||
if (!pos)
|
||||
return;
|
||||
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16);
|
||||
reg16 &= ~(state);
|
||||
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_pci_disable_link_state);
|
||||
#endif /* CONFIG_PCI */
|
||||
#endif /* 2.6.25 */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
static inline void flush_find_master_work(void)
|
||||
{
|
||||
flush_scheduled_work();
|
||||
}
|
||||
#else
|
||||
static inline void flush_find_master_work(void)
|
||||
{
|
||||
cancel_work_sync(&find_master_work);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __exit dahdi_cleanup(void)
|
||||
{
|
||||
|
||||
@@ -33,11 +33,9 @@
|
||||
|
||||
/* shortcuts, for code readability */
|
||||
#define MAKE_DAHDI_DEV(num, name) \
|
||||
device_create(dahdi_class, NULL, MKDEV(DAHDI_MAJOR, num), \
|
||||
NULL, "%s", name)
|
||||
|
||||
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
|
||||
#define DEL_DAHDI_DEV(num) \
|
||||
device_destroy(dahdi_class, MKDEV(DAHDI_MAJOR, num))
|
||||
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
|
||||
|
||||
static struct class *dahdi_class;
|
||||
|
||||
@@ -160,7 +158,6 @@ static BUS_ATTR_READER(ec_state_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute chan_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(channo),
|
||||
@@ -177,39 +174,6 @@ static struct device_attribute chan_dev_attrs[] = {
|
||||
__ATTR_RO(in_use),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(name);
|
||||
static DEVICE_ATTR_RO(channo);
|
||||
static DEVICE_ATTR_RO(chanpos);
|
||||
static DEVICE_ATTR_RO(sig);
|
||||
static DEVICE_ATTR_RO(sigcap);
|
||||
static DEVICE_ATTR_RO(alarms);
|
||||
static DEVICE_ATTR_RO(ec_factory);
|
||||
static DEVICE_ATTR_RO(ec_state);
|
||||
static DEVICE_ATTR_RO(blocksize);
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
static DEVICE_ATTR_RO(chanmute);
|
||||
#endif
|
||||
static DEVICE_ATTR_RO(in_use);
|
||||
|
||||
static struct attribute *chan_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_channo.attr,
|
||||
&dev_attr_chanpos.attr,
|
||||
&dev_attr_sig.attr,
|
||||
&dev_attr_sigcap.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_ec_factory.attr,
|
||||
&dev_attr_ec_state.attr,
|
||||
&dev_attr_blocksize.attr,
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
&dev_attr_chanmute.attr,
|
||||
#endif
|
||||
&dev_attr_in_use.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(chan_dev);
|
||||
#endif
|
||||
|
||||
static void chan_release(struct device *dev)
|
||||
{
|
||||
@@ -232,11 +196,7 @@ static int chan_match(struct device *dev, struct device_driver *driver)
|
||||
static struct bus_type chan_bus_type = {
|
||||
.name = "dahdi_channels",
|
||||
.match = chan_match,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = chan_dev_attrs,
|
||||
#else
|
||||
.dev_groups = chan_dev_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int chan_probe(struct device *dev)
|
||||
|
||||
@@ -32,15 +32,8 @@
|
||||
#include "dahdi-sysfs.h"
|
||||
|
||||
|
||||
static char *initdir;
|
||||
module_param(initdir, charp, 0444);
|
||||
MODULE_PARM_DESC(initdir,
|
||||
"deprecated, should use <tools_rootdir>/usr/share/dahdi");
|
||||
|
||||
static char *tools_rootdir;
|
||||
module_param(tools_rootdir, charp, 0444);
|
||||
MODULE_PARM_DESC(tools_rootdir,
|
||||
"root directory of all tools paths (default /)");
|
||||
static char *initdir = "/usr/share/dahdi";
|
||||
module_param(initdir, charp, 0644);
|
||||
|
||||
static int span_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
@@ -54,13 +47,43 @@ static inline struct dahdi_span *dev_to_span(struct device *dev)
|
||||
|
||||
#define SPAN_VAR_BLOCK \
|
||||
do { \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
|
||||
initdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
|
||||
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
|
||||
} while (0)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(envp, num_envp, &i, \
|
||||
buffer, buffer_size, &len, \
|
||||
fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int span_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int i = 0;
|
||||
int len = 0;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
if (!span)
|
||||
return -ENODEV;
|
||||
|
||||
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
|
||||
dev_name(dev), span->name);
|
||||
SPAN_VAR_BLOCK;
|
||||
envp[i] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(kenv, fmt, val); \
|
||||
@@ -83,6 +106,8 @@ static int span_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define span_attr(field, format_string) \
|
||||
static BUS_ATTR_READER(field##_show, dev, buf) \
|
||||
{ \
|
||||
@@ -180,7 +205,6 @@ static BUS_ATTR_READER(linecompat_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute span_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(desc),
|
||||
@@ -197,89 +221,17 @@ static struct device_attribute span_dev_attrs[] = {
|
||||
__ATTR_RO(linecompat),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(name);
|
||||
static DEVICE_ATTR_RO(desc);
|
||||
static DEVICE_ATTR_RO(spantype);
|
||||
static DEVICE_ATTR_RO(local_spanno);
|
||||
static DEVICE_ATTR_RO(alarms);
|
||||
static DEVICE_ATTR_RO(lbo);
|
||||
static DEVICE_ATTR_RO(syncsrc);
|
||||
static DEVICE_ATTR_RO(is_digital);
|
||||
static DEVICE_ATTR_RO(is_sync_master);
|
||||
static DEVICE_ATTR_RO(basechan);
|
||||
static DEVICE_ATTR_RO(channels);
|
||||
static DEVICE_ATTR_RO(lineconfig);
|
||||
static DEVICE_ATTR_RO(linecompat);
|
||||
|
||||
static struct attribute *span_dev_attrs[] = {
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_desc.attr,
|
||||
&dev_attr_spantype.attr,
|
||||
&dev_attr_local_spanno.attr,
|
||||
&dev_attr_lbo.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_syncsrc.attr,
|
||||
&dev_attr_is_digital.attr,
|
||||
&dev_attr_is_sync_master.attr,
|
||||
&dev_attr_basechan.attr,
|
||||
&dev_attr_channels.attr,
|
||||
&dev_attr_lineconfig.attr,
|
||||
&dev_attr_linecompat.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(span_dev);
|
||||
#endif
|
||||
|
||||
static ssize_t master_span_show(struct device_driver *driver, char *buf)
|
||||
{
|
||||
struct dahdi_span *s = get_master_span();
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", (s) ? s->spanno : 0);
|
||||
}
|
||||
|
||||
static ssize_t master_span_store(struct device_driver *driver, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int spanno;
|
||||
|
||||
if (sscanf(buf, "%d", &spanno) != 1) {
|
||||
module_printk(KERN_ERR, "non-numeric input '%s'\n", buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
set_master_span(spanno);
|
||||
return count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
static struct driver_attribute dahdi_attrs[] = {
|
||||
__ATTR(master_span, S_IRUGO | S_IWUSR, master_span_show,
|
||||
master_span_store),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DRIVER_ATTR_RW(master_span);
|
||||
static struct attribute *dahdi_attrs[] = {
|
||||
&driver_attr_master_span.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(dahdi);
|
||||
#endif
|
||||
|
||||
static struct bus_type spans_bus_type = {
|
||||
.name = "dahdi_spans",
|
||||
.match = span_match,
|
||||
.uevent = span_uevent,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = span_dev_attrs,
|
||||
#else
|
||||
.dev_groups = span_dev_groups,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
.drv_attrs = dahdi_attrs,
|
||||
#else
|
||||
.drv_groups = dahdi_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int span_probe(struct device *dev)
|
||||
@@ -344,7 +296,6 @@ void span_sysfs_remove(struct dahdi_span *span)
|
||||
|
||||
get_device(span_device);
|
||||
span_uevent_send(span, KOBJ_OFFLINE);
|
||||
sysfs_remove_link(&span_device->kobj, "ddev");
|
||||
device_unregister(span->span_device);
|
||||
dev_set_drvdata(span_device, NULL);
|
||||
span_device->parent = NULL;
|
||||
@@ -385,15 +336,6 @@ int span_sysfs_create(struct dahdi_span *span)
|
||||
span->span_device = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
res = sysfs_create_link(&span_device->kobj, &span_device->parent->kobj,
|
||||
"ddev");
|
||||
if (res) {
|
||||
span_err(span, "%s: sysfs_create_link failed: %d\n", __func__,
|
||||
res);
|
||||
kfree(span->span_device);
|
||||
span->span_device = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (x = 0; x < span->channels; x++) {
|
||||
res = chan_sysfs_create(span->chans[x]);
|
||||
@@ -420,40 +362,8 @@ static inline struct dahdi_device *to_ddev(struct device *dev)
|
||||
return container_of(dev, struct dahdi_device, dev);
|
||||
}
|
||||
|
||||
#define DEVICE_VAR_BLOCK \
|
||||
do { \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
|
||||
initdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_HWID=%s", \
|
||||
ddev->hardware_id); \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_LOCATION=%s", \
|
||||
ddev->location); \
|
||||
} while (0)
|
||||
|
||||
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(kenv, fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
||||
{
|
||||
struct dahdi_device *ddev;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
ddev = to_ddev(dev);
|
||||
if (!ddev)
|
||||
return -ENODEV;
|
||||
dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev));
|
||||
DEVICE_VAR_BLOCK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
manufacturer_show(struct device *dev,
|
||||
dahdi_device_manufacturer_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -461,7 +371,7 @@ manufacturer_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
type_show(struct device *dev,
|
||||
dahdi_device_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -469,7 +379,7 @@ type_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
span_count_show(struct device *dev,
|
||||
dahdi_device_span_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -483,7 +393,7 @@ span_count_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
hardware_id_show(struct device *dev,
|
||||
dahdi_device_hardware_id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -493,17 +403,7 @@ hardware_id_show(struct device *dev,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
location_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
(ddev->location) ? ddev->location : "");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
auto_assign_store(struct device *dev, struct device_attribute *attr,
|
||||
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
@@ -512,7 +412,7 @@ auto_assign_store(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
assign_span_store(struct device *dev, struct device_attribute *attr,
|
||||
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -547,7 +447,7 @@ assign_span_store(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
unassign_span_store(struct device *dev, struct device_attribute *attr,
|
||||
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
@@ -600,8 +500,7 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct dahdi_device *const ddev = to_ddev(dev);
|
||||
int ret;
|
||||
struct dahdi_span *span = NULL;
|
||||
struct dahdi_span *cur;
|
||||
struct dahdi_span *span;
|
||||
unsigned int local_span_number;
|
||||
char spantype_name[80];
|
||||
enum spantypes spantype;
|
||||
@@ -617,18 +516,9 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(cur, &ddev->spans, device_node) {
|
||||
if (local_spanno(cur) == local_span_number) {
|
||||
span = cur;
|
||||
list_for_each_entry(span, &ddev->spans, device_node) {
|
||||
if (local_spanno(span) == local_span_number)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!span || (local_spanno(span) != local_span_number)) {
|
||||
module_printk(KERN_WARNING,
|
||||
"%d is not a valid local span number "
|
||||
"for this device.\n", local_span_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
|
||||
@@ -637,6 +527,12 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (local_spanno(span) != local_span_number) {
|
||||
module_printk(KERN_WARNING,
|
||||
"%d is not a valid local span number "
|
||||
"for this device.\n", local_span_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!span->ops->set_spantype) {
|
||||
module_printk(KERN_WARNING, "Span %s does not support "
|
||||
@@ -648,70 +544,22 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
|
||||
return (ret < 0) ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_registration_time_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
int count = 0;
|
||||
struct timespec64 ts = ktime_to_timespec64(ddev->registration_time);
|
||||
|
||||
count += sprintf(buf, "%010lld.%09ld\n",
|
||||
(s64)ts.tv_sec,
|
||||
ts.tv_nsec);
|
||||
return count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute dahdi_device_attrs[] = {
|
||||
__ATTR(manufacturer, S_IRUGO, manufacturer_show, NULL),
|
||||
__ATTR(type, S_IRUGO, type_show, NULL),
|
||||
__ATTR(span_count, S_IRUGO, span_count_show, NULL),
|
||||
__ATTR(hardware_id, S_IRUGO, hardware_id_show, NULL),
|
||||
__ATTR(location, S_IRUGO, location_show, NULL),
|
||||
__ATTR(auto_assign, S_IWUSR, NULL, auto_assign_store),
|
||||
__ATTR(assign_span, S_IWUSR, NULL, assign_span_store),
|
||||
__ATTR(unassign_span, S_IWUSR, NULL, unassign_span_store),
|
||||
__ATTR(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
|
||||
__ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
|
||||
__ATTR(span_count, S_IRUGO, dahdi_device_span_count_show, NULL),
|
||||
__ATTR(hardware_id, S_IRUGO, dahdi_device_hardware_id_show, NULL),
|
||||
__ATTR(auto_assign, S_IWUSR, NULL, dahdi_device_auto_assign),
|
||||
__ATTR(assign_span, S_IWUSR, NULL, dahdi_device_assign_span),
|
||||
__ATTR(unassign_span, S_IWUSR, NULL, dahdi_device_unassign_span),
|
||||
__ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
|
||||
dahdi_spantype_store),
|
||||
__ATTR(registration_time, S_IRUGO, dahdi_registration_time_show, NULL),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(manufacturer);
|
||||
static DEVICE_ATTR_RO(type);
|
||||
static DEVICE_ATTR_RO(span_count);
|
||||
static DEVICE_ATTR_RO(hardware_id);
|
||||
static DEVICE_ATTR_RO(location);
|
||||
static DEVICE_ATTR_WO(auto_assign);
|
||||
static DEVICE_ATTR_WO(assign_span);
|
||||
static DEVICE_ATTR_WO(unassign_span);
|
||||
static DEVICE_ATTR_RW(dahdi_spantype);
|
||||
static DEVICE_ATTR_RO(dahdi_registration_time);
|
||||
static struct attribute *dahdi_device_attrs[] = {
|
||||
&dev_attr_manufacturer.attr,
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_span_count.attr,
|
||||
&dev_attr_hardware_id.attr,
|
||||
&dev_attr_location.attr,
|
||||
&dev_attr_auto_assign.attr,
|
||||
&dev_attr_assign_span.attr,
|
||||
&dev_attr_unassign_span.attr,
|
||||
&dev_attr_dahdi_spantype.attr,
|
||||
&dev_attr_dahdi_registration_time.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(dahdi_device);
|
||||
#endif
|
||||
|
||||
static struct bus_type dahdi_device_bus = {
|
||||
.name = "dahdi_devices",
|
||||
.uevent = device_uevent,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = dahdi_device_attrs,
|
||||
#else
|
||||
.dev_groups = dahdi_device_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void dahdi_sysfs_cleanup(void)
|
||||
@@ -791,19 +639,6 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
|
||||
int res = 0;
|
||||
|
||||
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
|
||||
|
||||
/* Handle dahdi-tools paths (for udev environment) */
|
||||
if (tools_rootdir && initdir) {
|
||||
dahdi_err("Cannot use tools-rootdir and initdir parameters simultaneously\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (initdir)
|
||||
pr_notice("dahdi: initdir is depracated -- prefer using \"tools_rootdir\" parameter\n");
|
||||
else
|
||||
initdir = "/usr/share/dahdi";
|
||||
if (!tools_rootdir)
|
||||
tools_rootdir = "";
|
||||
|
||||
res = bus_register(&dahdi_device_bus);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@@ -21,6 +21,29 @@
|
||||
#define DRIVER_ATTR_READER(name, drv, buf) \
|
||||
ssize_t name(struct device_driver *drv, char * buf)
|
||||
|
||||
/* Device file creation macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, NULL, "%s", name)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, name)
|
||||
#else
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
class_device_create(class, NULL, devt, device, name)
|
||||
#endif
|
||||
|
||||
/* Device file destruction macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
device_destroy(class, devt)
|
||||
#else
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
class_device_destroy(class, devt)
|
||||
#endif
|
||||
|
||||
/* Global */
|
||||
int __init dahdi_sysfs_chan_init(const struct file_operations *fops);
|
||||
void dahdi_sysfs_chan_exit(void);
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if defined(CONFIG_HIGH_RES_TIMERS)
|
||||
#if defined(CONFIG_HIGH_RES_TIMERS) && \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
|
||||
#define USE_HIGHRESTIMER
|
||||
#endif
|
||||
|
||||
@@ -49,8 +50,9 @@
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#if defined(USE_HIGHRESTIMER)
|
||||
#include <linux/hrtimer.h>
|
||||
#if !defined(USE_HIGHRESTIMER)
|
||||
#else
|
||||
#include <linux/timer.h>
|
||||
#endif
|
||||
|
||||
@@ -79,7 +81,7 @@ struct dahdi_dummy {
|
||||
struct dahdi_chan *chan;
|
||||
#if !defined(USE_HIGHRESTIMER)
|
||||
unsigned long calls_since_start;
|
||||
ktime_t start_interval;
|
||||
struct timespec start_interval;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -137,19 +139,36 @@ static enum hrtimer_restart dahdi_dummy_hr_int(struct hrtimer *htmr)
|
||||
return HRTIMER_RESTART;
|
||||
}
|
||||
#else
|
||||
|
||||
static void dahdi_dummy_timer(TIMER_DATA_TYPE unused)
|
||||
static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1)
|
||||
{
|
||||
long ms_since_start;
|
||||
ktime_t now;
|
||||
const long MAX_INTERVAL = 100000L;
|
||||
const long MS_LIMIT = 3000;
|
||||
long nanosec, sec;
|
||||
unsigned long ms;
|
||||
sec = (t1->tv_sec - t0->tv_sec);
|
||||
nanosec = (t1->tv_nsec - t0->tv_nsec);
|
||||
while (nanosec >= NSEC_PER_SEC) {
|
||||
nanosec -= NSEC_PER_SEC;
|
||||
++sec;
|
||||
}
|
||||
while (nanosec < 0) {
|
||||
nanosec += NSEC_PER_SEC;
|
||||
--sec;
|
||||
}
|
||||
ms = (sec * 1000) + (nanosec / 1000000L);
|
||||
return ms;
|
||||
}
|
||||
|
||||
static void dahdi_dummy_timer(unsigned long param)
|
||||
{
|
||||
unsigned long ms_since_start;
|
||||
struct timespec now;
|
||||
const unsigned long MAX_INTERVAL = 100000L;
|
||||
const unsigned long MS_LIMIT = 3000;
|
||||
|
||||
if (!atomic_read(&shutdown))
|
||||
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
|
||||
|
||||
now = ktime_get();
|
||||
ms_since_start = ktime_ms_delta(now, ztd->start_interval);
|
||||
now = current_kernel_time();
|
||||
ms_since_start = timespec_diff_ms(&ztd->start_interval, &now);
|
||||
|
||||
/*
|
||||
* If the system time has changed, it is possible for us to be far
|
||||
@@ -239,10 +258,12 @@ int init_module(void)
|
||||
hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL);
|
||||
printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n");
|
||||
#else
|
||||
timer_setup(&timer, dahdi_dummy_timer, 0);
|
||||
ztd->start_interval = ktime_get();
|
||||
init_timer(&timer);
|
||||
timer.function = dahdi_dummy_timer;
|
||||
ztd->start_interval = current_kernel_time();
|
||||
timer.expires = jiffies + JIFFIES_INTERVAL;
|
||||
atomic_set(&shutdown, 0);
|
||||
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
|
||||
add_timer(&timer);
|
||||
#endif
|
||||
|
||||
if (debug)
|
||||
|
||||
@@ -201,9 +201,7 @@ static void dahdi_dynamic_sendmessage(struct dahdi_dynamic *d)
|
||||
static void __dahdi_dynamic_run(void)
|
||||
{
|
||||
struct dahdi_dynamic *d;
|
||||
#ifdef ENABLE_TASKLETS
|
||||
struct dahdi_dynamic_driver *drv;
|
||||
#endif
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(d, &dspan_list, list) {
|
||||
@@ -213,13 +211,6 @@ static void __dahdi_dynamic_run(void)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TASKLETS
|
||||
list_for_each_entry_rcu(drv, &driver_list, list) {
|
||||
/* Flush any traffic still pending in the driver */
|
||||
if (drv->flush) {
|
||||
drv->flush();
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* If tasklets are not enabled, the above section will be called in
|
||||
* interrupt context and the flushing of each driver will be called in a
|
||||
* separate tasklet that only handles that. This is necessary since some
|
||||
@@ -230,6 +221,13 @@ static void __dahdi_dynamic_run(void)
|
||||
*
|
||||
*/
|
||||
tasklet_hi_schedule(&dahdi_dynamic_flush_tlet);
|
||||
#else
|
||||
list_for_each_entry_rcu(drv, &driver_list, list) {
|
||||
/* Flush any traffic still pending in the driver */
|
||||
if (drv->flush) {
|
||||
drv->flush();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -467,7 +465,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
|
||||
|
||||
/* We shouldn't have more than the two references at this point. If
|
||||
* we do, there are probably channels that are still opened. */
|
||||
if (refcount_read(&d->kref.refcount) > 2) {
|
||||
if (atomic_read(&d->kref.refcount) > 2) {
|
||||
dynamic_put(d);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -632,14 +630,10 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
d->span.deflaw = DAHDI_LAW_MULAW;
|
||||
d->span.flags |= DAHDI_FLAG_RBS;
|
||||
d->span.chans = d->chans;
|
||||
d->span.spantype = SPANTYPE_DIGITAL_DYNAMIC;
|
||||
d->span.linecompat = DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
|
||||
DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_CCS |
|
||||
DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_NOTOPEN;
|
||||
d->span.ops = &dynamic_ops;
|
||||
for (x = 0; x < d->span.channels; x++) {
|
||||
snprintf(d->chans[x]->name, sizeof(d->chans[x]->name),
|
||||
"DYN/%s/%s/%d", dds->driver, dds->addr, x+1);
|
||||
sprintf(d->chans[x]->name, "DYN/%s/%s/%d",
|
||||
dds->driver, dds->addr, x+1);
|
||||
d->chans[x]->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR |
|
||||
DAHDI_SIG_FXSLS | DAHDI_SIG_FXSKS |
|
||||
DAHDI_SIG_FXSGS | DAHDI_SIG_FXOLS |
|
||||
@@ -831,7 +825,7 @@ EXPORT_SYMBOL(dahdi_dynamic_unregister_driver);
|
||||
|
||||
static struct timer_list alarmcheck;
|
||||
|
||||
static void check_for_red_alarm(TIMER_DATA_TYPE unused)
|
||||
static void check_for_red_alarm(unsigned long ignored)
|
||||
{
|
||||
int newalarm;
|
||||
int alarmchanged = 0;
|
||||
@@ -867,7 +861,10 @@ static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
|
||||
static int dahdi_dynamic_init(void)
|
||||
{
|
||||
/* Start process to check for RED ALARM */
|
||||
timer_setup(&alarmcheck, check_for_red_alarm, 0);
|
||||
init_timer(&alarmcheck);
|
||||
alarmcheck.expires = 0;
|
||||
alarmcheck.data = 0;
|
||||
alarmcheck.function = check_for_red_alarm;
|
||||
/* Check once per second */
|
||||
mod_timer(&alarmcheck, jiffies + 1 * HZ);
|
||||
#ifdef ENABLE_TASKLETS
|
||||
|
||||
@@ -80,7 +80,11 @@ static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
struct ztdeth_header *zh;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
zh = (struct ztdeth_header *)skb_network_header(skb);
|
||||
#else
|
||||
zh = (struct ztdeth_header *)skb->nh.raw;
|
||||
#endif
|
||||
span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
|
||||
if (span) {
|
||||
skb_pull(skb, sizeof(struct ztdeth_header));
|
||||
@@ -162,9 +166,18 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
|
||||
/* Setup protocol and such */
|
||||
skb->protocol = __constant_htons(ETH_P_DAHDI_DETH);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||
skb_set_network_header(skb, 0);
|
||||
#else
|
||||
skb->nh.raw = skb->data;
|
||||
#endif
|
||||
skb->dev = dev;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
|
||||
dev_hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len);
|
||||
#else
|
||||
if (dev->hard_header)
|
||||
dev->hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len);
|
||||
#endif
|
||||
skb_queue_tail(&skbs, skb);
|
||||
}
|
||||
}
|
||||
@@ -253,7 +266,6 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
|
||||
struct ztdeth *z = dyn->pvt;
|
||||
unsigned long flags;
|
||||
struct ztdeth *prev=NULL, *cur;
|
||||
|
||||
spin_lock_irqsave(&zlock, flags);
|
||||
cur = zdevs;
|
||||
while(cur) {
|
||||
@@ -267,14 +279,12 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
|
||||
if (cur == z) { /* Successfully removed */
|
||||
dyn->pvt = NULL;
|
||||
dev_put(z->dev);
|
||||
printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
|
||||
kfree(z);
|
||||
}
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
|
||||
@@ -355,7 +365,11 @@ static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
|
||||
}
|
||||
z->subaddr = htons(sub);
|
||||
}
|
||||
z->dev = dev_get_by_name(&init_net, z->ethdev);
|
||||
z->dev = dev_get_by_name(
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
|
||||
&init_net,
|
||||
#endif
|
||||
z->ethdev);
|
||||
if (!z->dev) {
|
||||
printk(KERN_NOTICE "TDMoE: Invalid device '%s'\n", z->ethdev);
|
||||
kfree(z);
|
||||
|
||||
@@ -236,7 +236,11 @@ static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned int samples, channels, rbslen, flags;
|
||||
unsigned int skip = 0;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
|
||||
zh = (struct ztdeth_header *) skb_network_header(skb);
|
||||
#else
|
||||
zh = (struct ztdeth_header *) skb->nh.raw;
|
||||
#endif
|
||||
if (ntohs(zh->subaddr) & 0x8000) {
|
||||
/* got a multi-span frame */
|
||||
num_spans = ntohs(zh->subaddr) & 0xFF;
|
||||
@@ -480,9 +484,19 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
|
||||
/* Setup protocol type */
|
||||
skb->protocol = __constant_htons(ETH_P_ZTDETH);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
|
||||
skb_set_network_header(skb, 0);
|
||||
#else
|
||||
skb->nh.raw = skb->data;
|
||||
#endif
|
||||
skb->dev = dev;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||
dev_hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len);
|
||||
#else
|
||||
if (dev->hard_header)
|
||||
dev->hard_header(skb, dev, ETH_P_ZTDETH, addr,
|
||||
dev->dev_addr, skb->len);
|
||||
#endif
|
||||
/* queue frame for delivery */
|
||||
if (dev) {
|
||||
skb_queue_tail(&skbs, skb);
|
||||
@@ -589,7 +603,11 @@ static int ztdethmf_create(struct dahdi_dynamic *dyn, const char *addr)
|
||||
kfree(z);
|
||||
return -EINVAL;
|
||||
}
|
||||
z->dev = dev_get_by_name(&init_net, z->ethdev);
|
||||
z->dev = dev_get_by_name(
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||
&init_net,
|
||||
#endif
|
||||
z->ethdev);
|
||||
if (!z->dev) {
|
||||
printk(KERN_ERR "TDMoE Multiframe: Invalid device '%s'\n", z->ethdev);
|
||||
kfree(z);
|
||||
@@ -663,13 +681,16 @@ static int ethmf_delay_dec(void)
|
||||
* Timer callback function to allow all spans to be added, prior to any of
|
||||
* them being used.
|
||||
*/
|
||||
static void timer_callback(TIMER_DATA_TYPE unused)
|
||||
static void timer_callback(unsigned long param)
|
||||
{
|
||||
if (ethmf_delay_dec()) {
|
||||
if (!atomic_read(&timer_deleted))
|
||||
mod_timer(&timer, jiffies + HZ);
|
||||
if (!atomic_read(&timer_deleted)) {
|
||||
timer.expires = jiffies + HZ;
|
||||
add_timer(&timer);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_INFO "All TDMoE multiframe span groups are active.\n");
|
||||
del_timer(&timer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,28 +754,21 @@ static int ztdethmf_proc_open(struct inode *inode, struct file *file)
|
||||
return single_open(file, ztdethmf_proc_show, NULL);
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops ztdethmf_proc_fops = {
|
||||
.proc_open = ztdethmf_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = seq_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations ztdethmf_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ztdethmf_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.open = ztdethmf_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
#endif
|
||||
|
||||
static int __init ztdethmf_init(void)
|
||||
{
|
||||
timer_setup(&timer, timer_callback, 0);
|
||||
mod_timer(&timer, jiffies + HZ);
|
||||
init_timer(&timer);
|
||||
timer.expires = jiffies + HZ;
|
||||
timer.function = &timer_callback;
|
||||
if (!timer_pending(&timer))
|
||||
add_timer(&timer);
|
||||
|
||||
dev_add_pack(&ztdethmf_ptype);
|
||||
register_netdevice_notifier(&ztdethmf_nblock);
|
||||
|
||||
@@ -168,9 +168,8 @@ static void dtc_release(struct dahdi_transcoder_channel *chan)
|
||||
BUG_ON(!chan);
|
||||
if (chan->parent && chan->parent->release) {
|
||||
chan->parent->release(chan);
|
||||
} else {
|
||||
dahdi_tc_clear_busy(chan);
|
||||
}
|
||||
dahdi_tc_clear_busy(chan);
|
||||
}
|
||||
|
||||
static int dahdi_tc_release(struct inode *inode, struct file *file)
|
||||
@@ -397,6 +396,13 @@ static long dahdi_tc_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
|
||||
};
|
||||
}
|
||||
|
||||
#ifndef HAVE_UNLOCKED_IOCTL
|
||||
static int dahdi_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data)
|
||||
{
|
||||
return (int)dahdi_tc_unlocked_ioctl(file, cmd, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int dahdi_tc_poll(struct file *file, struct poll_table_struct *wait_table)
|
||||
{
|
||||
int ret;
|
||||
@@ -420,7 +426,11 @@ static struct file_operations __dahdi_transcode_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dahdi_tc_open,
|
||||
.release = dahdi_tc_release,
|
||||
#ifdef HAVE_UNLOCKED_IOCTL
|
||||
.unlocked_ioctl = dahdi_tc_unlocked_ioctl,
|
||||
#else
|
||||
.ioctl = dahdi_tc_ioctl,
|
||||
#endif
|
||||
.read = dahdi_tc_read,
|
||||
.write = dahdi_tc_write,
|
||||
.poll = dahdi_tc_poll,
|
||||
|
||||
@@ -8,7 +8,7 @@ PWD=$(shell pwd)
|
||||
|
||||
MODULESO:=$(MODULES:%=%.o)
|
||||
MODULESKO:=$(MODULES:%=%.ko)
|
||||
KMAKE = $(MAKE) -C $(KSRC) M=$(PWD)
|
||||
KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD)
|
||||
KMAKE_INST = $(KMAKE) \
|
||||
INSTALL_MOD_PATH=$(INSTALL_PREFIX) INSTALL_MOD_DIR=misc modules_install
|
||||
|
||||
|
||||
@@ -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>
|
||||
#
|
||||
@@ -31,20 +31,12 @@ VPMADT032_VERSION:=1.25.0
|
||||
HX8_VERSION:=2.06
|
||||
VPMOCT032_VERSION:=1.12.0
|
||||
WCT820_VERSION:=1.76
|
||||
TE133_VERSION:=7a001e
|
||||
TE134_VERSION:=780017
|
||||
TE435_VERSION:=13001e
|
||||
TE436_VERSION:=10017
|
||||
A8A_VERSION:=1d0017
|
||||
A8B_VERSION:=1f001e
|
||||
A4A_VERSION:=a0017
|
||||
A4B_VERSION:=d001e
|
||||
TE133_VERSION:=6f0017
|
||||
TE134_VERSION:=6f0017
|
||||
|
||||
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
|
||||
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256
|
||||
ALL_FIRMWARE+=FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
|
||||
ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435 FIRMWARE-TE436
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
|
||||
|
||||
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
|
||||
# First example: dahdi-fw-oct6114-064-1.05.01
|
||||
@@ -63,12 +55,6 @@ FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE435=dahdi-fw-te435-$(TE435_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE436=dahdi-fw-te436-$(TE436_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8A=dahdi-fw-a8b-$(A8B_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8B=dahdi-fw-a8a-$(A8A_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4A=dahdi-fw-a4b-$(A4B_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4B=dahdi-fw-a4a-$(A4A_VERSION).tar.gz)
|
||||
|
||||
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
|
||||
|
||||
@@ -84,8 +70,6 @@ OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
|
||||
# Force usage of wget, for now
|
||||
DOWNLOAD=wget
|
||||
WGET=wget
|
||||
INSTALL_FIRMWARE=../../../build_tools/install_firmware
|
||||
RUN_INST=$(INSTALL_FIRMWARE) $(1) $(2) $(DESTDIR)
|
||||
|
||||
# If "fetch" is used, --continue is not a valid option.
|
||||
ifeq ($(WGET),wget)
|
||||
@@ -111,6 +95,7 @@ dahdi-fw-%.tar.gz:
|
||||
echo "Attempting to download $@"; \
|
||||
if test ! -f $@; then $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \
|
||||
if test ! -f $@; then exit 1; fi; \
|
||||
(cat $@ | gzip -d | tar --no-same-owner -xf -) \
|
||||
fi
|
||||
|
||||
firmware-loaders: $(FWLOADERS)
|
||||
@@ -129,22 +114,117 @@ $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware:
|
||||
|
||||
# Install all downloaded firmware images for hotplug usage
|
||||
hotplug-install: $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware $(FIRMWARE)
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-032,$(OCT6114_032_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-064,$(OCT6114_064_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-128,$(OCT6114_128_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-oct6114-256,$(OCT6114_256_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-tc400m,$(TC400M_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-hx8,$(HX8_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-vpmoct032,$(VPMOCT032_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te820,$(WCT820_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te133,$(TE133_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te134,$(TE134_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te435,$(TE435_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-te436,$(TE436_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a8a,$(A8A_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a8b,$(A8B_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a4a,$(A4A_VERSION))
|
||||
@$(call RUN_INST,dahdi-fw-a4b,$(A4B_VERSION))
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-032.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-032.bin is already installed with required version $(OCT6114_032_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-064.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-064.bin is already installed with required version $(OCT6114_064_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-128.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-128.bin is already installed with required version $(OCT6114_128_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-256.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-256.bin is already installed with required version $(OCT6114_256_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-tc400m.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION)
|
||||
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-tc400m.bin is already installed with required version $(TC400M_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-$(HX8_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-$(HX8_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-hx8.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-hx8.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-hx8-$(HX8_VERSION)
|
||||
@install -m 644 dahdi-fw-hx8.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-hx8-$(HX8_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-hx8.bin is already installed with required version $(HX8_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-vpmoct032.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-vpmoct032.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION)
|
||||
@install -m 644 dahdi-fw-vpmoct032.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-vpmoct032-$(VPMOCT032_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-vpmoct032.bin is already installed with required version $(VPMOCT032_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te820.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
|
||||
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te820-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te820.bin is already installed with required version $(WCT820_VERSION)"
|
||||
endif
|
||||
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te133.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION)
|
||||
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te133-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te133.bin is already installed with required version $(TE133_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te134.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION)
|
||||
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te134-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te134.bin is already installed with required version $(TE134_VERSION)"
|
||||
endif
|
||||
|
||||
# Uninstall any installed dahdi firmware images from hotplug firmware directories
|
||||
hotplug-uninstall:
|
||||
|
||||
@@ -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)
|
||||
@@ -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_
|
||||
{
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
* Octasic OCT6100 Interface
|
||||
*
|
||||
* Copyright (C) 2013 Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#include "oct612x.h"
|
||||
|
||||
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
|
||||
{
|
||||
/* Why couldn't they just take a timeval like everyone else? */
|
||||
u64 total_usecs;
|
||||
|
||||
total_usecs = ktime_to_us(ktime_get_real());
|
||||
f_pTime->aulWallTimeUs[0] = total_usecs;
|
||||
f_pTime->aulWallTimeUs[1] = total_usecs >> 32;
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern,
|
||||
UINT32 f_ulLength)
|
||||
{
|
||||
memset(f_pAddress, f_ulPattern, f_ulLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource,
|
||||
UINT32 f_ulLength)
|
||||
{
|
||||
memcpy(f_pDestination, f_pSource, f_ulLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserCreateSerializeObject(
|
||||
tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
|
||||
{
|
||||
struct oct612x_context *context = f_pCreate->pProcessContext;
|
||||
struct mutex *lock = kzalloc(sizeof(*lock), GFP_KERNEL);
|
||||
if (!lock) {
|
||||
dev_err(context->dev, "Out of memory in %s.\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
mutex_init(lock);
|
||||
f_pCreate->ulSerialObjHndl = lock;
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDestroySerializeObject(
|
||||
tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
|
||||
{
|
||||
struct mutex *lock = f_pDestroy->ulSerialObjHndl;
|
||||
kfree(lock);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserSeizeSerializeObject(
|
||||
tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
|
||||
{
|
||||
struct mutex *lock = f_pSeize->ulSerialObjHndl;
|
||||
mutex_lock(lock);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserReleaseSerializeObject(
|
||||
tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
|
||||
{
|
||||
struct mutex *lock = f_pRelease->ulSerialObjHndl;
|
||||
mutex_unlock(lock);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
|
||||
{
|
||||
struct oct612x_context *context = f_pWriteParams->pProcessContext;
|
||||
#ifdef OCTASIC_DEBUG
|
||||
if (!context || !context->ops || !context->ops->write) {
|
||||
pr_debug("Invalid call to %s\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
#endif
|
||||
context->ops->write(context, f_pWriteParams->ulWriteAddress,
|
||||
f_pWriteParams->usWriteData);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
|
||||
{
|
||||
struct oct612x_context *context = f_pSmearParams->pProcessContext;
|
||||
#ifdef OCTASIC_DEBUG
|
||||
if (!context || !context->ops || !context->ops->write_smear) {
|
||||
pr_debug("Invalid call to %s\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
#endif
|
||||
context->ops->write_smear(context, f_pSmearParams->ulWriteAddress,
|
||||
f_pSmearParams->usWriteData,
|
||||
f_pSmearParams->ulWriteLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverWriteBurstApi(
|
||||
tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
|
||||
{
|
||||
struct oct612x_context *context = f_pBurstParams->pProcessContext;
|
||||
#ifdef OCTASIC_DEBUG
|
||||
if (!context || !context->ops || !context->ops->write_burst) {
|
||||
pr_debug("Invalid call to %s\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
#endif
|
||||
context->ops->write_burst(context, f_pBurstParams->ulWriteAddress,
|
||||
f_pBurstParams->pusWriteData,
|
||||
f_pBurstParams->ulWriteLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
|
||||
{
|
||||
struct oct612x_context *context = f_pReadParams->pProcessContext;
|
||||
#ifdef OCTASIC_DEBUG
|
||||
if (!context || !context->ops || !context->ops->read) {
|
||||
pr_debug("Invalid call to %s\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
#endif
|
||||
context->ops->read(context, f_pReadParams->ulReadAddress,
|
||||
f_pReadParams->pusReadData);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
|
||||
{
|
||||
struct oct612x_context *context = f_pBurstParams->pProcessContext;
|
||||
#ifdef OCTASIC_DEBUG
|
||||
if (!context || !context->ops || !context->ops->read_burst) {
|
||||
pr_debug("Invalid call to %s\n", __func__);
|
||||
return cOCT6100_ERR_BASE;
|
||||
}
|
||||
#endif
|
||||
context->ops->read_burst(context, f_pBurstParams->ulReadAddress,
|
||||
f_pBurstParams->pusReadData,
|
||||
f_pBurstParams->ulReadLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(Oct6100ChipOpen);
|
||||
EXPORT_SYMBOL(Oct6100ChipClose);
|
||||
EXPORT_SYMBOL(Oct6100ChipCloseDef);
|
||||
EXPORT_SYMBOL(Oct6100GetInstanceSize);
|
||||
EXPORT_SYMBOL(Oct6100GetInstanceSizeDef);
|
||||
EXPORT_SYMBOL(Oct6100ChipOpenDef);
|
||||
EXPORT_SYMBOL(Oct6100ChannelModify);
|
||||
EXPORT_SYMBOL(Oct6100ToneDetectionEnableDef);
|
||||
EXPORT_SYMBOL(Oct6100InterruptServiceRoutine);
|
||||
EXPORT_SYMBOL(Oct6100InterruptServiceRoutineDef);
|
||||
EXPORT_SYMBOL(Oct6100ApiGetCapacityPins);
|
||||
EXPORT_SYMBOL(Oct6100ToneDetectionEnable);
|
||||
EXPORT_SYMBOL(Oct6100EventGetToneDef);
|
||||
EXPORT_SYMBOL(Oct6100EventGetTone);
|
||||
EXPORT_SYMBOL(Oct6100ApiGetCapacityPinsDef);
|
||||
EXPORT_SYMBOL(Oct6100ChannelOpen);
|
||||
EXPORT_SYMBOL(Oct6100ChannelOpenDef);
|
||||
EXPORT_SYMBOL(Oct6100ChannelModifyDef);
|
||||
|
||||
static int __init oct612x_module_init(void)
|
||||
{
|
||||
/* This registration with dahdi.ko will fail since the span is not
|
||||
* defined, but it will make sure that this module is a dependency of
|
||||
* dahdi.ko, so that when it is being unloded, this module will be
|
||||
* unloaded as well. */
|
||||
dahdi_register_device(NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
module_init(oct612x_module_init);
|
||||
|
||||
static void __exit oct612x_module_cleanup(void)
|
||||
{
|
||||
/* Nothing to do */;
|
||||
}
|
||||
module_exit(oct612x_module_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Digium Incorporated <support@digium.com>");
|
||||
MODULE_DESCRIPTION("Octasic OCT6100 Hardware Echocan Library");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Octasic OCT6100 Interface
|
||||
*
|
||||
* Copyright (C) 2013 Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
#ifndef __OCT612X_H__
|
||||
#define __OCT612X_H__
|
||||
|
||||
#include <oct6100api/oct6100_api.h>
|
||||
|
||||
struct oct612x_context;
|
||||
|
||||
/**
|
||||
* struct oct612x_ops - Callbacks used by oct612x library to talk to part.
|
||||
*
|
||||
*/
|
||||
struct oct612x_ops {
|
||||
int (*write)(struct oct612x_context *context, u32 address, u16 value);
|
||||
int (*read)(struct oct612x_context *context, u32 address, u16 *value);
|
||||
int (*write_smear)(struct oct612x_context *context, u32 address,
|
||||
u16 value, size_t count);
|
||||
int (*write_burst)(struct oct612x_context *context, u32 address,
|
||||
const u16 *value, size_t count);
|
||||
int (*read_burst)(struct oct612x_context *context, u32 address,
|
||||
u16 *value, size_t count);
|
||||
};
|
||||
|
||||
struct oct612x_context {
|
||||
const struct oct612x_ops *ops;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#endif /* __OCT612X_H__ */
|
||||
1890
drivers/dahdi/pciradio.c
Normal file
1890
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 */
|
||||
|
||||
1543
drivers/dahdi/tor2.c
Normal file
1543
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);
|
||||
|
||||
@@ -33,8 +33,11 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/slab.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
#include <dahdi/user.h>
|
||||
@@ -376,9 +379,15 @@ static void update_channel_config(struct vpmadt032 *vpm, unsigned int channel,
|
||||
* the hardware can take some time while messages are sent to the VPMADT032
|
||||
* module and the driver waits for the responses.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void vpmadt032_bh(void *data)
|
||||
{
|
||||
struct vpmadt032 *vpm = data;
|
||||
#else
|
||||
static void vpmadt032_bh(struct work_struct *data)
|
||||
{
|
||||
struct vpmadt032 *vpm = container_of(data, struct vpmadt032, work);
|
||||
#endif
|
||||
struct change_order *order;
|
||||
|
||||
while ((order = get_next_order(vpm))) {
|
||||
@@ -504,7 +513,11 @@ vpmadt032_alloc(struct vpmadt032_options *options)
|
||||
sema_init(&vpm->sem, 1);
|
||||
vpm->curpage = 0x80;
|
||||
vpm->dspid = -1;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&vpm->work, vpmadt032_bh, vpm);
|
||||
#else
|
||||
INIT_WORK(&vpm->work, vpmadt032_bh);
|
||||
#endif
|
||||
|
||||
/* Do not use the global workqueue for processing these events. Some of
|
||||
* the operations can take 100s of ms, most of that time spent sleeping.
|
||||
|
||||
@@ -42,7 +42,10 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
|
||||
#include <linux/semaphore.h>
|
||||
#endif
|
||||
|
||||
#include "gpakenum.h"
|
||||
#include "adt_lec.h"
|
||||
|
||||
@@ -1000,7 +1000,6 @@ __vb_rx_demand_poll(struct voicebus *vb)
|
||||
__vb_setctl(vb, 0x0010, 0x00000000);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_VOICEBUS_TIMER
|
||||
static void
|
||||
__vb_enable_interrupts(struct voicebus *vb)
|
||||
{
|
||||
@@ -1009,7 +1008,6 @@ __vb_enable_interrupts(struct voicebus *vb)
|
||||
else
|
||||
__vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
__vb_disable_interrupts(struct voicebus *vb)
|
||||
@@ -1035,7 +1033,8 @@ static void start_packet_processing(struct voicebus *vb)
|
||||
clear_bit(VOICEBUS_STOP, &vb->flags);
|
||||
clear_bit(VOICEBUS_STOPPED, &vb->flags);
|
||||
#if defined(CONFIG_VOICEBUS_TIMER)
|
||||
mod_timer(&vb->timer, jiffies + HZ/1000);
|
||||
vb->timer.expires = jiffies + HZ/1000;
|
||||
add_timer(&vb->timer);
|
||||
#else
|
||||
/* Clear the interrupt status register. */
|
||||
__vb_setctl(vb, SR_CSR5, 0xffffffff);
|
||||
@@ -1197,8 +1196,11 @@ voicebus_release(struct voicebus *vb)
|
||||
#endif
|
||||
|
||||
/* Make sure the underrun_work isn't running or going to run. */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
flush_scheduled_work();
|
||||
#else
|
||||
cancel_work_sync(&vb->underrun_work);
|
||||
|
||||
#endif
|
||||
/* quiesce the hardware */
|
||||
voicebus_stop(vb);
|
||||
|
||||
@@ -1233,6 +1235,9 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
|
||||
struct list_head *buffers)
|
||||
{
|
||||
struct vbb *vbb;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
|
||||
struct vbb *n;
|
||||
#endif
|
||||
int i;
|
||||
LIST_HEAD(local);
|
||||
|
||||
@@ -1268,7 +1273,12 @@ vb_increase_latency(struct voicebus *vb, unsigned int increase,
|
||||
}
|
||||
|
||||
handle_transmit(vb, &local);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
|
||||
list_for_each_entry_safe(vbb, n, &local, entry)
|
||||
list_move_tail(&vbb->entry, buffers);
|
||||
#else
|
||||
list_splice_tail(&local, buffers);
|
||||
#endif
|
||||
|
||||
/* Set the new latency (but we want to ensure that there aren't any
|
||||
* printks to the console, so we don't call the function) */
|
||||
@@ -1622,10 +1632,16 @@ tx_error_exit:
|
||||
* @work: The work_struct used to queue this function.
|
||||
*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void handle_hardunderrun(void *data)
|
||||
{
|
||||
struct voicebus *vb = data;
|
||||
#else
|
||||
static void handle_hardunderrun(struct work_struct *work)
|
||||
{
|
||||
struct voicebus *vb = container_of(work, struct voicebus,
|
||||
underrun_work);
|
||||
#endif
|
||||
if (test_bit(VOICEBUS_STOP, &vb->flags) ||
|
||||
test_bit(VOICEBUS_STOPPED, &vb->flags))
|
||||
return;
|
||||
@@ -1660,7 +1676,11 @@ static void handle_hardunderrun(struct work_struct *work)
|
||||
* since it doesn't employ any locking on the voicebus interface.
|
||||
*/
|
||||
static irqreturn_t
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
vb_isr(int irq, void *dev_id, struct pt_regs *regs)
|
||||
#else
|
||||
vb_isr(int irq, void *dev_id)
|
||||
#endif
|
||||
{
|
||||
struct voicebus *vb = dev_id;
|
||||
unsigned long flags;
|
||||
@@ -1726,13 +1746,18 @@ vb_isr(int irq, void *dev_id)
|
||||
* the timer.
|
||||
*/
|
||||
static void
|
||||
vb_timer(TIMER_DATA_TYPE timer)
|
||||
vb_timer(unsigned long data)
|
||||
{
|
||||
unsigned long start = jiffies;
|
||||
struct voicebus *vb = from_timer(vb, timer, timer);
|
||||
struct voicebus *vb = (struct voicebus *)data;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
vb_isr(0, vb, 0);
|
||||
#else
|
||||
vb_isr(0, vb);
|
||||
#endif
|
||||
if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) {
|
||||
mod_timer(&vb->timer, start + HZ/1000);
|
||||
vb->timer.expires = start + HZ/1000;
|
||||
add_timer(&vb->timer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1775,10 +1800,16 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
|
||||
INIT_LIST_HEAD(&vb->free_rx);
|
||||
|
||||
#if defined(CONFIG_VOICEBUS_TIMER)
|
||||
timer_setup(&vb->timer, vb_timer, 0);
|
||||
init_timer(&vb->timer);
|
||||
vb->timer.function = vb_timer;
|
||||
vb->timer.data = (unsigned long)vb;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&vb->underrun_work, handle_hardunderrun, vb);
|
||||
#else
|
||||
INIT_WORK(&vb->underrun_work, handle_hardunderrun);
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
Configure the hardware / kernel module interfaces.
|
||||
@@ -1854,7 +1885,7 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
|
||||
goto cleanup;
|
||||
|
||||
#if !defined(CONFIG_VOICEBUS_TIMER)
|
||||
retval = request_irq(vb->pdev->irq, vb_isr, IRQF_SHARED,
|
||||
retval = request_irq(vb->pdev->irq, vb_isr, DAHDI_IRQ_SHARED,
|
||||
board_name, vb);
|
||||
if (retval) {
|
||||
dev_warn(&vb->pdev->dev, "Failed to request interrupt line.\n");
|
||||
|
||||
@@ -64,11 +64,7 @@
|
||||
* platform does not support it.
|
||||
*
|
||||
*/
|
||||
#ifdef CONFIG_VOICEBUS_DISABLE_ASPM
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
|
||||
#include <linux/pci-aspm.h>
|
||||
#endif
|
||||
#endif
|
||||
#undef CONFIG_VOICEBUS_DISABLE_ASPM
|
||||
|
||||
/* Define this to use a FIFO for the software echocan reference.
|
||||
* (experimental) */
|
||||
@@ -177,7 +173,9 @@ struct voicebus {
|
||||
struct sk_buff_head captured_packets;
|
||||
struct net_device *netdev;
|
||||
struct net_device_stats net_stats;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||
struct napi_struct napi;
|
||||
#endif
|
||||
atomic_t tx_seqnum;
|
||||
atomic_t rx_seqnum;
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
@@ -104,6 +103,26 @@ static int vb_net_receive(struct voicebus *vb, int max)
|
||||
return count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
static int vb_net_poll(struct net_device *netdev, int *budget)
|
||||
{
|
||||
struct voicebus *vb = voicebus_from_netdev(netdev);
|
||||
int count = 0;
|
||||
int quota = min(netdev->quota, *budget);
|
||||
|
||||
count = vb_net_receive(vb, quota);
|
||||
|
||||
*budget -= count;
|
||||
netdev->quota -= count;
|
||||
|
||||
if (!skb_queue_len(&vb->captured_packets)) {
|
||||
netif_rx_complete(netdev);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int vb_net_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct voicebus *vb = container_of(napi, struct voicebus, napi);
|
||||
@@ -122,6 +141,7 @@ static int vb_net_poll(struct napi_struct *napi, int budget)
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vb_net_set_multi(struct net_device *netdev)
|
||||
{
|
||||
@@ -134,7 +154,11 @@ static int vb_net_up(struct net_device *netdev)
|
||||
{
|
||||
struct voicebus *vb = voicebus_from_netdev(netdev);
|
||||
dev_dbg(&vb->pdev->dev, "%s\n", __func__);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
netif_poll_enable(netdev);
|
||||
#else
|
||||
napi_enable(&vb->napi);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -142,7 +166,11 @@ static int vb_net_down(struct net_device *netdev)
|
||||
{
|
||||
struct voicebus *vb = voicebus_from_netdev(netdev);
|
||||
dev_dbg(&vb->pdev->dev, "%s\n", __func__);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
netif_poll_disable(netdev);
|
||||
#else
|
||||
napi_disable(&vb->napi);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -178,13 +206,7 @@ int vb_net_register(struct voicebus *vb, const char *board_name)
|
||||
struct voicebus_netdev_priv *priv;
|
||||
const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
|
||||
netdev = alloc_netdev(sizeof(*priv), board_name,
|
||||
NET_NAME_UNKNOWN, ether_setup);
|
||||
#else
|
||||
netdev = alloc_netdev(sizeof(*priv), board_name, ether_setup);
|
||||
#endif
|
||||
|
||||
if (!netdev)
|
||||
return -ENOMEM;
|
||||
priv = netdev_priv(netdev);
|
||||
@@ -202,7 +224,12 @@ int vb_net_register(struct voicebus *vb, const char *board_name)
|
||||
|
||||
netdev->promiscuity = 0;
|
||||
netdev->flags |= IFF_NOARP;
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
netdev->poll = vb_net_poll;
|
||||
netdev->weight = 64;
|
||||
# else
|
||||
netif_napi_add(netdev, &vb->napi, vb_net_poll, 64);
|
||||
# endif
|
||||
|
||||
skb_queue_head_init(&vb->captured_packets);
|
||||
res = register_netdev(netdev);
|
||||
@@ -325,7 +352,9 @@ void vb_net_capture_vbb(struct voicebus *vb, const void *vbb, const int tx,
|
||||
return;
|
||||
|
||||
skb_queue_tail(&vb->captured_packets, skb);
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
netif_rx_schedule(netdev);
|
||||
# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
|
||||
netif_rx_schedule(netdev, &vb->napi);
|
||||
# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
|
||||
netif_rx_schedule(&vb->napi);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "voicebus/vpmoct.h"
|
||||
#include "linux/firmware.h"
|
||||
@@ -393,10 +392,16 @@ struct vpmoct_load_work {
|
||||
* long running firmware load.
|
||||
*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void vpmoct_load_complete_fn(void *data)
|
||||
{
|
||||
struct vpmoct_load_work *work = data;
|
||||
#else
|
||||
static void vpmoct_load_complete_fn(struct work_struct *data)
|
||||
{
|
||||
struct vpmoct_load_work *work =
|
||||
container_of(data, struct vpmoct_load_work, work);
|
||||
#endif
|
||||
/* Do not touch work->vpm after calling load complete. It may have
|
||||
* been freed in the function by the board driver. */
|
||||
work->load_complete(work->vpm->dev, work->operational);
|
||||
@@ -415,7 +420,11 @@ vpmoct_load_complete(struct vpmoct_load_work *work, bool operational)
|
||||
{
|
||||
work->operational = operational;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&work->work, vpmoct_load_complete_fn, work);
|
||||
#else
|
||||
INIT_WORK(&work->work, vpmoct_load_complete_fn);
|
||||
#endif
|
||||
schedule_work(&work->work);
|
||||
}
|
||||
|
||||
@@ -480,10 +489,16 @@ static void vpmoct_release_firmware(const struct firmware *fw)
|
||||
* @vpm: The VPMOCT032 module to check / load.
|
||||
*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void vpmoct_load_flash(void *data)
|
||||
{
|
||||
struct vpmoct_load_work *work = data;
|
||||
#else
|
||||
static void vpmoct_load_flash(struct work_struct *data)
|
||||
{
|
||||
struct vpmoct_load_work *work =
|
||||
container_of(data, struct vpmoct_load_work, work);
|
||||
#endif
|
||||
int res;
|
||||
struct vpmoct *const vpm = work->vpm;
|
||||
const struct firmware *fw;
|
||||
@@ -670,7 +685,11 @@ int vpmoct_init(struct vpmoct *vpm, load_complete_func_t load_complete)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&work->work, vpmoct_load_flash, work);
|
||||
#else
|
||||
INIT_WORK(&work->work, vpmoct_load_flash);
|
||||
#endif
|
||||
|
||||
work->vpm = vpm;
|
||||
work->load_complete = load_complete;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -248,8 +248,8 @@
|
||||
#define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */
|
||||
#define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */
|
||||
#define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */
|
||||
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data from STIO2 */
|
||||
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data from STIO1 */
|
||||
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data comes from STIO1 */
|
||||
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data comes from STIO2 */
|
||||
|
||||
#define V_CH_SNUM_SHIFT (1)
|
||||
#define V_CH_SNUM_MASK (31 << 1)
|
||||
@@ -367,16 +367,6 @@
|
||||
#define V_B2_RX_EN (1 << 1) /* 1=enable B2 RX */
|
||||
#define V_ST_TRI (1 << 6) /* 1=tristate S/T output buffer */
|
||||
|
||||
/* User Flash Manager */
|
||||
#define UFM_PROGRAM (1<<0)
|
||||
#define UFM_ERASE (1<<1)
|
||||
#define UFM_DRSHIFT (1<<2)
|
||||
#define UFM_DRDIN (1<<3)
|
||||
#define UFM_DRCLK (1<<4)
|
||||
#define UFM_ARSHIFT (1<<5)
|
||||
#define UFM_ARDIN (1<<6)
|
||||
#define UFM_ARCLK (1<<7)
|
||||
|
||||
#define NUM_REGS 0xff
|
||||
#define NUM_PCI 12
|
||||
|
||||
@@ -395,8 +385,7 @@
|
||||
|
||||
struct b4xxp_span {
|
||||
struct b4xxp *parent;
|
||||
int port; /* virtual port */
|
||||
int phy_port; /* physical port */
|
||||
int port; /* which S/T port this span belongs to */
|
||||
|
||||
unsigned char writechunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
|
||||
unsigned char readchunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
|
||||
@@ -437,9 +426,7 @@ enum cards_ids { /* Cards ==> Brand & Model */
|
||||
BN4S0, /* Beronet BN4S0 */
|
||||
BN8S0, /* BeroNet BN8S0 */
|
||||
BSWYX_SX2, /* Swyx 4xS0 SX2 QuadBri */
|
||||
QUADBRI_EVAL, /* HFC-4S CCD Eval. Board */
|
||||
B430P, /* Digium B430P */
|
||||
B230P /* Digium B230P */
|
||||
QUADBRI_EVAL /* HFC-4S CCD Eval. Board */
|
||||
};
|
||||
|
||||
/* This structure exists one per card */
|
||||
|
||||
1093
drivers/dahdi/wcfxo.c
Normal file
1093
drivers/dahdi/wcfxo.c
Normal file
File diff suppressed because it is too large
Load Diff
1449
drivers/dahdi/wct1xxp.c
Normal file
1449
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,7 +14,7 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
wct4xxp-objs := base.o vpm450m.o
|
||||
wct4xxp-objs := base.o vpm450m.o ../oct612x/lib.a
|
||||
|
||||
ifneq ($(HOTPLUG_FIRMWARE),yes)
|
||||
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <dahdi/kernel.h>
|
||||
@@ -48,6 +47,16 @@
|
||||
#include "wct4xxp.h"
|
||||
#include "vpm450m.h"
|
||||
|
||||
/* Work queues are a way to better distribute load on SMP systems */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
|
||||
/*
|
||||
* Work queues can significantly improve performance and scalability
|
||||
* on multi-processor machines, but requires bypassing some kernel
|
||||
* API's, so it's not guaranteed to be compatible with all kernels.
|
||||
*/
|
||||
/* #define ENABLE_WORKQUEUES */
|
||||
#endif
|
||||
|
||||
/* Support first generation cards? */
|
||||
#define SUPPORT_GEN1
|
||||
|
||||
@@ -69,6 +78,88 @@
|
||||
/* Maximum latency to be used with Gen 5 */
|
||||
#define GEN5_MAX_LATENCY 127
|
||||
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
#include <linux/cpu.h>
|
||||
|
||||
/* XXX UGLY!!!! XXX We have to access the direct structures of the workqueue which
|
||||
are only defined within workqueue.c because they don't give us a routine to allow us
|
||||
to nail a work to a particular thread of the CPU. Nailing to threads gives us substantially
|
||||
higher scalability in multi-CPU environments though! */
|
||||
|
||||
/*
|
||||
* The per-CPU workqueue (if single thread, we always use cpu 0's).
|
||||
*
|
||||
* The sequence counters are for flush_scheduled_work(). It wants to wait
|
||||
* until until all currently-scheduled works are completed, but it doesn't
|
||||
* want to be livelocked by new, incoming ones. So it waits until
|
||||
* remove_sequence is >= the insert_sequence which pertained when
|
||||
* flush_scheduled_work() was called.
|
||||
*/
|
||||
|
||||
struct cpu_workqueue_struct {
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
long remove_sequence; /* Least-recently added (next to run) */
|
||||
long insert_sequence; /* Next to add */
|
||||
|
||||
struct list_head worklist;
|
||||
wait_queue_head_t more_work;
|
||||
wait_queue_head_t work_done;
|
||||
|
||||
struct workqueue_struct *wq;
|
||||
task_t *thread;
|
||||
|
||||
int run_depth; /* Detect run_workqueue() recursion depth */
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/*
|
||||
* The externally visible workqueue abstraction is an array of
|
||||
* per-CPU workqueues:
|
||||
*/
|
||||
struct workqueue_struct {
|
||||
/* TODO: Find out exactly where the API changed */
|
||||
struct cpu_workqueue_struct *cpu_wq;
|
||||
const char *name;
|
||||
struct list_head list; /* Empty if single thread */
|
||||
};
|
||||
|
||||
/* Preempt must be disabled. */
|
||||
static void __t4_queue_work(struct cpu_workqueue_struct *cwq,
|
||||
struct work_struct *work)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cwq->lock, flags);
|
||||
work->wq_data = cwq;
|
||||
list_add_tail(&work->entry, &cwq->worklist);
|
||||
cwq->insert_sequence++;
|
||||
wake_up(&cwq->more_work);
|
||||
spin_unlock_irqrestore(&cwq->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue work on a workqueue. Return non-zero if it was successfully
|
||||
* added.
|
||||
*
|
||||
* We queue the work to the CPU it was submitted, but there is no
|
||||
* guarantee that it will be processed by that CPU.
|
||||
*/
|
||||
static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu)
|
||||
{
|
||||
int ret = 0;
|
||||
get_cpu();
|
||||
if (!test_and_set_bit(0, &work->pending)) {
|
||||
BUG_ON(!list_empty(&work->entry));
|
||||
__t4_queue_work(wq->cpu_wq + cpu, work);
|
||||
ret = 1;
|
||||
}
|
||||
put_cpu();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define CONFIG_FORCE_EXTENDED_RESET to allow the qfalc framer extra time
|
||||
* to reset itself upon hardware initialization. This exits for rare
|
||||
@@ -87,18 +178,12 @@
|
||||
*/
|
||||
/* #define CONFIG_WCT4XXP_DISABLE_ASPM */
|
||||
|
||||
#ifdef CONFIG_WCT4XXP_DISABLE_ASPM
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
|
||||
#include <linux/pci-aspm.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FORCE_EXTENDED_RESET) && defined(CONFIG_NOEXTENDED_RESET)
|
||||
#error "You cannot define both CONFIG_FORCE_EXTENDED_RESET and " \
|
||||
"CONFIG_NOEXTENDED_RESET."
|
||||
#endif
|
||||
|
||||
int debug = 0;
|
||||
static int debug=0;
|
||||
static int timingcable = 0;
|
||||
static int t1e1override = -1; /* deprecated */
|
||||
static char *default_linemode = "auto";
|
||||
@@ -214,7 +299,6 @@ struct t4_span {
|
||||
unsigned long alarmcheck_time;
|
||||
int spanflags;
|
||||
int syncpos;
|
||||
|
||||
#ifdef SUPPORT_GEN1
|
||||
int e1check; /* E1 check */
|
||||
#endif
|
||||
@@ -238,6 +322,9 @@ struct t4_span {
|
||||
unsigned long dtmfmask;
|
||||
unsigned long dtmfmutemask;
|
||||
#endif
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
struct work_struct swork;
|
||||
#endif
|
||||
struct dahdi_chan *chans[32]; /* Individual channels */
|
||||
struct dahdi_echocan_state *ec[32]; /* Echocan state for each channel */
|
||||
};
|
||||
@@ -258,7 +345,6 @@ struct t4 {
|
||||
int irq; /* IRQ used by device */
|
||||
int order; /* Order */
|
||||
const struct devtype *devtype;
|
||||
unsigned int reset_required:1; /* If reset needed in serial_setup */
|
||||
unsigned int falc31:1; /* are we falc v3.1 (atomic not necessary) */
|
||||
unsigned int t1e1:8; /* T1 / E1 select pins */
|
||||
int ledreg; /* LED Register */
|
||||
@@ -270,6 +356,10 @@ struct t4 {
|
||||
int spansstarted; /* number of spans started */
|
||||
u32 *writechunk; /* Double-word aligned write memory */
|
||||
u32 *readchunk; /* Double-word aligned read memory */
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
atomic_t worklist;
|
||||
struct workqueue_struct *workq;
|
||||
#endif
|
||||
int last0; /* for detecting double-missed IRQ */
|
||||
|
||||
/* DMA related fields */
|
||||
@@ -278,14 +368,9 @@ struct t4 {
|
||||
dma_addr_t writedma;
|
||||
void __iomem *membase; /* Base address of card */
|
||||
|
||||
#define T4_CHECK_VPM 0
|
||||
#define T4_LOADING_FW 1
|
||||
#define T4_STOP_DMA 2
|
||||
#define T4_CHECK_TIMING 3
|
||||
#define T4_CHANGE_LATENCY 4
|
||||
#define T4_IGNORE_LATENCY 5
|
||||
/* Flags for our bottom half */
|
||||
unsigned long checkflag;
|
||||
struct work_struct bh_work;
|
||||
struct tasklet_struct t4_tlet;
|
||||
/* Latency related additions */
|
||||
unsigned char rxident;
|
||||
unsigned char lastindex;
|
||||
@@ -420,7 +505,7 @@ static void t4_check_sigbits(struct t4 *wc, int span);
|
||||
#define FMR5_EIBR (1 << 6) /* Internal Bit Robbing Access */
|
||||
#define DEC_T 0x60 /* Diable Error Counter */
|
||||
#define IERR_T 0x1B /* Single Bit Defect Insertion Register */
|
||||
#define IBV (1 << 0) /* Bipolar violation */
|
||||
#define IBV 0 /* Bipolar violation */
|
||||
#define IPE (1 << 1) /* PRBS defect */
|
||||
#define ICASE (1 << 2) /* CAS defect */
|
||||
#define ICRCE (1 << 3) /* CRC defect */
|
||||
@@ -461,6 +546,8 @@ static void t4_check_sigbits(struct t4 *wc, int span);
|
||||
|
||||
#define MAX_T4_CARDS 64
|
||||
|
||||
static void t4_isr_bh(unsigned long data);
|
||||
|
||||
static struct t4 *cards[MAX_T4_CARDS];
|
||||
|
||||
struct t8_firm_header {
|
||||
@@ -1032,11 +1119,16 @@ static int t4_echocan_create(struct dahdi_chan *chan,
|
||||
struct t4 *wc = chan->pvt;
|
||||
struct t4_span *tspan = container_of(chan->span, struct t4_span, span);
|
||||
int channel;
|
||||
const struct dahdi_echocan_ops *ops;
|
||||
const struct dahdi_echocan_features *features;
|
||||
const bool alaw = (chan->span->deflaw == 2);
|
||||
|
||||
if (!vpmsupport || !wc->vpm)
|
||||
return -ENODEV;
|
||||
|
||||
ops = &vpm_ec_ops;
|
||||
features = &vpm_ec_features;
|
||||
|
||||
if (ecp->param_count > 0) {
|
||||
dev_warn(&wc->dev->dev, "%s echo canceller does not support "
|
||||
"parameters; failing request\n",
|
||||
@@ -1045,8 +1137,8 @@ static int t4_echocan_create(struct dahdi_chan *chan,
|
||||
}
|
||||
|
||||
*ec = tspan->ec[chan->chanpos - 1];
|
||||
(*ec)->ops = &vpm_ec_ops;
|
||||
(*ec)->features = vpm_ec_features;
|
||||
(*ec)->ops = ops;
|
||||
(*ec)->features = *features;
|
||||
|
||||
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
|
||||
|
||||
@@ -1620,11 +1712,8 @@ _t4_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
|
||||
if (lc->sync < 0)
|
||||
lc->sync = 0;
|
||||
if (lc->sync > wc->numspans) {
|
||||
dev_warn(&wc->dev->dev, "WARNING: Cannot set priority on span %d to %d. Please set to a number between 1 and %d\n",
|
||||
span->spanno, lc->sync, wc->numspans);
|
||||
if (lc->sync > wc->numspans)
|
||||
lc->sync = 0;
|
||||
}
|
||||
|
||||
/* remove this span number from the current sync sources, if there */
|
||||
for(i = 0; i < wc->numspans; i++) {
|
||||
@@ -1739,6 +1828,16 @@ t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t4_open(struct dahdi_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t4_close(struct dahdi_chan *chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_span_devicetype(struct t4 *wc)
|
||||
{
|
||||
#ifdef VPM_SUPPORT
|
||||
@@ -1791,33 +1890,6 @@ static void setup_chunks(struct t4 *wc, int which)
|
||||
}
|
||||
}
|
||||
|
||||
static int __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags,
|
||||
bool first_time);
|
||||
static int __t4_hardware_init_2(struct t4 *wc, bool first_time);
|
||||
|
||||
static int t4_hardware_stop(struct t4 *wc);
|
||||
|
||||
static void t4_framer_reset(struct t4 *wc)
|
||||
{
|
||||
const bool first_time = false;
|
||||
bool have_vpm = wc->vpm != NULL;
|
||||
if (have_vpm) {
|
||||
release_vpm450m(wc->vpm);
|
||||
wc->vpm = NULL;
|
||||
}
|
||||
t4_hardware_stop(wc);
|
||||
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
|
||||
__t4_hardware_init_1(wc, wc->devtype->flags, first_time);
|
||||
__t4_hardware_init_2(wc, first_time);
|
||||
if (have_vpm) {
|
||||
t4_vpm_init(wc);
|
||||
wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0;
|
||||
t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
|
||||
}
|
||||
setup_chunks(wc, 0);
|
||||
wc->lastindex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_serial_setup - Setup serial parameters and system interface.
|
||||
* @wc: The card to configure.
|
||||
@@ -1827,7 +1899,6 @@ static void t4_serial_setup(struct t4 *wc)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int unit;
|
||||
bool reset_required = false;
|
||||
|
||||
if (debug) {
|
||||
dev_info(&wc->dev->dev,
|
||||
@@ -1835,14 +1906,6 @@ static void t4_serial_setup(struct t4 *wc)
|
||||
wc->numspans);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
reset_required = wc->reset_required > 0;
|
||||
wc->reset_required = 0;
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
|
||||
if (reset_required)
|
||||
t4_framer_reset(wc);
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
/* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from
|
||||
* channel 0 */
|
||||
@@ -1993,7 +2056,6 @@ static void t4_span_assigned(struct dahdi_span *span)
|
||||
struct t4 *wc = tspan->owner;
|
||||
struct dahdi_span *pos;
|
||||
unsigned int unassigned_spans = 0;
|
||||
unsigned long flags;
|
||||
|
||||
/* We use this to make sure all the spans are assigned before
|
||||
* running the serial setup. */
|
||||
@@ -2002,22 +2064,14 @@ static void t4_span_assigned(struct dahdi_span *span)
|
||||
++unassigned_spans;
|
||||
}
|
||||
|
||||
if (0 == unassigned_spans) {
|
||||
if (0 == unassigned_spans)
|
||||
t4_serial_setup(wc);
|
||||
|
||||
set_bit(T4_CHECK_TIMING, &wc->checkflag);
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_wc(struct t4 *wc)
|
||||
{
|
||||
unsigned int x, y;
|
||||
|
||||
flush_scheduled_work();
|
||||
|
||||
for (x = 0; x < ARRAY_SIZE(wc->tspans); x++) {
|
||||
if (!wc->tspans[x])
|
||||
continue;
|
||||
@@ -2173,7 +2227,6 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
enum linemode mode;
|
||||
const char *old_name;
|
||||
static DEFINE_MUTEX(linemode_lock);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name,
|
||||
dahdi_spantype2str(linemode));
|
||||
@@ -2181,10 +2234,6 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
if (span->spantype == linemode)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
wc->reset_required = 1;
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
|
||||
/* Do not allow the t1e1 member to be changed by multiple threads. */
|
||||
mutex_lock(&linemode_lock);
|
||||
old_name = dahdi_spantype2str(span->spantype);
|
||||
@@ -2231,6 +2280,8 @@ static const struct dahdi_span_ops t4_gen1_span_ops = {
|
||||
.shutdown = t4_shutdown,
|
||||
.rbsbits = t4_rbsbits,
|
||||
.maint = t4_maint,
|
||||
.open = t4_open,
|
||||
.close = t4_close,
|
||||
.ioctl = t4_ioctl,
|
||||
.hdlc_hard_xmit = t4_hdlc_hard_xmit,
|
||||
.assigned = t4_span_assigned,
|
||||
@@ -2245,6 +2296,8 @@ static const struct dahdi_span_ops t4_gen2_span_ops = {
|
||||
.shutdown = t4_shutdown,
|
||||
.rbsbits = t4_rbsbits,
|
||||
.maint = t4_maint,
|
||||
.open = t4_open,
|
||||
.close = t4_close,
|
||||
.ioctl = t4_ioctl,
|
||||
.hdlc_hard_xmit = t4_hdlc_hard_xmit,
|
||||
.dacs = t4_dacs,
|
||||
@@ -2617,7 +2670,7 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev
|
||||
if (lineconfig & DAHDI_CONFIG_AMI) {
|
||||
line = "AMI";
|
||||
/* workaround for errata #2 in ES v3 09-10-16 */
|
||||
fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0;
|
||||
fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
|
||||
} else {
|
||||
line = "B8ZS";
|
||||
fmr0 = 0xf0;
|
||||
@@ -2716,7 +2769,7 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
|
||||
if (lineconfig & DAHDI_CONFIG_AMI) {
|
||||
line = "AMI";
|
||||
/* workaround for errata #2 in ES v3 09-10-16 */
|
||||
fmr0 = (is_octal(wc) || wc->falc31) ? 0xb0 : 0xa0;
|
||||
fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
|
||||
} else {
|
||||
line = "HDB3";
|
||||
fmr0 = 0xf0;
|
||||
@@ -2777,10 +2830,6 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
|
||||
__t4_framer_out(wc, unit, 0x17, 0x04 | imr3extra); /* IMR3: AIS */
|
||||
__t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */
|
||||
|
||||
__t4_framer_out(wc, unit, 0x2f, 0x00);
|
||||
__t4_framer_out(wc, unit, 0x30, 0x00);
|
||||
__t4_framer_out(wc, unit, 0x31, 0x00);
|
||||
|
||||
dev_info(&wc->dev->dev, "TE%dXXP: Span %d configured for %s/%s%s\n",
|
||||
wc->numspans, unit + 1, framing, line, crc4);
|
||||
}
|
||||
@@ -3102,6 +3151,19 @@ static inline void __transmit_span(struct t4_span *ts)
|
||||
_dahdi_transmit(&ts->span);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
static void workq_handlespan(void *data)
|
||||
{
|
||||
struct t4_span *ts = data;
|
||||
struct t4 *wc = ts->owner;
|
||||
|
||||
__receive_span(ts);
|
||||
__transmit_span(ts);
|
||||
atomic_dec(&wc->worklist);
|
||||
if (!atomic_read(&wc->worklist))
|
||||
t4_pci_out(wc, WC_INTR, 0);
|
||||
}
|
||||
#else
|
||||
static void t4_prep_gen2(struct t4 *wc)
|
||||
{
|
||||
int x;
|
||||
@@ -3113,6 +3175,7 @@ static void t4_prep_gen2(struct t4 *wc)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef SUPPORT_GEN1
|
||||
static void t4_transmitprep(struct t4 *wc, int irq)
|
||||
{
|
||||
@@ -3189,6 +3252,8 @@ static void t4_check_sigbits(struct t4 *wc, int span)
|
||||
dev_notice(&wc->dev->dev, "Checking sigbits on span %d\n",
|
||||
span + 1);
|
||||
|
||||
if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
|
||||
return;
|
||||
if (E1 == ts->linemode) {
|
||||
for (i = 0; i < 15; i++) {
|
||||
a = t4_framer_in(wc, span, 0x71 + i);
|
||||
@@ -3578,7 +3643,6 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
struct t4_span *ts = wc->tspans[span];
|
||||
struct dahdi_chan *sigchan;
|
||||
unsigned long flags;
|
||||
bool recheck_sigbits = false;
|
||||
|
||||
|
||||
/* 1st gen cards isn't used interrupts */
|
||||
@@ -3604,8 +3668,6 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
ts->span.count.ebit += __t4_framer_in(wc, span, EBCL_T);
|
||||
ts->span.count.be += __t4_framer_in(wc, span, BECL_T);
|
||||
ts->span.count.prbs = __t4_framer_in(wc, span, FRS1_T);
|
||||
if (DAHDI_RXSIG_INITIAL == ts->span.chans[0]->rxhooksig)
|
||||
recheck_sigbits = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
|
||||
@@ -3614,7 +3676,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
ts->span.count.errsec += 1;
|
||||
}
|
||||
|
||||
if (isr0 & 0x08 || recheck_sigbits)
|
||||
if (isr0)
|
||||
t4_check_sigbits(wc, span);
|
||||
|
||||
if (E1 == ts->linemode) {
|
||||
@@ -3837,7 +3899,7 @@ static irqreturn_t _t4_interrupt(int irq, void *dev_id)
|
||||
return IRQ_RETVAL(1);
|
||||
}
|
||||
|
||||
static irqreturn_t t4_interrupt(int irq, void *dev_id)
|
||||
DAHDI_IRQ_HANDLER(t4_interrupt)
|
||||
{
|
||||
irqreturn_t ret;
|
||||
unsigned long flags;
|
||||
@@ -3941,9 +4003,9 @@ static void t4_increase_latency(struct t4 *wc, int newlatency)
|
||||
|
||||
}
|
||||
|
||||
static void t4_work_func(struct work_struct *work)
|
||||
static void t4_isr_bh(unsigned long data)
|
||||
{
|
||||
struct t4 *wc = container_of(work, struct t4, bh_work);
|
||||
struct t4 *wc = (struct t4 *)data;
|
||||
|
||||
if (test_bit(T4_CHANGE_LATENCY, &wc->checkflag)) {
|
||||
if (wc->needed_latency != wc->numbufs) {
|
||||
@@ -3990,6 +4052,10 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
__t4_pci_out(wc, WC_INTR, status & 0x00000008);
|
||||
#endif
|
||||
|
||||
if (unlikely(!wc->spansstarted)) {
|
||||
dev_info(&wc->dev->dev, "Not prepped yet!\n");
|
||||
return IRQ_NONE;
|
||||
@@ -4052,6 +4118,28 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
|
||||
#endif
|
||||
|
||||
if (likely(status & 0x2)) {
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
int cpus = num_online_cpus();
|
||||
atomic_set(&wc->worklist, wc->numspans);
|
||||
if (wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)
|
||||
t4_queue_work(wc->workq, &wc->tspans[0]->swork, 0);
|
||||
else
|
||||
atomic_dec(&wc->worklist);
|
||||
if (wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)
|
||||
t4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus);
|
||||
else
|
||||
atomic_dec(&wc->worklist);
|
||||
if (wc->numspans == 4) {
|
||||
if (wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)
|
||||
t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus);
|
||||
else
|
||||
atomic_dec(&wc->worklist);
|
||||
if (wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)
|
||||
t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus);
|
||||
else
|
||||
atomic_dec(&wc->worklist);
|
||||
}
|
||||
#else
|
||||
unsigned int reg5 = __t4_pci_in(wc, 5);
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -4071,6 +4159,7 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
|
||||
t4_prep_gen2(wc);
|
||||
}
|
||||
|
||||
#endif
|
||||
t4_do_counters(wc);
|
||||
spin_lock(&wc->reglock);
|
||||
__handle_leds(wc);
|
||||
@@ -4123,13 +4212,16 @@ static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
|
||||
|
||||
out:
|
||||
if (unlikely(test_bit(T4_CHANGE_LATENCY, &wc->checkflag) || test_bit(T4_CHECK_VPM, &wc->checkflag)))
|
||||
schedule_work(&wc->bh_work);
|
||||
tasklet_schedule(&wc->t4_tlet);
|
||||
|
||||
#ifndef ENABLE_WORKQUEUES
|
||||
__t4_pci_out(wc, WC_INTR, 0);
|
||||
#endif
|
||||
|
||||
return IRQ_RETVAL(1);
|
||||
}
|
||||
|
||||
static irqreturn_t t4_interrupt_gen2(int irq, void *dev_id)
|
||||
DAHDI_IRQ_HANDLER(t4_interrupt_gen2)
|
||||
{
|
||||
irqreturn_t ret;
|
||||
unsigned long flags;
|
||||
@@ -4214,7 +4306,7 @@ static void t4_vpm_init(struct t4 *wc)
|
||||
laws[x] = 1;
|
||||
}
|
||||
|
||||
vpm_capacity = get_vpm450m_capacity(&wc->dev->dev);
|
||||
vpm_capacity = get_vpm450m_capacity(wc);
|
||||
if (vpm_capacity != wc->numspans * 32) {
|
||||
dev_info(&wc->dev->dev, "Disabling VPMOCT%03d. TE%dXXP"\
|
||||
" requires a VPMOCT%03d", vpm_capacity,
|
||||
@@ -4286,8 +4378,7 @@ static void t4_vpm_init(struct t4 *wc)
|
||||
return;
|
||||
}
|
||||
|
||||
wc->vpm = init_vpm450m(&wc->dev->dev, laws, wc->numspans, firmware);
|
||||
if (!wc->vpm) {
|
||||
if (!(wc->vpm = init_vpm450m(wc, laws, wc->numspans, firmware))) {
|
||||
dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n");
|
||||
if (firmware != &embedded_firmware)
|
||||
release_firmware(firmware);
|
||||
@@ -4774,23 +4865,25 @@ cleanup:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
|
||||
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
|
||||
{
|
||||
unsigned int version;
|
||||
int res;
|
||||
|
||||
version = t4_pci_in(wc, WC_VERSION);
|
||||
if (is_octal(wc) && first_time) {
|
||||
if (is_octal(wc)) {
|
||||
dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n",
|
||||
(version & 0xf00) >> 8,
|
||||
version & 0xff);
|
||||
} else if (first_time) {
|
||||
} else {
|
||||
dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version);
|
||||
}
|
||||
if (debug) {
|
||||
dev_info(&wc->dev->dev, "Burst Mode: %s\n",
|
||||
(!(cardflags & FLAG_BURST) && noburst) ? "Off" : "On");
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
dev_info(&wc->dev->dev, "Work Queues: Enabled\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check the field updatable firmware for the wcte820 */
|
||||
@@ -4830,33 +4923,30 @@ __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
|
||||
t4_pci_out(wc, WC_INTR, 0x00000000);
|
||||
|
||||
/* Read T1/E1 status */
|
||||
if (first_time) {
|
||||
if (!strcasecmp("auto", default_linemode)) {
|
||||
if (-1 == t1e1override) {
|
||||
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) &
|
||||
0x0f00) >> 8);
|
||||
wc->t1e1 &= 0xf;
|
||||
if (is_octal(wc)) {
|
||||
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
|
||||
0x0f00) >> 4;
|
||||
}
|
||||
} else {
|
||||
dev_warn(&wc->dev->dev,
|
||||
"'t1e1override' is deprecated. Please use 'default_linemode'.\n");
|
||||
wc->t1e1 = t1e1override & 0xf;
|
||||
if (!strcasecmp("auto", default_linemode)) {
|
||||
if (-1 == t1e1override) {
|
||||
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8);
|
||||
wc->t1e1 &= 0xf;
|
||||
if (is_octal(wc)) {
|
||||
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
|
||||
0x0f00) >> 4;
|
||||
}
|
||||
} else if (!strcasecmp("t1", default_linemode)) {
|
||||
wc->t1e1 = 0;
|
||||
} else if (!strcasecmp("e1", default_linemode)) {
|
||||
wc->t1e1 = 0xff;
|
||||
} else if (!strcasecmp("j1", default_linemode)) {
|
||||
wc->t1e1 = 0;
|
||||
j1mode = 1;
|
||||
} else {
|
||||
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
|
||||
default_linemode);
|
||||
wc->t1e1 = 0;
|
||||
dev_warn(&wc->dev->dev, "'t1e1override' is deprecated. "
|
||||
"Please use 'default_linemode'.\n");
|
||||
wc->t1e1 = t1e1override & 0xf;
|
||||
}
|
||||
} else if (!strcasecmp("t1", default_linemode)) {
|
||||
wc->t1e1 = 0;
|
||||
} else if (!strcasecmp("e1", default_linemode)) {
|
||||
wc->t1e1 = 0xff;
|
||||
} else if (!strcasecmp("j1", default_linemode)) {
|
||||
wc->t1e1 = 0;
|
||||
j1mode = 1;
|
||||
} else {
|
||||
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
|
||||
default_linemode);
|
||||
wc->t1e1 = 0;
|
||||
}
|
||||
|
||||
wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28;
|
||||
@@ -4885,12 +4975,7 @@ __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
|
||||
{
|
||||
return __t4_hardware_init_1(wc, cardflags, true);
|
||||
}
|
||||
|
||||
static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
|
||||
static int t4_hardware_init_2(struct t4 *wc)
|
||||
{
|
||||
int x;
|
||||
unsigned int regval;
|
||||
@@ -4922,14 +5007,13 @@ static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
|
||||
|
||||
if (!is_octal(wc)) {
|
||||
regval = t4_framer_in(wc, 0, 0x4a);
|
||||
if (first_time && regval == 0x05) {
|
||||
if (regval == 0x05) {
|
||||
dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or "
|
||||
"earlier\n");
|
||||
} else if (regval == 0x20) {
|
||||
if (first_time)
|
||||
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
|
||||
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
|
||||
wc->falc31 = 1;
|
||||
} else if (first_time) {
|
||||
} else {
|
||||
dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
|
||||
"(VSTR = 0x%02x)\n", regval);
|
||||
}
|
||||
@@ -4949,24 +5033,14 @@ static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
|
||||
t4_pci_in(wc, x));
|
||||
}
|
||||
}
|
||||
|
||||
wc->gpio = 0x00000000;
|
||||
t4_pci_out(wc, WC_GPIO, wc->gpio);
|
||||
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
|
||||
t4_gpio_setdir(wc, (0xff), (0xff));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t4_hardware_init_2(struct t4 *wc)
|
||||
{
|
||||
return __t4_hardware_init_2(wc, true);
|
||||
}
|
||||
|
||||
static int __devinit t4_launch(struct t4 *wc)
|
||||
{
|
||||
int x;
|
||||
int res;
|
||||
unsigned long flags;
|
||||
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
|
||||
return 0;
|
||||
@@ -4998,14 +5072,17 @@ static int __devinit t4_launch(struct t4 *wc)
|
||||
&wc->ddev->spans);
|
||||
}
|
||||
|
||||
INIT_WORK(&wc->bh_work, t4_work_func);
|
||||
|
||||
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
|
||||
if (res) {
|
||||
dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
set_bit(T4_CHECK_TIMING, &wc->checkflag);
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5149,6 +5226,15 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
wc->num = x;
|
||||
cards[x] = wc;
|
||||
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
if (wc->devtype->flags & FLAG_2NDGEN) {
|
||||
char tmp[20];
|
||||
|
||||
sprintf(tmp, "te%dxxp[%d]", wc->numspans, wc->num);
|
||||
wc->workq = create_workqueue(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate pieces we need here */
|
||||
for (x = 0; x < ports_on_framer(wc); x++) {
|
||||
struct t4_span *ts;
|
||||
@@ -5161,6 +5247,9 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
wc->tspans[x] = ts;
|
||||
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
INIT_WORK(&ts->swork, workq_handlespan, ts);
|
||||
#endif
|
||||
ts->spanflags |= wc->devtype->flags;
|
||||
linemode = (wc->t1e1 & (1 << x)) ? E1 : ((j1mode) ? J1 : T1);
|
||||
t4_alloc_channels(wc, wc->tspans[x], linemode);
|
||||
@@ -5172,7 +5261,7 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
#ifdef SUPPORT_GEN1
|
||||
if (request_irq(pdev->irq, (wc->devtype->flags & FLAG_2NDGEN) ?
|
||||
t4_interrupt_gen2 : t4_interrupt,
|
||||
IRQF_SHARED,
|
||||
DAHDI_IRQ_SHARED,
|
||||
(wc->numspans == 8) ? "wct8xxp" :
|
||||
(wc->numspans == 2) ? "wct2xxp" :
|
||||
"wct4xxp",
|
||||
@@ -5186,7 +5275,7 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
|
||||
if (request_irq(pdev->irq, t4_interrupt_gen2,
|
||||
IRQF_SHARED, "t4xxp", wc)) {
|
||||
DAHDI_IRQ_SHARED, "t4xxp", wc)) {
|
||||
#endif
|
||||
dev_notice(&wc->dev->dev, "Unable to request IRQ %d\n",
|
||||
pdev->irq);
|
||||
@@ -5207,6 +5296,10 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev_info(&wc->dev->dev,
|
||||
"Found a Wildcard: %s\n", wc->devtype->desc);
|
||||
}
|
||||
wc->gpio = 0x00000000;
|
||||
t4_pci_out(wc, WC_GPIO, wc->gpio);
|
||||
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
|
||||
t4_gpio_setdir(wc, (0xff), (0xff));
|
||||
|
||||
#ifdef VPM_SUPPORT
|
||||
if (!wc->vpm) {
|
||||
@@ -5300,6 +5393,13 @@ static void _t4_remove_one(struct t4 *wc)
|
||||
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN))
|
||||
basesize = basesize * 2;
|
||||
|
||||
#ifdef ENABLE_WORKQUEUES
|
||||
if (wc->workq) {
|
||||
flush_workqueue(wc->workq);
|
||||
destroy_workqueue(wc->workq);
|
||||
}
|
||||
#endif
|
||||
|
||||
free_irq(wc->dev->irq, wc);
|
||||
|
||||
if (wc->membase)
|
||||
@@ -5387,7 +5487,7 @@ static int __init t4_init(void)
|
||||
"Please use 'default_linemode' instead.\n");
|
||||
}
|
||||
|
||||
res = pci_register_driver(&t4_driver);
|
||||
res = dahdi_pci_module(&t4_driver);
|
||||
if (res)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
@@ -31,62 +31,99 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "vpm450m.h"
|
||||
#include <oct612x.h>
|
||||
#include "oct6100api/oct6100_api.h"
|
||||
|
||||
static int wct4xxp_oct612x_write(struct oct612x_context *context,
|
||||
u32 address, u16 value)
|
||||
/* API for Octasic access */
|
||||
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
|
||||
{
|
||||
struct t4 *wc = dev_get_drvdata(context->dev);
|
||||
oct_set_reg(wc, address, value);
|
||||
return 0;
|
||||
/* Why couldn't they just take a timeval like everyone else? */
|
||||
struct timeval tv;
|
||||
unsigned long long total_usecs;
|
||||
unsigned int mask = ~0;
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
|
||||
(((unsigned long long)(tv.tv_usec)));
|
||||
f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
|
||||
f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
static int wct4xxp_oct612x_read(struct oct612x_context *context, u32 address,
|
||||
u16 *value)
|
||||
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength)
|
||||
{
|
||||
struct t4 *wc = dev_get_drvdata(context->dev);
|
||||
*value = (u16)oct_get_reg(wc, address);
|
||||
return 0;
|
||||
memset(f_pAddress, f_ulPattern, f_ulLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
static int wct4xxp_oct612x_write_smear(struct oct612x_context *context,
|
||||
u32 address, u16 value, size_t count)
|
||||
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength)
|
||||
{
|
||||
struct t4 *wc = dev_get_drvdata(context->dev);
|
||||
int i;
|
||||
for (i = 0; i < count; ++i)
|
||||
oct_set_reg(wc, address + (i << 1), value);
|
||||
return 0;
|
||||
memcpy(f_pDestination, f_pSource, f_ulLength);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
static int wct4xxp_oct612x_write_burst(struct oct612x_context *context,
|
||||
u32 address, const u16 *buffer,
|
||||
size_t count)
|
||||
UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
|
||||
{
|
||||
struct t4 *wc = dev_get_drvdata(context->dev);
|
||||
int i;
|
||||
for (i = 0; i < count; ++i)
|
||||
oct_set_reg(wc, address + (i << 1), buffer[i]);
|
||||
return 0;
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
static int wct4xxp_oct612x_read_burst(struct oct612x_context *context,
|
||||
u32 address, u16 *buffer, size_t count)
|
||||
UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
|
||||
{
|
||||
struct t4 *wc = dev_get_drvdata(context->dev);
|
||||
int i;
|
||||
for (i = 0; i < count; ++i)
|
||||
buffer[i] = oct_get_reg(wc, address + (i << 1));
|
||||
return 0;
|
||||
#ifdef OCTASIC_DEBUG
|
||||
printk(KERN_DEBUG "I should never be called! (destroy serialize object)\n");
|
||||
#endif
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
static const struct oct612x_ops wct4xxp_oct612x_ops = {
|
||||
.write = wct4xxp_oct612x_write,
|
||||
.read = wct4xxp_oct612x_read,
|
||||
.write_smear = wct4xxp_oct612x_write_smear,
|
||||
.write_burst = wct4xxp_oct612x_write_burst,
|
||||
.read_burst = wct4xxp_oct612x_read_burst,
|
||||
};
|
||||
UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
|
||||
{
|
||||
/* Not needed */
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
|
||||
{
|
||||
/* Not needed */
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
|
||||
{
|
||||
oct_set_reg(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
|
||||
{
|
||||
unsigned int x;
|
||||
for (x=0;x<f_pSmearParams->ulWriteLength;x++) {
|
||||
oct_set_reg(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData);
|
||||
}
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
|
||||
{
|
||||
unsigned int x;
|
||||
for (x=0;x<f_pBurstParams->ulWriteLength;x++) {
|
||||
oct_set_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]);
|
||||
}
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
|
||||
{
|
||||
*(f_pReadParams->pusReadData) = oct_get_reg(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress);
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
|
||||
{
|
||||
unsigned int x;
|
||||
for (x=0;x<f_pBurstParams->ulReadLength;x++) {
|
||||
f_pBurstParams->pusReadData[x] = oct_get_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1));
|
||||
}
|
||||
return cOCT6100_ERR_OK;
|
||||
}
|
||||
|
||||
#define SOUT_G168_1100GB_ON 0x40000004
|
||||
#define SOUT_DTMF_1 0x40000011
|
||||
@@ -136,7 +173,6 @@ static const struct oct612x_ops wct4xxp_oct612x_ops = {
|
||||
|
||||
struct vpm450m {
|
||||
tPOCT6100_INSTANCE_API pApiInstance;
|
||||
struct oct612x_context context;
|
||||
UINT32 aulEchoChanHndl[256];
|
||||
int chanflags[256];
|
||||
int ecmode[256];
|
||||
@@ -220,10 +256,8 @@ void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
|
||||
pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n",
|
||||
vpm450m->aulEchoChanHndl[channel], channel, ulResult);
|
||||
} else {
|
||||
if (debug) {
|
||||
pr_info("Changed companding on channel %d to %s.\n",
|
||||
channel, (alaw) ? "alaw" : "ulaw");
|
||||
}
|
||||
pr_info("Changed companding on channel %d to %s.\n", channel,
|
||||
(alaw) ? "alaw" : "ulaw");
|
||||
if (alaw)
|
||||
vpm450m->chanflags[channel] |= FLAG_ALAW;
|
||||
else
|
||||
@@ -239,7 +273,7 @@ static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode)
|
||||
|
||||
if (vpm450m->ecmode[channel] == mode)
|
||||
return;
|
||||
modify = kzalloc(sizeof(*modify), GFP_ATOMIC);
|
||||
modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
|
||||
if (!modify) {
|
||||
printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setec!\n");
|
||||
return;
|
||||
@@ -269,7 +303,7 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
|
||||
return;
|
||||
}
|
||||
|
||||
modify = kzalloc(sizeof(*modify), GFP_KERNEL);
|
||||
modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL);
|
||||
if (!modify) {
|
||||
printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setdtmf!\n");
|
||||
return;
|
||||
@@ -417,18 +451,14 @@ int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int get_vpm450m_capacity(struct device *device)
|
||||
unsigned int get_vpm450m_capacity(void *wc)
|
||||
{
|
||||
struct oct612x_context context;
|
||||
UINT32 ulResult;
|
||||
|
||||
tOCT6100_API_GET_CAPACITY_PINS CapacityPins;
|
||||
|
||||
context.dev = device;
|
||||
context.ops = &wct4xxp_oct612x_ops;
|
||||
|
||||
Oct6100ApiGetCapacityPinsDef(&CapacityPins);
|
||||
CapacityPins.pProcessContext = &context;
|
||||
CapacityPins.pProcessContext = wc;
|
||||
CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR;
|
||||
CapacityPins.fEnableMemClkOut = TRUE;
|
||||
CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
|
||||
@@ -442,8 +472,7 @@ unsigned int get_vpm450m_capacity(struct device *device)
|
||||
return CapacityPins.ulCapacityValue;
|
||||
}
|
||||
|
||||
struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
int numspans, const struct firmware *firmware)
|
||||
struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware)
|
||||
{
|
||||
tOCT6100_CHIP_OPEN *ChipOpen;
|
||||
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
|
||||
@@ -454,27 +483,26 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
struct vpm450m *vpm450m;
|
||||
int x,y,law;
|
||||
|
||||
vpm450m = kzalloc(sizeof(*vpm450m), GFP_KERNEL);
|
||||
if (!vpm450m)
|
||||
if (!(vpm450m = kmalloc(sizeof(struct vpm450m), GFP_KERNEL)))
|
||||
return NULL;
|
||||
|
||||
vpm450m->context.dev = device;
|
||||
vpm450m->context.ops = &wct4xxp_oct612x_ops;
|
||||
memset(vpm450m, 0, sizeof(struct vpm450m));
|
||||
|
||||
ChipOpen = kzalloc(sizeof(*ChipOpen), GFP_KERNEL);
|
||||
if (!ChipOpen) {
|
||||
kfree(vpm450m);
|
||||
if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) {
|
||||
kfree(vpm450m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ChannelOpen = kzalloc(sizeof(*ChannelOpen), GFP_KERNEL);
|
||||
if (!ChannelOpen) {
|
||||
memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN));
|
||||
|
||||
if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) {
|
||||
kfree(vpm450m);
|
||||
kfree(ChipOpen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN));
|
||||
|
||||
for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++)
|
||||
vpm450m->ecmode[x] = -1;
|
||||
|
||||
@@ -487,7 +515,7 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;
|
||||
Oct6100GetInstanceSizeDef(&InstanceSize);
|
||||
|
||||
ChipOpen->pProcessContext = &vpm450m->context;
|
||||
ChipOpen->pProcessContext = wc;
|
||||
|
||||
ChipOpen->pbyImageFile = firmware->data;
|
||||
ChipOpen->ulImageSize = firmware->size;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
struct t4;
|
||||
struct vpm450m;
|
||||
|
||||
/* From driver */
|
||||
@@ -33,9 +32,8 @@ unsigned int oct_get_reg(void *data, unsigned int reg);
|
||||
void oct_set_reg(void *data, unsigned int reg, unsigned int val);
|
||||
|
||||
/* From vpm450m */
|
||||
struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
|
||||
int numspans, const struct firmware *firmware);
|
||||
unsigned int get_vpm450m_capacity(struct device *device);
|
||||
struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware);
|
||||
unsigned int get_vpm450m_capacity(void *wc);
|
||||
void vpm450m_setec(struct vpm450m *instance, int channel, int eclen);
|
||||
void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int dtmfmute);
|
||||
int vpm450m_checkirq(struct vpm450m *vpm450m);
|
||||
@@ -44,6 +42,4 @@ void release_vpm450m(struct vpm450m *instance);
|
||||
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
|
||||
int channel, bool alaw);
|
||||
|
||||
extern int debug;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -131,6 +131,13 @@ struct t4_reg {
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
#define T4_CHECK_VPM 0
|
||||
#define T4_LOADING_FW 1
|
||||
#define T4_STOP_DMA 2
|
||||
#define T4_CHECK_TIMING 3
|
||||
#define T4_CHANGE_LATENCY 4
|
||||
#define T4_IGNORE_LATENCY 5
|
||||
|
||||
#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
|
||||
#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
|
||||
#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2881
drivers/dahdi/wctdm.c
Normal file
2881
drivers/dahdi/wctdm.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -44,15 +44,17 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
||||
#include <linux/semaphore.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -69,10 +71,6 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
|
||||
#include <dahdi/kernel.h>
|
||||
#include <dahdi/wctdm_user.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif /* 4.11.0 */
|
||||
|
||||
#include "proslic.h"
|
||||
|
||||
#include "wctdm24xxp.h"
|
||||
@@ -328,9 +326,15 @@ struct bg {
|
||||
int ret;
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void bg_work_func(void *data)
|
||||
{
|
||||
struct bg *bg = data;
|
||||
#else
|
||||
static void bg_work_func(struct work_struct *work)
|
||||
{
|
||||
struct bg *bg = container_of(work, struct bg, work);
|
||||
#endif
|
||||
bg->ret = bg->fn(bg->wc, bg->param);
|
||||
complete(&bg->complete);
|
||||
}
|
||||
@@ -367,7 +371,11 @@ bg_create(struct wctdm *wc, bg_work_func_t fn, unsigned long param)
|
||||
}
|
||||
|
||||
init_completion(&bg->complete);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&bg->work, bg_work_func, bg);
|
||||
#else
|
||||
INIT_WORK(&bg->work, bg_work_func);
|
||||
#endif
|
||||
|
||||
bg->wc = wc;
|
||||
bg->fn = fn;
|
||||
@@ -449,10 +457,16 @@ struct vpmadt032_channel_setup {
|
||||
struct wctdm *wc;
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void vpm_setup_work_func(void *data)
|
||||
{
|
||||
struct vpmadt032_channel_setup *setup = data;
|
||||
#else
|
||||
static void vpm_setup_work_func(struct work_struct *work)
|
||||
{
|
||||
struct vpmadt032_channel_setup *setup =
|
||||
container_of(work, struct vpmadt032_channel_setup, work);
|
||||
#endif
|
||||
int i;
|
||||
int res;
|
||||
GpakChannelConfig_t chanconfig;
|
||||
@@ -614,7 +628,13 @@ static int config_vpmadt032(struct vpmadt032 *vpm, struct wctdm *wc)
|
||||
return -ENOMEM;
|
||||
|
||||
setup->wc = wc;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&setup->work, vpm_setup_work_func, setup);
|
||||
#else
|
||||
INIT_WORK(&setup->work, vpm_setup_work_func);
|
||||
#endif
|
||||
|
||||
queue_work(vpm->wq, &setup->work);
|
||||
|
||||
return 0;
|
||||
@@ -1955,14 +1975,12 @@ wctdm_check_battery_lost(struct wctdm *wc, struct wctdm_module *const mod)
|
||||
break;
|
||||
case BATTERY_UNKNOWN:
|
||||
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
|
||||
/* fallthrough */
|
||||
case BATTERY_PRESENT:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_LOST;
|
||||
fxo->battdebounce_timer = wc->framecount + battdebounce;
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM:
|
||||
/* fallthrough */
|
||||
case BATTERY_DEBOUNCING_LOST:
|
||||
case BATTERY_DEBOUNCING_LOST: /* Intentional drop through */
|
||||
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
|
||||
if (debug) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
@@ -2065,8 +2083,7 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
|
||||
break;
|
||||
case BATTERY_UNKNOWN:
|
||||
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
|
||||
/* fallthrough */
|
||||
case BATTERY_LOST:
|
||||
case BATTERY_LOST: /* intentional drop through */
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT;
|
||||
fxo->battdebounce_timer = wc->framecount + battdebounce;
|
||||
break;
|
||||
@@ -3083,8 +3100,6 @@ wctdm_init_voicedaa(struct wctdm *wc, struct wctdm_module *mod,
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
msleep(20);
|
||||
|
||||
memset(&mod->mod.fxo, 0, sizeof(mod->mod.fxo));
|
||||
|
||||
if (!sane && wctdm_voicedaa_insane(wc, mod))
|
||||
return -2;
|
||||
|
||||
@@ -3229,7 +3244,8 @@ wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod,
|
||||
return -2;
|
||||
|
||||
/* Initialize VMWI settings */
|
||||
memset(fxs, 0, sizeof(*fxs));
|
||||
memset(&(fxs->vmwisetting), 0, sizeof(fxs->vmwisetting));
|
||||
fxs->vmwi_linereverse = 0;
|
||||
|
||||
/* By default, don't send on hook */
|
||||
if (!reversepolarity != !fxs->reversepolarity)
|
||||
@@ -4368,6 +4384,32 @@ wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
|
||||
return wctdm_wait_for_ready(wc);
|
||||
}
|
||||
|
||||
/*
|
||||
* wctdm24xxp_assigned - Called when span is assigned.
|
||||
* @span: The span that is now assigned.
|
||||
*
|
||||
* This function is called by the core of DAHDI after the span number and
|
||||
* channel numbers have been assigned.
|
||||
*
|
||||
*/
|
||||
static void wctdm24xxp_assigned(struct dahdi_span *span)
|
||||
{
|
||||
struct dahdi_span *s;
|
||||
struct dahdi_device *ddev = span->parent;
|
||||
struct wctdm *wc = NULL;
|
||||
|
||||
list_for_each_entry(s, &ddev->spans, device_node) {
|
||||
wc = (container_of(s, struct wctdm_span, span))->wc;
|
||||
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
|
||||
return;
|
||||
}
|
||||
|
||||
if (wc) {
|
||||
WARN_ON(0 == wc->not_ready);
|
||||
--wc->not_ready;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.hooksig = wctdm_hooksig,
|
||||
@@ -4377,6 +4419,7 @@ static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
|
||||
.watchdog = wctdm_watchdog,
|
||||
.chanconfig = wctdm_chanconfig,
|
||||
.dacs = wctdm_dacs,
|
||||
.assigned = wctdm24xxp_assigned,
|
||||
#ifdef VPM_SUPPORT
|
||||
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
|
||||
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
|
||||
@@ -4395,6 +4438,7 @@ static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = {
|
||||
.spanconfig = b400m_spanconfig,
|
||||
.chanconfig = b400m_chanconfig,
|
||||
.dacs = wctdm_dacs,
|
||||
.assigned = wctdm24xxp_assigned,
|
||||
#ifdef VPM_SUPPORT
|
||||
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
|
||||
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
|
||||
@@ -5907,9 +5951,6 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -1;
|
||||
}
|
||||
|
||||
WARN_ON(wc->not_ready <= 0);
|
||||
--wc->not_ready;
|
||||
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
|
||||
(is_hx8(wc)) ? "Hybrid card" : "Wildcard TDM",
|
||||
@@ -6029,7 +6070,11 @@ static void __devexit wctdm_remove_one(struct pci_dev *pdev)
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(wctdm_pci_tbl) = {
|
||||
{ 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 },
|
||||
{ 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 },
|
||||
{ 0xd161, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex800 },
|
||||
{ 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 },
|
||||
{ 0xd161, 0x8005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm410 },
|
||||
{ 0xd161, 0x8006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex410 },
|
||||
{ 0xd161, 0x8007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcha80000 },
|
||||
{ 0xd161, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wchb80000 },
|
||||
{ 0 }
|
||||
@@ -6105,7 +6150,7 @@ static int __init wctdm_init(void)
|
||||
|
||||
b400m_module_init();
|
||||
|
||||
res = pci_register_driver(&wctdm_driver);
|
||||
res = dahdi_pci_module(&wctdm_driver);
|
||||
if (res)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
@@ -29,7 +29,11 @@
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
||||
#include <linux/semaphore.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
|
||||
#include "voicebus/voicebus.h"
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <linux/ppp_defs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define FAST_HDLC_NEED_TABLES
|
||||
#include <dahdi/kernel.h>
|
||||
@@ -2386,9 +2385,15 @@ int b400m_dchan(struct dahdi_span *span)
|
||||
|
||||
/*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void xhfc_work(void *data)
|
||||
{
|
||||
struct b400m *b4 = data;
|
||||
#else
|
||||
static void xhfc_work(struct work_struct *work)
|
||||
{
|
||||
struct b400m *b4 = container_of(work, struct b400m, xhfc_wq);
|
||||
#endif
|
||||
int i, j, k, fifo;
|
||||
unsigned char b, b2;
|
||||
|
||||
@@ -2558,10 +2563,9 @@ static int b400m_probe(struct wctdm *wc, int modpos)
|
||||
struct b400m *b4;
|
||||
unsigned long flags;
|
||||
int chiprev;
|
||||
u8 lastreg = 0;
|
||||
|
||||
wctdm_setreg(wc, &wc->mods[modpos], 0x10, 0x10);
|
||||
id = xhfc_getreg(wc, &wc->mods[modpos], R_CHIP_ID, &lastreg);
|
||||
id = xhfc_getreg(wc, &wc->mods[modpos], R_CHIP_ID, &x);
|
||||
|
||||
/* chip ID high 7 bits must be 0x62, see datasheet */
|
||||
if ((id & 0xfe) != 0x62)
|
||||
@@ -2576,7 +2580,6 @@ static int b400m_probe(struct wctdm *wc, int modpos)
|
||||
|
||||
/* card found, enabled and main struct allocated. Fill it out. */
|
||||
b4->wc = wc;
|
||||
b4->lastreg = lastreg;
|
||||
b4->position = modpos;
|
||||
|
||||
/* which B400M in the system is this one? count all of them found so
|
||||
@@ -2626,7 +2629,11 @@ void b400m_post_init(struct b400m *b4)
|
||||
snprintf(b4->name, sizeof(b4->name) - 1, "b400m-%d",
|
||||
b4->b400m_no);
|
||||
b4->xhfc_ws = create_singlethread_workqueue(b4->name);
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&b4->xhfc_wq, xhfc_work, b4);
|
||||
# else
|
||||
INIT_WORK(&b4->xhfc_wq, xhfc_work);
|
||||
# endif
|
||||
b4->inited = 1;
|
||||
}
|
||||
|
||||
|
||||
1642
drivers/dahdi/wcte11xp.c
Normal file
1642
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
|
||||
3217
drivers/dahdi/wcte12xp/base.c
Normal file
3217
drivers/dahdi/wcte12xp/base.c
Normal file
File diff suppressed because it is too large
Load Diff
167
drivers/dahdi/wcte12xp/wcte12xp.h
Normal file
167
drivers/dahdi/wcte12xp/wcte12xp.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Digium, Inc. Wildcard TE12xP T1/E1 card Driver
|
||||
*
|
||||
* Written by Michael Spiceland <mspiceland@digium.com>
|
||||
*
|
||||
* Adapted from the wctdm24xxp and wcte11xp drivers originally
|
||||
* written by Mark Spencer <markster@digium.com>
|
||||
* Matthew Fredrickson <creslin@digium.com>
|
||||
* William Meadows <wmeadows@digium.com>
|
||||
*
|
||||
* Copyright (C) 2007-2010, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#ifndef _WCTE12XP_H
|
||||
#define _WCTE12XP_H
|
||||
|
||||
/* Comment to disable VPM support */
|
||||
#define VPM_SUPPORT 1
|
||||
|
||||
#define WC_MAX_IFACES 8
|
||||
|
||||
#ifdef VPM_SUPPORT
|
||||
#define MAX_TDM_CHAN 31
|
||||
#endif
|
||||
|
||||
#define SDI_CLK (0x00010000)
|
||||
#define SDI_DOUT (0x00020000)
|
||||
#define SDI_DREAD (0x00040000)
|
||||
#define SDI_DIN (0x00080000)
|
||||
|
||||
#define EFRAME_SIZE 108
|
||||
#define ERING_SIZE 16 /* Maximum ring size */
|
||||
#define EFRAME_GAP 20
|
||||
#define SFRAME_SIZE ((EFRAME_SIZE * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1)))
|
||||
|
||||
#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
|
||||
|
||||
#define MAX_COMMANDS 16
|
||||
|
||||
#define NUM_EC 4
|
||||
|
||||
#define __CMD_PINS (1 << 18) /* CPLD pin read */
|
||||
#define __CMD_LEDS (1 << 19) /* LED Operation */
|
||||
#define __CMD_RD (1 << 20) /* Read Operation */
|
||||
#define __CMD_WR (1 << 21) /* Write Operation */
|
||||
|
||||
#define __LED_ORANGE (1<<3)
|
||||
#define __LED_GREEN (1<<2)
|
||||
#define __LED_RED (1<<1)
|
||||
|
||||
#define SET_LED_ORANGE(a) (a | __LED_ORANGE)
|
||||
#define SET_LED_RED(a) ((a | __LED_RED) & ~__LED_GREEN)
|
||||
#define SET_LED_GREEN(a) ((a | __LED_GREEN) & ~__LED_RED)
|
||||
|
||||
#define UNSET_LED_ORANGE(a) (a & ~__LED_ORANGE)
|
||||
#define UNSET_LED_REDGREEN(a) (a | __LED_RED | __LED_GREEN)
|
||||
|
||||
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
|
||||
//TODO: make a separate macro
|
||||
|
||||
enum linemode {
|
||||
T1 = 1,
|
||||
E1,
|
||||
J1,
|
||||
};
|
||||
|
||||
struct command {
|
||||
struct list_head node;
|
||||
struct completion complete;
|
||||
u8 data;
|
||||
u8 ident;
|
||||
u8 cs_slot;
|
||||
u16 address;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct vpm150m;
|
||||
|
||||
struct t1 {
|
||||
spinlock_t reglock;
|
||||
unsigned char txident;
|
||||
unsigned char rxident;
|
||||
unsigned char statreg; /* bit 0 = vpmadt032 int */
|
||||
struct {
|
||||
unsigned int nmf:1;
|
||||
unsigned int sendingyellow:1;
|
||||
} flags;
|
||||
unsigned char txsigs[16]; /* Copy of tx sig registers */
|
||||
int alarmcount; /* How much red alarm we've seen */
|
||||
int losalarmcount;
|
||||
int aisalarmcount;
|
||||
int yelalarmcount;
|
||||
const char *variety;
|
||||
char name[80];
|
||||
unsigned long blinktimer;
|
||||
int loopupcnt;
|
||||
int loopdowncnt;
|
||||
#define INITIALIZED 1
|
||||
#define SHUTDOWN 2
|
||||
#define READY 3
|
||||
#define IOERROR 4
|
||||
unsigned long bit_flags;
|
||||
unsigned long alarmtimer;
|
||||
unsigned char ledstate;
|
||||
unsigned char vpm_check_count;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span; /* Span */
|
||||
struct dahdi_chan *chans[32]; /* Channels */
|
||||
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
|
||||
#ifdef CONFIG_VOICEBUS_ECREFERENCE
|
||||
struct dahdi_fifo *ec_reference[32];
|
||||
#else
|
||||
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
|
||||
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
|
||||
#endif
|
||||
unsigned long ctlreg;
|
||||
struct voicebus vb;
|
||||
atomic_t txints;
|
||||
struct vpmadt032 *vpmadt032;
|
||||
struct vpmoct *vpmoct;
|
||||
unsigned long vpm_check;
|
||||
struct work_struct vpm_check_work;
|
||||
|
||||
/* protected by t1.reglock */
|
||||
struct list_head pending_cmds;
|
||||
struct list_head active_cmds;
|
||||
struct timer_list timer;
|
||||
struct work_struct timer_work;
|
||||
struct workqueue_struct *wq;
|
||||
unsigned int not_ready; /* 0 when entire card is ready to go */
|
||||
};
|
||||
|
||||
#define t1_info(t1, format, arg...) \
|
||||
dev_info(&t1->vb.pdev->dev , format , ## arg)
|
||||
|
||||
#define t1_notice(t1, format, arg...) \
|
||||
dev_notice(&t1->vb.pdev->dev , format , ## arg)
|
||||
|
||||
/* Maintenance Mode Registers */
|
||||
#define LIM0 0x36
|
||||
#define LIM0_LL (1<<1)
|
||||
#define LIM1 0x37
|
||||
#define LIM1_RL (1<<1)
|
||||
#define LIM1_JATT (1<<2)
|
||||
|
||||
/* Clear Channel Registers */
|
||||
#define CCB1 0x2f
|
||||
#define CCB2 0x30
|
||||
#define CCB3 0x31
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1047
drivers/dahdi/wcxb.c
1047
drivers/dahdi/wcxb.c
File diff suppressed because it is too large
Load Diff
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* wcxb SPI library
|
||||
*
|
||||
* Copyright (C) 2013 Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#ifndef __WCXB_H__
|
||||
#define __WCXB_H__
|
||||
|
||||
#define WCXB_DEFAULT_LATENCY 3U
|
||||
#define WCXB_DEFAULT_MAXLATENCY 12U
|
||||
#define WCXB_DMA_CHAN_SIZE 128
|
||||
|
||||
struct wcxb;
|
||||
|
||||
struct wcxb_operations {
|
||||
void (*handle_receive)(struct wcxb *xb, void *frame);
|
||||
void (*handle_transmit)(struct wcxb *xb, void *frame);
|
||||
void (*handle_error)(struct wcxb *xb);
|
||||
void (*handle_interrupt)(struct wcxb *xb, u32 pending);
|
||||
};
|
||||
|
||||
struct wcxb_meta_desc;
|
||||
struct wcxb_hw_desc;
|
||||
|
||||
/**
|
||||
* struct wcxb - Interface to wcxb firmware.
|
||||
* @last_retry_count: Running count of times firmware had to retry host DMA
|
||||
* transaction. Debugging aide.
|
||||
*/
|
||||
struct wcxb {
|
||||
struct pci_dev *pdev;
|
||||
spinlock_t lock;
|
||||
const struct wcxb_operations *ops;
|
||||
unsigned int *debug;
|
||||
unsigned int max_latency;
|
||||
unsigned int latency;
|
||||
struct {
|
||||
u32 have_msi:1;
|
||||
u32 latency_locked:1;
|
||||
u32 drive_timing_cable:1;
|
||||
u32 dma_ins:1;
|
||||
} flags;
|
||||
void __iomem *membase;
|
||||
struct wcxb_meta_desc *meta_dring;
|
||||
struct wcxb_hw_desc *hw_dring;
|
||||
unsigned int dma_head;
|
||||
unsigned int dma_tail;
|
||||
dma_addr_t hw_dring_phys;
|
||||
struct dma_pool *pool;
|
||||
unsigned long framecount;
|
||||
#ifdef DEBUG
|
||||
u8 last_retry_count;
|
||||
u8 max_retry_count;
|
||||
u32 last_dma_time;
|
||||
u32 max_dma_time;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode);
|
||||
extern void wcxb_release(struct wcxb *xb);
|
||||
extern int wcxb_start(struct wcxb *xb);
|
||||
extern void wcxb_stop(struct wcxb *xb);
|
||||
extern int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms);
|
||||
extern bool wcxb_is_stopped(struct wcxb *xb);
|
||||
|
||||
enum wcxb_clock_sources {
|
||||
WCXB_CLOCK_SELF, /* Use the internal oscillator for timing. */
|
||||
WCXB_CLOCK_RECOVER, /* Recover the clock from a framer. */
|
||||
#ifdef RPC_RCLK
|
||||
WCXB_CLOCK_RECOVER_ALT, /* Recover the clock from a framer. */
|
||||
#endif
|
||||
WCXB_CLOCK_SLAVE /* Recover clock from any timing header. */
|
||||
};
|
||||
|
||||
extern enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb);
|
||||
extern void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc);
|
||||
|
||||
static inline void wcxb_enable_timing_header_driver(struct wcxb *xb)
|
||||
{
|
||||
xb->flags.drive_timing_cable = 1;
|
||||
}
|
||||
static inline bool wcxb_is_timing_header_driver_enabled(struct wcxb *xb)
|
||||
{
|
||||
return 1 == xb->flags.drive_timing_cable;
|
||||
}
|
||||
|
||||
static inline void wcxb_disable_timing_header_driver(struct wcxb *xb)
|
||||
{
|
||||
xb->flags.drive_timing_cable = 0;
|
||||
}
|
||||
|
||||
enum wcxb_reset_option {
|
||||
WCXB_RESET_NOW,
|
||||
WCXB_RESET_LATER
|
||||
};
|
||||
|
||||
extern u32 wcxb_get_firmware_version(struct wcxb *xb);
|
||||
extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
|
||||
const char *firmware_filename,
|
||||
bool force_firmware,
|
||||
enum wcxb_reset_option reset);
|
||||
|
||||
extern void wcxb_stop_dma(struct wcxb *xb);
|
||||
extern void wcxb_disable_interrupts(struct wcxb *xb);
|
||||
|
||||
static inline void wcxb_gpio_set(struct wcxb *xb, u32 bits)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
reg = ioread32be(xb->membase);
|
||||
iowrite32be(reg | bits, xb->membase);
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
}
|
||||
|
||||
static inline void wcxb_gpio_clear(struct wcxb *xb, u32 bits)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
reg = ioread32be(xb->membase);
|
||||
iowrite32be(reg & (~bits), xb->membase);
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
wcxb_set_maxlatency(struct wcxb *xb, unsigned int max_latency)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
xb->max_latency = clamp(max_latency,
|
||||
xb->latency,
|
||||
WCXB_DEFAULT_MAXLATENCY);
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
wcxb_set_minlatency(struct wcxb *xb, unsigned int min_latency)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
xb->latency = clamp(min_latency, WCXB_DEFAULT_LATENCY,
|
||||
WCXB_DEFAULT_MAXLATENCY);
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
wcxb_lock_latency(struct wcxb *xb)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
xb->flags.latency_locked = 1;
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
wcxb_unlock_latency(struct wcxb *xb)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&xb->lock, flags);
|
||||
xb->flags.latency_locked = 0;
|
||||
spin_unlock_irqrestore(&xb->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Interface for the echocan block */
|
||||
extern void wcxb_enable_echocan(struct wcxb *xb);
|
||||
extern void wcxb_disable_echocan(struct wcxb *xb);
|
||||
extern void wcxb_reset_echocan(struct wcxb *xb);
|
||||
extern void wcxb_enable_echocan_dram(struct wcxb *xb);
|
||||
extern bool wcxb_is_echocan_present(struct wcxb *xb);
|
||||
extern u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address);
|
||||
extern void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val);
|
||||
|
||||
#endif
|
||||
@@ -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_*
|
||||
@@ -57,8 +68,8 @@ xpp_verified = $(foreach file, $(xpp_verifications), $(file).verified)
|
||||
FXO_MODES = $(src)/../fxo_modes.h
|
||||
FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
|
||||
|
||||
hostprogs := print_fxo_modes
|
||||
always-y := $(xpp_verified)
|
||||
hostprogs-y := print_fxo_modes
|
||||
always := $(xpp_verified) xpp_version.h
|
||||
print_fxo_modes-objs := print_fxo_modes.o
|
||||
HOSTCFLAGS_print_fxo_modes.o += -include $(FXO_MODES)
|
||||
|
||||
|
||||
@@ -153,12 +153,8 @@ static int write_state_register(xpd_t *xpd, __u8 value);
|
||||
static bool bri_packet_is_valid(xpacket_t *pack);
|
||||
static void bri_packet_dump(const char *msg, xpacket_t *pack);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops proc_bri_info_ops;
|
||||
#else
|
||||
static const struct file_operations proc_bri_info_ops;
|
||||
#endif
|
||||
#endif
|
||||
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
struct dahdi_lineconfig *lc);
|
||||
static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
@@ -166,6 +162,7 @@ static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
static int bri_startup(struct file *file, struct dahdi_span *span);
|
||||
static int bri_shutdown(struct dahdi_span *span);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
#define PROC_BRI_INFO_FNAME "bri_info"
|
||||
|
||||
enum led_state {
|
||||
@@ -471,8 +468,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
int ret = 0;
|
||||
|
||||
src = REG_XDATA(regcmd);
|
||||
len = regcmd->h.bytes;
|
||||
eoframe = regcmd->h.eoframe;
|
||||
len = regcmd->bytes;
|
||||
eoframe = regcmd->eoframe;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */
|
||||
@@ -568,12 +565,12 @@ static void fill_multibyte(xpd_t *xpd, xpacket_t *pack,
|
||||
char *p;
|
||||
|
||||
XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
|
||||
XPACKET_LEN(pack) = XFRAME_CMD_LEN(REG);
|
||||
XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->h.bytes = len;
|
||||
reg_cmd->h.is_multibyte = 1;
|
||||
reg_cmd->h.portnum = xpd->addr.subunit;
|
||||
reg_cmd->h.eoframe = eoframe;
|
||||
reg_cmd->bytes = len;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = xpd->addr.subunit;
|
||||
reg_cmd->eoframe = eoframe;
|
||||
p = REG_XDATA(reg_cmd);
|
||||
memcpy(p, buf, len);
|
||||
if (debug)
|
||||
@@ -614,7 +611,7 @@ static int tx_dchan(xpd_t *xpd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
|
||||
int packet_len = XFRAME_CMD_LEN(REG);
|
||||
int packet_len = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
char buf[MULTIBYTE_MAX_LEN];
|
||||
int len = MULTIBYTE_MAX_LEN;
|
||||
|
||||
@@ -690,29 +687,20 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
}
|
||||
|
||||
static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels = min(3, CHANNELS_PERXPD);
|
||||
|
||||
if ((unit_descriptor->ports_per_chip < 1) ||
|
||||
(unit_descriptor->ports_per_chip > 4)) {
|
||||
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
|
||||
unit_descriptor->ports_per_chip);
|
||||
return NULL;
|
||||
}
|
||||
if ((unit_descriptor->numchips) < 1 ||
|
||||
(unit_descriptor->numchips > 2)) {
|
||||
XBUS_ERR(xbus, "Bad numchips=%d\n",
|
||||
unit_descriptor->numchips);
|
||||
if (subunit_ports != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct BRI_priv_data), proto_table, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
|
||||
@@ -989,8 +977,7 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
||||
0, /* data_low */
|
||||
0, /* do_datah */
|
||||
0, /* data_high */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
0 /* should_reply */
|
||||
);
|
||||
|
||||
if (IS_NT(xpd) && nt_keepalive
|
||||
@@ -1439,8 +1426,7 @@ static int write_state_register(xpd_t *xpd, __u8 value)
|
||||
value, /* data_low */
|
||||
0, /* do_datah */
|
||||
0, /* data_high */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
0 /* should_reply */
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
@@ -1552,7 +1538,7 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/* Map UNIT + PORTNUM to XPD */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->h.portnum;
|
||||
addr.subunit = info->portnum;
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
if (!xpd) {
|
||||
static int rate_limit;
|
||||
@@ -1577,9 +1563,9 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
|
||||
REG_FIELD(info, data_low));
|
||||
}
|
||||
if (info->h.is_multibyte) {
|
||||
if (info->is_multibyte) {
|
||||
XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
|
||||
info->h.bytes, info->h.eoframe);
|
||||
info->bytes, info->eoframe);
|
||||
ret = rx_dchan(xpd, info);
|
||||
if (ret < 0) {
|
||||
priv->dchan_rx_drops++;
|
||||
@@ -1744,22 +1730,13 @@ static int proc_bri_info_open(struct inode *inode, struct file *file)
|
||||
return single_open(file, proc_bri_info_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops proc_bri_info_ops = {
|
||||
.proc_open = proc_bri_info_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations proc_bri_info_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_bri_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_bri_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
#endif
|
||||
|
||||
static int bri_xpd_probe(struct device *dev)
|
||||
@@ -1768,9 +1745,9 @@ static int bri_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->xpd_type != XPD_TYPE_BRI) {
|
||||
if (xpd->type != XPD_TYPE_BRI) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->xpd_type);
|
||||
xpd->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -1787,7 +1764,7 @@ static int bri_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver bri_driver = {
|
||||
.xpd_type = XPD_TYPE_BRI,
|
||||
.type = XPD_TYPE_BRI,
|
||||
.driver = {
|
||||
.name = "bri",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1801,6 +1778,7 @@ static int __init card_bri_startup(void)
|
||||
|
||||
if ((ret = xpd_driver_register(&bri_driver.driver)) < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
xproto_register(&PROTO_TABLE(BRI));
|
||||
return 0;
|
||||
}
|
||||
@@ -1815,6 +1793,7 @@ static void __exit card_bri_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP BRI Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_BRI);
|
||||
|
||||
module_init(card_bri_startup);
|
||||
|
||||
@@ -54,21 +54,20 @@ static xproto_table_t PROTO_TABLE(ECHO);
|
||||
/*---------------- ECHO: Methods -------------------------------------------*/
|
||||
|
||||
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels = 0;
|
||||
|
||||
if (unit_descriptor->ports_per_chip != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
|
||||
if (subunit_ports != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct ECHO_priv_data), proto_table, unit_descriptor, channels);
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct ECHO_priv_data), proto_table, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
xpd->type_name = "ECHO";
|
||||
@@ -81,7 +80,7 @@ static int ECHO_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
|
||||
BUG_ON(!xpd);
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
xpd->xpd_type = XPD_TYPE_ECHO;
|
||||
xpd->type = XPD_TYPE_ECHO;
|
||||
XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name);
|
||||
ret = CALL_EC_METHOD(ec_update, xbus, xbus);
|
||||
return ret;
|
||||
@@ -113,7 +112,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/* Map UNIT + PORTNUM to XPD */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->h.portnum;
|
||||
addr.subunit = info->portnum;
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
if (!xpd) {
|
||||
static int rate_limit;
|
||||
@@ -308,9 +307,9 @@ static int echo_xpd_probe(struct device *dev)
|
||||
|
||||
ec_xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (ec_xpd->xpd_type != XPD_TYPE_ECHO) {
|
||||
if (ec_xpd->type != XPD_TYPE_ECHO) {
|
||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
ec_xpd->xpd_type);
|
||||
ec_xpd->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||
@@ -327,7 +326,7 @@ static int echo_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver echo_driver = {
|
||||
.xpd_type = XPD_TYPE_ECHO,
|
||||
.type = XPD_TYPE_ECHO,
|
||||
.driver = {
|
||||
.name = "echo",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -342,6 +341,7 @@ static int __init card_echo_startup(void)
|
||||
ret = xpd_driver_register(&echo_driver.driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
INFO("FEATURE: WITH Octasic echo canceller\n");
|
||||
xproto_register(&PROTO_TABLE(ECHO));
|
||||
return 0;
|
||||
@@ -357,6 +357,7 @@ static void __exit card_echo_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP ECHO Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_ECHO);
|
||||
|
||||
module_init(card_echo_startup);
|
||||
|
||||
@@ -100,25 +100,22 @@ enum fxo_leds {
|
||||
#define DAA_READ 0
|
||||
#define DAA_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \
|
||||
xpp_register_request((xbus), (xpd), (port), \
|
||||
(writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
|
||||
(writing), (reg), 0, 0, (dL), 0, 0, 0)
|
||||
|
||||
/*---------------- FXO Protocol Commands ----------------------------------*/
|
||||
|
||||
static bool fxo_packet_is_valid(xpacket_t *pack);
|
||||
static void fxo_packet_dump(const char *msg, xpacket_t *pack);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops proc_fxo_info_ops;
|
||||
#else
|
||||
static const struct file_operations proc_fxo_info_ops;
|
||||
#endif
|
||||
#ifdef WITH_METERING
|
||||
static const struct proc_ops proc_xpd_metering_ops;
|
||||
static const struct file_operations proc_xpd_metering_ops;
|
||||
#endif
|
||||
#endif
|
||||
static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
|
||||
static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
#define PROC_FXO_INFO_FNAME "fxo_info"
|
||||
#ifdef WITH_METERING
|
||||
#define PROC_METERING_FNAME "metering_read"
|
||||
@@ -491,13 +488,11 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
}
|
||||
|
||||
static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels;
|
||||
int subunit_ports;
|
||||
|
||||
if (to_phone) {
|
||||
XBUS_NOTICE(xbus,
|
||||
@@ -506,14 +501,13 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
unit, subunit);
|
||||
return NULL;
|
||||
}
|
||||
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
|
||||
if (unit_descriptor->subtype == 2)
|
||||
if (subtype == 2)
|
||||
channels = min(2, subunit_ports);
|
||||
else
|
||||
channels = min(8, subunit_ports);
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels);
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct FXO_priv_data), proto_table, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
PHONEDEV(xpd).direction = TO_PSTN;
|
||||
@@ -624,6 +618,7 @@ static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on)
|
||||
BUG_ON(!priv);
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF");
|
||||
for_each_line(xpd, i) {
|
||||
dahdi_report_battery(xpd, i);
|
||||
MARK_OFF(priv, i, LED_GREEN);
|
||||
msleep(2);
|
||||
MARK_OFF(priv, i, LED_RED);
|
||||
@@ -632,23 +627,6 @@ static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FXO_span_assigned(xpd_t *xpd)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
struct FXO_priv_data *priv;
|
||||
int i;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
xbus = xpd->xbus;
|
||||
BUG_ON(!xbus);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
for_each_line(xpd, i)
|
||||
dahdi_report_battery(xpd, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FXO_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
||||
{
|
||||
struct FXO_priv_data *priv;
|
||||
@@ -1269,7 +1247,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
portno = info->h.portnum;
|
||||
portno = info->portnum;
|
||||
switch (REG_FIELD(info, regnum)) {
|
||||
case REG_INTERRUPT_SRC:
|
||||
got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
|
||||
@@ -1287,7 +1265,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
#endif
|
||||
}
|
||||
LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||
((info->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
|
||||
((info->bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
|
||||
REG_FIELD(info, data_low), REG_FIELD(info, data_high));
|
||||
/* Update /proc info only if reply relate to the last slic read request */
|
||||
if (REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
@@ -1334,7 +1312,6 @@ static const struct phoneops fxo_phoneops = {
|
||||
.card_ioctl = FXO_card_ioctl,
|
||||
.card_open = FXO_card_open,
|
||||
.card_state = FXO_card_state,
|
||||
.span_assigned = FXO_span_assigned,
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(FXO) = {
|
||||
@@ -1488,22 +1465,13 @@ static int proc_fxo_info_open(struct inode *inode, struct file *file)
|
||||
return single_open(file, proc_fxo_info_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops proc_fxo_info_ops = {
|
||||
.proc_open = proc_fxo_info_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations proc_fxo_info_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_fxo_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_fxo_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef WITH_METERING
|
||||
static int proc_xpd_metering_show(struct seq_file *sfile, void *not_used)
|
||||
@@ -1585,9 +1553,9 @@ static int fxo_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->xpd_type != XPD_TYPE_FXO) {
|
||||
if (xpd->type != XPD_TYPE_FXO) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->xpd_type);
|
||||
xpd->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -1613,7 +1581,7 @@ static int fxo_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver fxo_driver = {
|
||||
.xpd_type = XPD_TYPE_FXO,
|
||||
.type = XPD_TYPE_FXO,
|
||||
.driver = {
|
||||
.name = "fxo",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1632,6 +1600,7 @@ static int __init card_fxo_startup(void)
|
||||
}
|
||||
if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
#ifdef WITH_METERING
|
||||
INFO("FEATURE: WITH METERING Detection\n");
|
||||
#else
|
||||
@@ -1650,6 +1619,7 @@ static void __exit card_fxo_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP FXO Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_FXO);
|
||||
|
||||
module_init(card_fxo_startup);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,12 +56,12 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
* eoftx==1: Start sending us D-channel packets.
|
||||
* eoftx==0: Stop sending us D-channel packets.
|
||||
*/
|
||||
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit);
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->h.bytes = 0;
|
||||
reg_cmd->h.is_multibyte = 1;
|
||||
reg_cmd->h.portnum = portno;
|
||||
reg_cmd->h.eoframe = eoftx;
|
||||
reg_cmd->bytes = 0;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->eoframe = eoftx;
|
||||
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
|
||||
if (debug & DBG_REGS)
|
||||
dump_xframe(__func__, xbus, xframe, debug);
|
||||
@@ -90,14 +90,13 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
int portno;
|
||||
bool writing;
|
||||
int op; /* [W]rite, [R]ead */
|
||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */
|
||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
|
||||
bool do_subreg = 0;
|
||||
int regnum;
|
||||
int subreg;
|
||||
int data_low;
|
||||
bool do_datah;
|
||||
int data_high;
|
||||
bool do_expander = 0;
|
||||
int ret = -EBADR;
|
||||
|
||||
num_args = 2; /* port + operation */
|
||||
@@ -159,12 +158,6 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
num_args++; /* register */
|
||||
//XPD_DBG(REGS, xpd, "DIRECT\n");
|
||||
break;
|
||||
case 'X':
|
||||
do_subreg = 0;
|
||||
do_expander = 1;
|
||||
num_args++; /* register */
|
||||
//XPD_DBG(REGS, xpd, "EXPANDER\n");
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (op != 'W') {
|
||||
@@ -176,16 +169,6 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
num_args--; /* No data low */
|
||||
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
|
||||
break;
|
||||
case 'R':
|
||||
switch (op) {
|
||||
case 'W':
|
||||
num_args += 5; /* add: addr_high, data_[0-3] */
|
||||
break;
|
||||
case 'R':
|
||||
num_args += 2; /* add: addr_low, addr_high */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
|
||||
goto out;
|
||||
@@ -214,32 +197,6 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
addr_mode == 'm');
|
||||
goto out;
|
||||
}
|
||||
if (addr_mode == 'R') {
|
||||
__u8 input[6];
|
||||
int i;
|
||||
|
||||
if (num_args - 2 > 6) {
|
||||
XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2);
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < num_args - 2; i++, argno++) {
|
||||
int hexbyte= parse_hexbyte(argv[argno]);
|
||||
if (hexbyte < 0) {
|
||||
XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
input[i] = hexbyte;
|
||||
}
|
||||
ret = xpp_ram_request(xpd->xbus, xpd, portno, writing,
|
||||
input[0],
|
||||
input[1],
|
||||
input[2],
|
||||
input[3],
|
||||
input[4],
|
||||
input[5],
|
||||
1);
|
||||
goto out;
|
||||
}
|
||||
/* Normal (non-Magic) register commands */
|
||||
do_datah = 0;
|
||||
if (argno >= argc) {
|
||||
@@ -307,17 +264,17 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
#if 0
|
||||
XPD_DBG(REGS, xpd,
|
||||
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
|
||||
"dataL=%d do_datah=%d dataH=%d do_expander=%d\n",
|
||||
"dataL=%d do_datah=%d dataH=%d\n",
|
||||
portno, /* portno */
|
||||
writing, /* writing */
|
||||
regnum, do_subreg, /* use subreg */
|
||||
subreg, /* subreg */
|
||||
data_low, do_datah, /* use data_high */
|
||||
data_high, do_expander);
|
||||
data_high);
|
||||
#endif
|
||||
ret = xpp_register_request(xpd->xbus, xpd, portno,
|
||||
writing, regnum, do_subreg, subreg,
|
||||
data_low, do_datah, data_high, 1, do_expander);
|
||||
data_low, do_datah, data_high, 1);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -405,7 +362,7 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
|
||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||
__u8 data_low, bool do_datah, __u8 data_high,
|
||||
bool should_reply, bool do_expander)
|
||||
bool should_reply)
|
||||
{
|
||||
int ret = 0;
|
||||
xframe_t *xframe;
|
||||
@@ -416,22 +373,23 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
DBG(REGS, "NO XBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx);
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
|
||||
xpd->xbus_idx);
|
||||
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
|
||||
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
|
||||
data_low, data_high);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
/* do not count the 'bytes' field */
|
||||
reg_cmd->h.bytes = REG_CMD_SIZE(REG);
|
||||
reg_cmd->h.is_multibyte = 0;
|
||||
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
|
||||
reg_cmd->is_multibyte = 0;
|
||||
if (portno == PORT_BROADCAST) {
|
||||
reg_cmd->h.portnum = 0;
|
||||
reg_cmd->portnum = 0;
|
||||
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
|
||||
} else {
|
||||
reg_cmd->h.portnum = portno;
|
||||
reg_cmd->portnum = portno;
|
||||
REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
|
||||
}
|
||||
reg_cmd->h.eoframe = 0;
|
||||
reg_cmd->eoframe = 0;
|
||||
REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
|
||||
REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
|
||||
REG_FIELD(reg_cmd, do_subreg) = do_subreg;
|
||||
@@ -440,12 +398,11 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
REG_FIELD(reg_cmd, do_datah) = do_datah;
|
||||
REG_FIELD(reg_cmd, data_low) = data_low;
|
||||
REG_FIELD(reg_cmd, data_high) = data_high;
|
||||
REG_FIELD(reg_cmd, do_expander) = do_expander;
|
||||
if (should_reply)
|
||||
xpd->requested_reply = *reg_cmd;
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
|
||||
reg_cmd->h.portnum, reg_cmd);
|
||||
reg_cmd->portnum, reg_cmd);
|
||||
dump_packet("REG_REQ", pack, 1);
|
||||
}
|
||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||
@@ -459,67 +416,6 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_register_request);
|
||||
|
||||
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing,
|
||||
__u8 addr_low,
|
||||
__u8 addr_high,
|
||||
__u8 data_0,
|
||||
__u8 data_1,
|
||||
__u8 data_2,
|
||||
__u8 data_3,
|
||||
bool should_reply)
|
||||
{
|
||||
int ret = 0;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
|
||||
if (!xbus) {
|
||||
DBG(REGS, "NO XBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx);
|
||||
LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n",
|
||||
(writing) ? 'W' : 'R',
|
||||
addr_low, addr_high,
|
||||
data_0, data_1, data_2, data_3);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
/* do not count the 'bytes' field */
|
||||
reg_cmd->h.bytes = REG_CMD_SIZE(RAM);
|
||||
reg_cmd->h.is_multibyte = 0;
|
||||
if (portno == PORT_BROADCAST) {
|
||||
reg_cmd->h.portnum = 0;
|
||||
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1;
|
||||
} else {
|
||||
reg_cmd->h.portnum = portno;
|
||||
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0;
|
||||
}
|
||||
reg_cmd->h.eoframe = 0;
|
||||
REG_FIELD_RAM(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
|
||||
REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1;
|
||||
REG_FIELD_RAM(reg_cmd, do_datah) = 1;
|
||||
REG_FIELD_RAM(reg_cmd, do_subreg) = 1;
|
||||
REG_FIELD_RAM(reg_cmd, addr_low) = addr_low;
|
||||
REG_FIELD_RAM(reg_cmd, addr_high) = addr_high;
|
||||
REG_FIELD_RAM(reg_cmd, data_0) = data_0;
|
||||
REG_FIELD_RAM(reg_cmd, data_1) = data_1;
|
||||
REG_FIELD_RAM(reg_cmd, data_2) = data_2;
|
||||
REG_FIELD_RAM(reg_cmd, data_3) = data_3;
|
||||
if (should_reply)
|
||||
xpd->requested_reply = *reg_cmd;
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit,
|
||||
reg_cmd->h.portnum, reg_cmd);
|
||||
dump_packet("REG_RAM", pack, 1);
|
||||
}
|
||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||
xframe->usec_towait = 1000;
|
||||
}
|
||||
ret = send_cmd_frame(xbus, xframe);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_ram_request);
|
||||
|
||||
/*
|
||||
* The XPD parameter is totaly ignored by the driver and firmware as well.
|
||||
*/
|
||||
@@ -615,11 +511,6 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
}
|
||||
if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) {
|
||||
XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n");
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
}
|
||||
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
@@ -649,14 +540,21 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
}
|
||||
card_desc->magic = CARD_DESC_MAGIC;
|
||||
INIT_LIST_HEAD(&card_desc->card_list);
|
||||
card_desc->unit_descriptor = *this_unit;
|
||||
card_desc->type = this_unit->type;
|
||||
card_desc->subtype = this_unit->subtype;
|
||||
card_desc->xpd_addr = this_unit->addr;
|
||||
card_desc->numchips = this_unit->numchips;
|
||||
card_desc->ports_per_chip = this_unit->ports_per_chip;
|
||||
card_desc->port_dir = this_unit->port_dir;
|
||||
card_desc->ports =
|
||||
card_desc->numchips * card_desc->ports_per_chip;
|
||||
XBUS_INFO(xbus,
|
||||
" CARD %d type=%d.%d ports=(%dx%d), "
|
||||
" CARD %d type=%d.%d ports=%d (%dx%d), "
|
||||
"port-dir=0x%02X\n",
|
||||
this_unit->addr.unit, this_unit->type,
|
||||
this_unit->subtype,
|
||||
this_unit->numchips, this_unit->ports_per_chip,
|
||||
this_unit->port_dir);
|
||||
card_desc->xpd_addr.unit, card_desc->type,
|
||||
card_desc->subtype, card_desc->ports,
|
||||
card_desc->numchips, card_desc->ports_per_chip,
|
||||
card_desc->port_dir);
|
||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||
worker->num_units++;
|
||||
XBUS_COUNTER(xbus, UNITS)++;
|
||||
@@ -670,7 +568,6 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
}
|
||||
goto out;
|
||||
proto_err:
|
||||
xbus_setstate(xbus, XBUS_STATE_FAIL);
|
||||
dump_packet("AB_DESCRIPTION", pack, DBG_ANY);
|
||||
out:
|
||||
return ret;
|
||||
@@ -688,7 +585,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
||||
return -EPROTO;
|
||||
}
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
|
||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
|
||||
reg);
|
||||
dump_packet("REG_REPLY", pack, 1);
|
||||
}
|
||||
@@ -803,7 +700,6 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
char xbuslabel[MAX_ENV_STR];
|
||||
char init_card[MAX_PATH_STR];
|
||||
__u8 direction_mask;
|
||||
__u8 hw_type = XPD_HW(xpd).type;
|
||||
int i;
|
||||
char *argv[] = {
|
||||
init_card,
|
||||
@@ -850,9 +746,8 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
|
||||
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
|
||||
xbus->transport.model_string);
|
||||
snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type);
|
||||
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
|
||||
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type);
|
||||
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
|
||||
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
|
||||
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
|
||||
direction_mask);
|
||||
@@ -861,7 +756,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
xbus->connector);
|
||||
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
|
||||
if (snprintf
|
||||
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type,
|
||||
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
|
||||
xbus->revision) > MAX_PATH_STR) {
|
||||
XPD_NOTICE(xpd,
|
||||
"Cannot initialize. pathname is longer "
|
||||
@@ -878,7 +773,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
goto err;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
|
||||
init_card, xpd->xpd_type, xbus->revision);
|
||||
init_card, xpd->type, xbus->revision);
|
||||
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
|
||||
/*
|
||||
* Carefully report results
|
||||
|
||||
@@ -74,18 +74,9 @@ DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
|
||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||
__u8 data_low, bool do_datah, __u8 data_high,
|
||||
bool should_reply, bool do_expander);
|
||||
bool should_reply);
|
||||
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
bool eoftx, __u8 *buf, unsigned len);
|
||||
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing,
|
||||
__u8 addr_low,
|
||||
__u8 addr_high,
|
||||
__u8 data_0,
|
||||
__u8 data_1,
|
||||
__u8 data_2,
|
||||
__u8 data_3,
|
||||
bool should_reply);
|
||||
extern xproto_table_t PROTO_TABLE(GLOBAL);
|
||||
int run_initialize_registers(xpd_t *xpd);
|
||||
int parse_chip_command(xpd_t *xpd, char *cmdline);
|
||||
|
||||
@@ -85,6 +85,8 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig);
|
||||
static void send_idlebits(xpd_t *xpd, bool saveold);
|
||||
static int apply_pri_protocol(xpd_t *xpd);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
|
||||
enum pri_protocol {
|
||||
PRI_PROTO_0 = 0,
|
||||
PRI_PROTO_E1 = 1,
|
||||
@@ -388,8 +390,7 @@ static int query_subunit(xpd_t *xpd, __u8 regnum)
|
||||
0, /* data_L */
|
||||
0, /* do_datah */
|
||||
0, /* data_H */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
0 /* should_reply */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -405,8 +406,7 @@ static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
|
||||
val, /* data_L */
|
||||
0, /* do_datah */
|
||||
0, /* data_H */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
0 /* should_reply */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -421,8 +421,7 @@ static int pri_write_reg(xpd_t *xpd, int regnum, __u8 val)
|
||||
val, /* data_L */
|
||||
0, /* do_datah */
|
||||
0, /* data_H */
|
||||
0, /* should_reply */
|
||||
0 /* do_expander */
|
||||
0 /* should_reply */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -525,12 +524,9 @@ static void PRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
|
||||
//XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
|
||||
/* Add/remove all the trivial cases */
|
||||
pcm_mask |= PHONEDEV(xpd).offhook_state;
|
||||
if (priv->is_cas)
|
||||
pcm_mask |= BITMASK(PHONEDEV(xpd).channels);
|
||||
for_each_line(xpd, i)
|
||||
if (IS_SET(pcm_mask, i))
|
||||
line_count++;
|
||||
else
|
||||
if (priv->is_cas) {
|
||||
if (priv->pri_protocol == PRI_PROTO_E1) {
|
||||
/* CAS: Don't send PCM to D-Channel */
|
||||
@@ -615,7 +611,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
}
|
||||
priv->pri_protocol = set_proto;
|
||||
priv->is_cas = -1;
|
||||
phonedev_alloc_channels(xpd, pri_num_channels(set_proto));
|
||||
phonedev->channels = pri_num_channels(set_proto);
|
||||
phonedev->offhook_state = BITMASK(phonedev->channels);
|
||||
CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
|
||||
priv->deflaw = deflaw;
|
||||
@@ -708,7 +704,7 @@ static void set_clocking(xpd_t *xpd)
|
||||
/* Now set it */
|
||||
if (best_xpd
|
||||
&& ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) {
|
||||
__u8 reg_pc_init[] = { VAL_PC_SYPR, VAL_PC_GPI, VAL_PC_GPI };
|
||||
__u8 reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI };
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) {
|
||||
__u8 reg_pc = reg_pc_init[i];
|
||||
@@ -1086,7 +1082,6 @@ static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype)
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
enum pri_protocol set_proto = PRI_PROTO_0;
|
||||
int ret;
|
||||
|
||||
XPD_INFO(xpd, "%s: %s\n", __func__, dahdi_spantype2str(spantype));
|
||||
switch (spantype) {
|
||||
@@ -1104,13 +1099,7 @@ static int pri_set_spantype(struct dahdi_span *span, enum spantypes spantype)
|
||||
__func__, dahdi_spantype2str(spantype));
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = set_pri_proto(xpd, set_proto);
|
||||
if (ret < 0) {
|
||||
XPD_ERR(xpd, "%s: set_pri_proto failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
dahdi_init_span(span);
|
||||
return 0;
|
||||
return set_pri_proto(xpd, set_proto);
|
||||
}
|
||||
|
||||
static int PRI_card_open(xpd_t *xpd, lineno_t pos)
|
||||
@@ -1235,7 +1224,7 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0)
|
||||
set_mode_cas(xpd, 0);
|
||||
} else {
|
||||
if (chan->chanpos == 1) {
|
||||
if (chan->channo == 1) {
|
||||
XPD_DBG(GENERAL, xpd,
|
||||
"channel %d (%s) marked a not DChan\n",
|
||||
chan->channo, chan->name);
|
||||
@@ -1256,29 +1245,21 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||
}
|
||||
|
||||
static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table,
|
||||
const struct unit_descriptor *unit_descriptor,
|
||||
bool to_phone)
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
struct PRI_priv_data *priv;
|
||||
int channels = min(31, CHANNELS_PERXPD); /* worst case */
|
||||
|
||||
if ((unit_descriptor->ports_per_chip < 1) ||
|
||||
(unit_descriptor->ports_per_chip > 4)) {
|
||||
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
|
||||
unit_descriptor->ports_per_chip);
|
||||
return NULL;
|
||||
}
|
||||
if (unit_descriptor->numchips != 1) {
|
||||
XBUS_ERR(xbus, "Bad numchips=%d\n",
|
||||
unit_descriptor->numchips);
|
||||
if (subunit_ports != 1) {
|
||||
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit,
|
||||
sizeof(struct PRI_priv_data), proto_table, unit_descriptor, channels);
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct PRI_priv_data), proto_table, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
priv = xpd->priv;
|
||||
@@ -1298,7 +1279,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
|
||||
BUG_ON(!xpd);
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
xpd->xpd_type = XPD_TYPE_PRI;
|
||||
xpd->type = XPD_TYPE_PRI;
|
||||
priv = xpd->priv;
|
||||
if (priv->pri_protocol == PRI_PROTO_0) {
|
||||
/*
|
||||
@@ -1948,8 +1929,7 @@ static void PRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
||||
dchan_state(xpd, 0);
|
||||
}
|
||||
if (IS_SET(physical_mask, i)) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, logical_chan);
|
||||
r = chan->readchunk;
|
||||
r = XPD_CHAN(xpd, logical_chan)->readchunk;
|
||||
// memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG
|
||||
memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
|
||||
pcm += DAHDI_CHUNKSIZE;
|
||||
@@ -2264,7 +2244,7 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/* Map UNIT + PORTNUM to XPD */
|
||||
orig_xpd = xpd;
|
||||
addr.unit = orig_xpd->addr.unit;
|
||||
addr.subunit = info->h.portnum;
|
||||
addr.subunit = info->portnum;
|
||||
regnum = REG_FIELD(info, regnum);
|
||||
data_low = REG_FIELD(info, data_low);
|
||||
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
|
||||
@@ -2278,9 +2258,9 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if (info->h.is_multibyte) {
|
||||
if (info->is_multibyte) {
|
||||
XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
|
||||
info->h.bytes, info->h.eoframe);
|
||||
info->bytes, info->eoframe);
|
||||
goto end;
|
||||
}
|
||||
if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg))
|
||||
@@ -2408,11 +2388,11 @@ static DEVICE_ATTR_WRITER(pri_protocol_store, dev, buf, count)
|
||||
buf, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (strncasecmp(buf, "E1", 2) == 0)
|
||||
if (strnicmp(buf, "E1", 2) == 0)
|
||||
new_protocol = PRI_PROTO_E1;
|
||||
else if (strncasecmp(buf, "T1", 2) == 0)
|
||||
else if (strnicmp(buf, "T1", 2) == 0)
|
||||
new_protocol = PRI_PROTO_T1;
|
||||
else if (strncasecmp(buf, "J1", 2) == 0)
|
||||
else if (strnicmp(buf, "J1", 2) == 0)
|
||||
new_protocol = PRI_PROTO_J1;
|
||||
else {
|
||||
XPD_NOTICE(xpd,
|
||||
@@ -2646,9 +2626,9 @@ static int pri_xpd_probe(struct device *dev)
|
||||
|
||||
xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (xpd->xpd_type != XPD_TYPE_PRI) {
|
||||
if (xpd->type != XPD_TYPE_PRI) {
|
||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
xpd->xpd_type);
|
||||
xpd->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||
@@ -2731,7 +2711,7 @@ static int pri_xpd_remove(struct device *dev)
|
||||
}
|
||||
|
||||
static struct xpd_driver pri_driver = {
|
||||
.xpd_type = XPD_TYPE_PRI,
|
||||
.type = XPD_TYPE_PRI,
|
||||
.driver = {
|
||||
.name = "pri",
|
||||
.owner = THIS_MODULE,
|
||||
@@ -2745,6 +2725,7 @@ static int __init card_pri_startup(void)
|
||||
|
||||
if ((ret = xpd_driver_register(&pri_driver.driver)) < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
#ifdef DAHDI_AUDIO_NOTIFY
|
||||
INFO("FEATURE: WITH DAHDI_AUDIO_NOTIFY\n");
|
||||
#else
|
||||
@@ -2764,6 +2745,7 @@ static void __exit card_pri_cleanup(void)
|
||||
MODULE_DESCRIPTION("XPP PRI Card Driver");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(XPP_VERSION);
|
||||
MODULE_ALIAS_XPD(XPD_TYPE_PRI);
|
||||
|
||||
module_init(card_pri_startup);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
FPGA_1161.201.hex
|
||||
@@ -3,13 +3,12 @@
|
||||
|
||||
USB_FW = USB_FW.hex USB_FW.201.hex USB_RECOV.hex
|
||||
FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex \
|
||||
FPGA_1161.201.hex FPGA_1161.202.hex
|
||||
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex \
|
||||
PIC_TYPE_6.hex
|
||||
FPGA_1161.201.hex
|
||||
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
|
||||
OCT_FW = $(wildcard OCT6104E-256D.ima)
|
||||
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
|
||||
PROTO_VER = 30
|
||||
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5 6)
|
||||
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5)
|
||||
SCRIPTS = $(SCRIPTS_BASE:%=../%)
|
||||
TARGET = $(DESTDIR)/usr/share/dahdi
|
||||
|
||||
@@ -21,12 +20,4 @@ install:
|
||||
mkdir -p $(TARGET)
|
||||
install $(SCRIPTS) $(TARGET)/
|
||||
install -m 644 ../XppConfig.pm $(FIRMWARES) $(TARGET)/
|
||||
for id in 202 203; do \
|
||||
if [ ! -r $(TARGET)/USB_FW.$$id.hex ]; then \
|
||||
ln -s USB_FW.201.hex $(TARGET)/USB_FW.$$id.hex;\
|
||||
fi; \
|
||||
done
|
||||
if [ ! -r $(TARGET)/FPGA_1161.203.hex ]; then \
|
||||
ln -s FPGA_1161.201.hex $(TARGET)/FPGA_1161.203.hex;\
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,460 +0,0 @@
|
||||
#
|
||||
# $Id: PIC_TYPE_6.hex 11526 2016-04-05 13:30:04Z dima $
|
||||
#
|
||||
:03000000A1CA5042
|
||||
:03000100C41C41DB
|
||||
:0300020069969963
|
||||
:03000300D50D50C8
|
||||
:030004000390392D
|
||||
:0300050067967982
|
||||
:03000600A05A05F8
|
||||
:03000700C40C40E6
|
||||
:030008006996995D
|
||||
:03000900D50D50C2
|
||||
:03000A0003903927
|
||||
:03000B007797796B
|
||||
:03000C00A0BA0B8C
|
||||
:03000D0080080068
|
||||
:03000E00F01F01DF
|
||||
:03000F00022022AA
|
||||
:03001000C05C05CC
|
||||
:0300110002402486
|
||||
:03001200C00C001F
|
||||
:03001300021021B7
|
||||
:030014003613613F
|
||||
:03001500202202A4
|
||||
:03001600E01E01E8
|
||||
:03001700121121A2
|
||||
:030018003223226E
|
||||
:030019002E42E490
|
||||
:03001A00A14A14E4
|
||||
:03001B008008005A
|
||||
:03001C00C0010B15
|
||||
:03001D0019A038EF
|
||||
:03001E00743C57D8
|
||||
:03001F00A24D40AF
|
||||
:03002000C01034D9
|
||||
:030021001CCC42B2
|
||||
:03002200E07D017D
|
||||
:0300230002C021F7
|
||||
:03002400C07C138A
|
||||
:0300250018C024DC
|
||||
:03002600643C0433
|
||||
:03002700A4C0373B
|
||||
:0300280020C201F2
|
||||
:03002900743032FE
|
||||
:03002A00AC3204F1
|
||||
:03002B0021A031E0
|
||||
:03002C0090E2025D
|
||||
:03002D00C20030DE
|
||||
:03002E00D40901F1
|
||||
:03002F00121C00A0
|
||||
:03003000C1E037F5
|
||||
:03003100024C423C
|
||||
:03003200C00021EA
|
||||
:03003300022202A4
|
||||
:03003400201FFF8B
|
||||
:0300350003015074
|
||||
:030036009016B968
|
||||
:0300370020410263
|
||||
:03003800030022A0
|
||||
:03003900901C0414
|
||||
:03003A002020374C
|
||||
:03003B00030201BC
|
||||
:03003C00901032EF
|
||||
:03003D00C11204E9
|
||||
:03003E0019003175
|
||||
:03003F0064320226
|
||||
:03004000A4503099
|
||||
:03004100C22901D0
|
||||
:03004200190C0096
|
||||
:03004300743037DF
|
||||
:03004400A48C0782
|
||||
:03004500209D40BB
|
||||
:0300460012503421
|
||||
:03004700A4B8005A
|
||||
:03004800209214EF
|
||||
:03004900FFFE7047
|
||||
:03004A0016530842
|
||||
:03004B00AC3308CB
|
||||
:03004C0021A308E5
|
||||
:03004D0090E30835
|
||||
:03004E00C20027C6
|
||||
:03004F00D40800D2
|
||||
:03005000121C007F
|
||||
:03005100209039C3
|
||||
:030052001450380F
|
||||
:0300530064303FD7
|
||||
:03005400AC3C07BA
|
||||
:03005500C22D4079
|
||||
:0300560002403431
|
||||
:03005700C00C08D2
|
||||
:030058000220384B
|
||||
:0300590020121959
|
||||
:03005A00030E078B
|
||||
:03005B00901020E2
|
||||
:03005C00204360DE
|
||||
:03005D000303603A
|
||||
:03005E009013609C
|
||||
:03005F00202360FB
|
||||
:03006000030C107E
|
||||
:03006100901038C4
|
||||
:03006200C02219A0
|
||||
:03006300150E0770
|
||||
:03006400643120E4
|
||||
:03006500A69C183E
|
||||
:03006600209038AF
|
||||
:0300670013E21988
|
||||
:03006800A6CE0F12
|
||||
:03006900209022C2
|
||||
:03006A00FFFC0098
|
||||
:03006B0017E03863
|
||||
:03006C0021E2008E
|
||||
:03006D00035E0728
|
||||
:03006E00C13CFF93
|
||||
:03006F000240311B
|
||||
:03007000C00C18A9
|
||||
:03007100022A72EE
|
||||
:0300720020103C1F
|
||||
:0300730003003057
|
||||
:03007400901E0FCC
|
||||
:0300750020403CEC
|
||||
:03007600030C0276
|
||||
:03007700901039AD
|
||||
:03007800202C0039
|
||||
:0300790003003948
|
||||
:03007A00901C0FC8
|
||||
:03007B002100223F
|
||||
:03007C00027C8083
|
||||
:03007D00C3C024D9
|
||||
:03007E00024C0829
|
||||
:03007F00C00104B9
|
||||
:0300800002203922
|
||||
:03008100201C0040
|
||||
:030082000300393F
|
||||
:03008300901C00CE
|
||||
:0300840020403ADF
|
||||
:0300850003002B4A
|
||||
:03008600901020B7
|
||||
:03008700202C0327
|
||||
:0300880003002C46
|
||||
:03008900901C4088
|
||||
:03008A0021003919
|
||||
:03008B0003B7D9DF
|
||||
:03008C00787A8BF4
|
||||
:03008D00A91C406B
|
||||
:03008E0020903986
|
||||
:03008F0013F6D98C
|
||||
:03009000A99A9496
|
||||
:030091002096F9BD
|
||||
:0300920015FBB4A7
|
||||
:03009300643A8F3D
|
||||
:03009400AC367314
|
||||
:030095006BBA9CA7
|
||||
:03009600AC39483A
|
||||
:03009700209207AD
|
||||
:030098001BF90E43
|
||||
:03009900C50C2073
|
||||
:03009A00039121AE
|
||||
:03009B00799AC48B
|
||||
:03009C00A9BC57A5
|
||||
:03009D0020B0345C
|
||||
:03009E00D00C4241
|
||||
:03009F00038021BA
|
||||
:0300A000219C019F
|
||||
:0300A100E07121EA
|
||||
:0300A200348C009B
|
||||
:0300A30034802284
|
||||
:0300A400348C0495
|
||||
:0300A5003480376D
|
||||
:0300A60003020151
|
||||
:0300A70021A03263
|
||||
:0300A8003482158A
|
||||
:0300A9003480316F
|
||||
:0300AA003482029B
|
||||
:0300AB003480306E
|
||||
:0300AC00D0590127
|
||||
:0300AD00031C0031
|
||||
:0300AE00C0003758
|
||||
:0300AF000326D352
|
||||
:0300B000033ADB35
|
||||
:0300B100C70CFF7A
|
||||
:0300B2000391981F
|
||||
:0300B300C5015034
|
||||
:0300B4000391179E
|
||||
:0300B500C3C022A3
|
||||
:0300B600030C42F6
|
||||
:0300B700C0002165
|
||||
:0300B800031C0422
|
||||
:0300B90021B0373C
|
||||
:0300BA000322011D
|
||||
:0300BB00C0003250
|
||||
:0300BC00033215F7
|
||||
:0300BD00C7003148
|
||||
:0300BE00039202A8
|
||||
:0300BF00C5003049
|
||||
:0300C000039901A0
|
||||
:0300C100C40C006C
|
||||
:0300C20003903771
|
||||
:0300C300369ADB8F
|
||||
:0300C400C01C80DD
|
||||
:0300C5001FA6F380
|
||||
:0300C60021C12134
|
||||
:0300C70009A6B3D4
|
||||
:0300C800743B077F
|
||||
:0300C900A1C7D3F9
|
||||
:0300CA0003AAD0B6
|
||||
:0300CB00C02C4006
|
||||
:0300CC00FFF12120
|
||||
:0300CD0016BC005E
|
||||
:0300CE00C020222D
|
||||
:0300CF0023EAD24F
|
||||
:0300D00074321770
|
||||
:0300D10012B02248
|
||||
:0300D20020B20158
|
||||
:0300D30003803077
|
||||
:0300D400C449011B
|
||||
:0300D5000392157E
|
||||
:0300D600C4003033
|
||||
:0300D70003990189
|
||||
:0300D800C0020261
|
||||
:0300D900023030C2
|
||||
:0300DA00A8D901A1
|
||||
:0300DB00ADBC07B2
|
||||
:0300DC00000D40D4
|
||||
:0300DD00000034EC
|
||||
:0300DE000002100D
|
||||
:0300DF00000024FA
|
||||
:0300E0000007D343
|
||||
:0300E100000BAF62
|
||||
:0300E200000C50BF
|
||||
:0300E300000039E1
|
||||
:0300E40000079979
|
||||
:0300E500000AE42A
|
||||
:0300E60000021203
|
||||
:0300E700000030E6
|
||||
:0300E800000214FF
|
||||
:0300E900000031E3
|
||||
:0300EA00000213FE
|
||||
:0300EB00000032E0
|
||||
:0300EC00000C08FD
|
||||
:0300ED00000037D9
|
||||
:0300EE00000218F5
|
||||
:0300EF00000036D8
|
||||
:0300F000000217F4
|
||||
:0300F100000033D9
|
||||
:0300F200000C00FF
|
||||
:0300F300000037D3
|
||||
:0300F400000C708D
|
||||
:0300F500000039CF
|
||||
:0300F600000C50AB
|
||||
:0300F700000039CD
|
||||
:0300F800000215EE
|
||||
:0300F900000030D4
|
||||
:0300FA00000C00F7
|
||||
:0300FB00000031D1
|
||||
:0300FC00000C00F5
|
||||
:0300FD00000033CD
|
||||
:0300FE00000204F9
|
||||
:0300FF00000032CC
|
||||
:03010000000C7080
|
||||
:03010100000039C2
|
||||
:03010200000C509E
|
||||
:03010300000039C0
|
||||
:03010400000C40AC
|
||||
:03010500000039BE
|
||||
:03010600000BAF3C
|
||||
:03010700000C05E4
|
||||
:03010800000024D0
|
||||
:03010900000216DB
|
||||
:03010A00000022D0
|
||||
:03010B00000C07DE
|
||||
:03010C000001628D
|
||||
:03010D00000C08DB
|
||||
:03010E00000122CB
|
||||
:03010F0000036288
|
||||
:03011000000703E2
|
||||
:03011100000B0FD1
|
||||
:03011200000CE0FE
|
||||
:0301130000016286
|
||||
:03011400000201E5
|
||||
:03011500000030B7
|
||||
:03011600000901DC
|
||||
:03011700000204DF
|
||||
:03011800000030B4
|
||||
:03011900000901D9
|
||||
:03011A00000202DE
|
||||
:03011B00000030B1
|
||||
:03011C00000901D6
|
||||
:03011D000007D305
|
||||
:03011E00000B4192
|
||||
:03011F00000C0AC7
|
||||
:03012000000024B8
|
||||
:03012100000215C4
|
||||
:03012200000022B8
|
||||
:03012300000201D6
|
||||
:03012400000030A8
|
||||
:03012500000901CD
|
||||
:03012600000204D0
|
||||
:03012700000030A5
|
||||
:03012800000901CA
|
||||
:03012900000202CF
|
||||
:03012A00000030A2
|
||||
:03012B00000901C7
|
||||
:03012C00000C0ABA
|
||||
:03012D00000027A8
|
||||
:03012E00000C4082
|
||||
:03012F00000121AB
|
||||
:03013000000C04BC
|
||||
:03013100000024A7
|
||||
:03013200000C00BE
|
||||
:03013300000022A7
|
||||
:03013400000201C5
|
||||
:0301350000003097
|
||||
:03013600000901BC
|
||||
:03013700000204BF
|
||||
:0301380000003094
|
||||
:03013900000901B9
|
||||
:03013A00000202BE
|
||||
:03013B0000003091
|
||||
:03013C00000901B6
|
||||
:03013D000002E7D6
|
||||
:03013E00000710A7
|
||||
:03013F00000B4171
|
||||
:03014000000B347D
|
||||
:03014100000C08A7
|
||||
:0301420000003783
|
||||
:03014300000C09A4
|
||||
:0301440000002494
|
||||
:030145000002189D
|
||||
:0301460000002294
|
||||
:03014700000201B2
|
||||
:0301480000003084
|
||||
:03014900000901A9
|
||||
:03014A00000204AC
|
||||
:03014B0000003081
|
||||
:03014C00000901A6
|
||||
:03014D00000202AB
|
||||
:03014E000000307E
|
||||
:03014F00000901A3
|
||||
:030150000002109A
|
||||
:0301510000002784
|
||||
:03015200000C0896
|
||||
:0301530000002485
|
||||
:030154000002178F
|
||||
:0301550000002285
|
||||
:03015600000C009A
|
||||
:030157000000376E
|
||||
:03015800000201A1
|
||||
:0301590000003073
|
||||
:03015A0000090198
|
||||
:03015B000002049B
|
||||
:03015C0000003070
|
||||
:03015D0000090195
|
||||
:03015E000002029A
|
||||
:03015F000000306D
|
||||
:0301600000090192
|
||||
:030161000007D3C1
|
||||
:03016200000B751A
|
||||
:03016300000C503D
|
||||
:030164000000395F
|
||||
:03016500000799F7
|
||||
:03016600000B6526
|
||||
:0301670000021281
|
||||
:0301680000003064
|
||||
:030169000002147D
|
||||
:03016A0000003161
|
||||
:03016B000002137C
|
||||
:03016C000000325E
|
||||
:03016D0000020786
|
||||
:03016E0000003658
|
||||
:03016F000002107B
|
||||
:0301700000003359
|
||||
:03017100000C700F
|
||||
:0301720000003951
|
||||
:03017300000C502D
|
||||
:030174000000394F
|
||||
:03017500000C0774
|
||||
:0301760000002462
|
||||
:030177000002186B
|
||||
:0301780000002262
|
||||
:0301790000020180
|
||||
:03017A0000003052
|
||||
:03017B0000090177
|
||||
:03017C000002047A
|
||||
:03017D000000304F
|
||||
:03017E0000090174
|
||||
:03017F0000020279
|
||||
:030180000000304C
|
||||
:0301810000090171
|
||||
:0301820000021068
|
||||
:0301830000002752
|
||||
:03018400000C0666
|
||||
:0301850000002453
|
||||
:030186000002175D
|
||||
:0301870000002253
|
||||
:0301880000020171
|
||||
:0301890000003043
|
||||
:03018A0000090168
|
||||
:03018B000002046B
|
||||
:03018C0000003040
|
||||
:03018D0000090165
|
||||
:03018E000002026A
|
||||
:03018F000000303D
|
||||
:0301900000090162
|
||||
:030191000007D391
|
||||
:03019200000BA2BD
|
||||
:0301930000021552
|
||||
:0301940000003038
|
||||
:030195000002164F
|
||||
:0301960000003135
|
||||
:030197000002075C
|
||||
:0301980000003331
|
||||
:0301990000021051
|
||||
:03019A0000003230
|
||||
:03019B00000C70E5
|
||||
:03019C0000003927
|
||||
:03019D00000C5003
|
||||
:03019E0000003925
|
||||
:03019F00000C4011
|
||||
:0301A00000003923
|
||||
:0301A100000BAFA1
|
||||
:0301A200000C0A44
|
||||
:0301A30000002435
|
||||
:0301A40000021541
|
||||
:0301A50000002235
|
||||
:0301A60000020153
|
||||
:0301A70000003025
|
||||
:0301A8000009014A
|
||||
:0301A9000002044D
|
||||
:0301AA0000003022
|
||||
:0301AB0000090147
|
||||
:0301AC000002024C
|
||||
:0301AD000000301F
|
||||
:0301AE0000090144
|
||||
:0301AF00000C0041
|
||||
:0301B00000003913
|
||||
:0301B100000C003F
|
||||
:0301B200000C003E
|
||||
:0301B300000A8DB2
|
||||
:0301B400000C0735
|
||||
:0301B50000002F18
|
||||
:0301B600000C0436
|
||||
:0301B70000002223
|
||||
:0301B800000C0038
|
||||
:0301B90000091C1E
|
||||
:0301BA00000C1026
|
||||
:0301BB000000221F
|
||||
:0301BC00000C082C
|
||||
:0301BD0000091C1A
|
||||
:0301BE00000C0032
|
||||
:0301BF0000003A03
|
||||
:0301C000000C012F
|
||||
:0301C10000002912
|
||||
:0301C200000C002E
|
||||
:0301C30000002F0A
|
||||
:0301C400000C200C
|
||||
:0301C50000002314
|
||||
:0301C600000A002C
|
||||
:0301C700000BC763
|
||||
:00000001FF
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
USB_FW.201.hex
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# $Id: USB_FW.hex 11452 2015-03-29 18:21:13Z dima $
|
||||
# $Id: USB_FW.hex 10401 2012-02-15 15:30:24Z dima $
|
||||
#
|
||||
:03004300021F0099
|
||||
:03005300021F0089
|
||||
@@ -27,7 +27,7 @@
|
||||
:051EF1000300000000E9
|
||||
:1011F50041E0370041E0B70042E0B2000041E0388D
|
||||
:1012050000021BE0860218E07A43E0B40000004EBD
|
||||
:10121500E03931313435314D502020202020200057
|
||||
:10121500E03931303339354D502020202020200051
|
||||
:101D9A008B518A528953E5561556AE557002155520
|
||||
:101DAA004E6014AB510553E553AA52700205521402
|
||||
:081DBA00F9ED12077180DF2230
|
||||
@@ -165,7 +165,7 @@
|
||||
:100B7800AB43AA44A9457401120771E4F54EE54E4A
|
||||
:100B8800C454F0AB43AA44A94590000112078385D9
|
||||
:100B98004656854757854858755908121A94AB46E2
|
||||
:100BA800AA47A948900002120744FE5407FFEE54D2
|
||||
:100BA800AA47A948900002120744FE5403FFEE54D6
|
||||
:100BB80070F54F24E0602924F0604B24F0605D2438
|
||||
:100BC800F0606F24406003020C50753F01851840A7
|
||||
:100BD800851941EF24FE600624FE703B801C801FAF
|
||||
|
||||
@@ -59,7 +59,6 @@ my %settings;
|
||||
$settings{debug} = 0;
|
||||
$settings{fxs_skip_calib} = 0;
|
||||
my $chipregs;
|
||||
my $ring_registers;
|
||||
|
||||
sub logit {
|
||||
print STDERR "$unit_id: @_\n";
|
||||
@@ -94,7 +93,7 @@ if (-t STDERR) {
|
||||
}
|
||||
}
|
||||
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
|
||||
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/20.}) {
|
||||
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
|
||||
$eeprom_release_201 = 1;
|
||||
}
|
||||
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
|
||||
@@ -105,10 +104,6 @@ if (-t STDERR) {
|
||||
logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
|
||||
if -f $chipregs;
|
||||
}
|
||||
$ring_registers = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/fxs_ring_registers",
|
||||
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
|
||||
logit "OLD DRIVER: missing '$ring_registers' -- fallback to hard-coded defaults"
|
||||
unless -f $ring_registers;
|
||||
}
|
||||
|
||||
sub set_output() {
|
||||
@@ -152,16 +147,6 @@ sub write_to_slic_file($) {
|
||||
|
||||
}
|
||||
|
||||
sub write_to_ring_register($) {
|
||||
my $write_str = shift;
|
||||
|
||||
open(SLICS,">$ring_registers") or
|
||||
die("Failed writing to ring_registers file $ring_registers");
|
||||
print SLICS $write_str;
|
||||
close(SLICS) or die "Failed writing '$write_str' to '$ring_registers': $!";
|
||||
main::mysleep(0.001);
|
||||
}
|
||||
|
||||
sub read_reg($$$) {
|
||||
my $read_slic = shift;
|
||||
my $read_reg = shift;
|
||||
@@ -313,7 +298,7 @@ sub init_early_direct_regs() {
|
||||
return write_to_slic_file("#
|
||||
* WD 08 00 # Audio Path Loopback Control
|
||||
* WD 6C 01
|
||||
* WD 4A 34 # High Battery Voltage
|
||||
* WD 4A 3F # High Battery Voltage
|
||||
* WD 4B $lbv # Low Battery Voltage
|
||||
* WD 49 $vcm # Common Mode Voltage (VCM)
|
||||
* WD 40 00 # Line Feed Control
|
||||
@@ -457,10 +442,6 @@ sub check_slics() {
|
||||
return @slics;
|
||||
}
|
||||
|
||||
sub overwrite_ring_registers() {
|
||||
write_to_ring_register("NEON 0x33 0x12");
|
||||
}
|
||||
|
||||
package main;
|
||||
|
||||
main::debug "Starting '$0'";
|
||||
@@ -489,7 +470,6 @@ while(<DATA>) {
|
||||
print "$_\n";
|
||||
}
|
||||
close REG;
|
||||
FXS::overwrite_ring_registers();
|
||||
|
||||
main::debug "Ending '$0'";
|
||||
close STDERR;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,6 @@
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/blackfin.h>
|
||||
@@ -561,6 +560,9 @@ static int __init xpp_mmap_init(void)
|
||||
xframe_cache =
|
||||
kmem_cache_create("xframe_cache",
|
||||
sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||
NULL,
|
||||
#endif
|
||||
NULL);
|
||||
if (!xframe_cache) {
|
||||
ret = -ENOMEM;
|
||||
|
||||
@@ -103,6 +103,7 @@ void __exit parallel_dbg_cleanup(void)
|
||||
MODULE_DESCRIPTION("Use parallel port to debug drivers");
|
||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("$Id:");
|
||||
|
||||
module_init(parallel_dbg_init);
|
||||
module_exit(parallel_dbg_cleanup);
|
||||
|
||||
@@ -24,10 +24,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
#include <linux/ctype.h>
|
||||
#endif
|
||||
@@ -50,15 +48,8 @@ static const char rcsid[] = "$Id$";
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#define PROC_XBUS_COMMAND "command"
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops proc_xbus_command_ops;
|
||||
#else
|
||||
static const struct file_operations proc_xbus_command_ops;
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Command line parameters */
|
||||
@@ -68,19 +59,12 @@ static DEF_PARM(uint, command_queue_length, 1500, 0444,
|
||||
static DEF_PARM(uint, poll_timeout, 1000, 0644,
|
||||
"Timeout (in jiffies) waiting for units to reply");
|
||||
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
|
||||
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0444,
|
||||
"Register devices automatically (1) or not (0). UNUSED.");
|
||||
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
|
||||
"Register devices automatically (1) or not (0)");
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops xbus_read_proc_ops;
|
||||
#else
|
||||
static const struct file_operations xbus_read_proc_ops;
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
#endif
|
||||
static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
|
||||
ushort max_send_size,
|
||||
struct device *transport_device, void *priv);
|
||||
@@ -94,14 +78,8 @@ static struct proc_dir_entry *proc_xbuses;
|
||||
|
||||
static struct xbus_desc {
|
||||
xbus_t *xbus;
|
||||
int shutting_down;
|
||||
} xbuses_array[MAX_BUSES];
|
||||
|
||||
static int xbus_is_shutting_down(int num)
|
||||
{
|
||||
return xbuses_array[num].shutting_down;
|
||||
}
|
||||
|
||||
static xbus_t *xbus_byhwid(const char *hwid)
|
||||
{
|
||||
int i;
|
||||
@@ -169,8 +147,6 @@ static void init_xbus(uint num, xbus_t *xbus)
|
||||
BUG_ON(num >= ARRAY_SIZE(xbuses_array));
|
||||
desc = &xbuses_array[num];
|
||||
desc->xbus = xbus;
|
||||
if (xbus)
|
||||
desc->shutting_down = 0;
|
||||
}
|
||||
|
||||
xbus_t *xbus_num(uint num)
|
||||
@@ -210,12 +186,9 @@ static void finalize_xbuses_array(void)
|
||||
static void xbus_destroy(struct kref *kref)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int num;
|
||||
|
||||
xbus = kref_to_xbus(kref);
|
||||
XBUS_DBG(DEVICES, xbus, "%s\n", __func__);
|
||||
num = xbus->num;
|
||||
xbuses_array[num].shutting_down = 1;
|
||||
XBUS_NOTICE(xbus, "%s\n", __func__);
|
||||
xbus_sysfs_remove(xbus);
|
||||
}
|
||||
|
||||
@@ -224,11 +197,6 @@ xbus_t *get_xbus(const char *msg, uint num)
|
||||
unsigned long flags;
|
||||
xbus_t *xbus;
|
||||
|
||||
if (xbus_is_shutting_down(num)) {
|
||||
DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n", __func__,
|
||||
msg, num);
|
||||
return NULL;
|
||||
}
|
||||
spin_lock_irqsave(&xbuses_lock, flags);
|
||||
xbus = xbus_num(num);
|
||||
if (xbus != NULL) {
|
||||
@@ -242,13 +210,6 @@ xbus_t *get_xbus(const char *msg, uint num)
|
||||
|
||||
void put_xbus(const char *msg, xbus_t *xbus)
|
||||
{
|
||||
if (xbus_is_shutting_down(xbus->num)) {
|
||||
if (!refcount_xbus(xbus)) {
|
||||
DBG(DEVICES, "%s(%s): XBUS-%d: shutting down\n",
|
||||
__func__, msg, xbus->num);
|
||||
return;
|
||||
}
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg,
|
||||
refcount_xbus(xbus));
|
||||
kref_put(&xbus->kref, xbus_destroy);
|
||||
@@ -258,7 +219,7 @@ int refcount_xbus(xbus_t *xbus)
|
||||
{
|
||||
struct kref *kref = &xbus->kref;
|
||||
|
||||
return refcount_read(&kref->refcount);
|
||||
return atomic_read(&kref->refcount);
|
||||
}
|
||||
|
||||
/*------------------------- Frame Handling ------------------------*/
|
||||
@@ -273,7 +234,7 @@ void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
|
||||
xframe->packets = xframe->first_free = buf;
|
||||
xframe->frame_maxlen = maxsize;
|
||||
atomic_set(&xframe->frame_len, 0);
|
||||
xframe->kt_created = ktime_get();
|
||||
do_gettimeofday(&xframe->tv_created);
|
||||
xframe->xframe_magic = XFRAME_MAGIC;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_init);
|
||||
@@ -598,14 +559,6 @@ static void receive_tasklet_func(unsigned long data)
|
||||
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe)
|
||||
{
|
||||
BUG_ON(!xbus);
|
||||
if (xbus_is_shutting_down(xbus->num)) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1000) == 0)
|
||||
XBUS_NOTICE(xbus, "%s: during shutdown (%d)\n",
|
||||
__func__, rate_limit);
|
||||
return;
|
||||
}
|
||||
if (rx_tasklet) {
|
||||
xframe_enqueue_recv(xbus, xframe);
|
||||
} else {
|
||||
@@ -701,56 +654,10 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static xpd_type_t xpd_hw2xpd_type(const struct unit_descriptor *unit_descriptor)
|
||||
static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
|
||||
__u8 numchips, __u8 ports_per_chip, __u8 ports,
|
||||
__u8 port_dir)
|
||||
{
|
||||
xpd_type_t xpd_type;
|
||||
|
||||
switch (unit_descriptor->type) {
|
||||
case 1:
|
||||
case 6:
|
||||
xpd_type = XPD_TYPE_FXS;
|
||||
break;
|
||||
case 2:
|
||||
xpd_type = XPD_TYPE_FXO;
|
||||
break;
|
||||
case 3:
|
||||
xpd_type = XPD_TYPE_BRI;
|
||||
break;
|
||||
case 4:
|
||||
xpd_type = XPD_TYPE_PRI;
|
||||
break;
|
||||
case 5:
|
||||
xpd_type = XPD_TYPE_ECHO;
|
||||
break;
|
||||
case 7:
|
||||
xpd_type = XPD_TYPE_NOMODULE;
|
||||
break;
|
||||
default:
|
||||
NOTICE("WARNING: xpd hw type is: %d\n", unit_descriptor->type);
|
||||
xpd_type = XPD_TYPE_NOMODULE;
|
||||
break;
|
||||
}
|
||||
return xpd_type;
|
||||
}
|
||||
|
||||
int subunits_of_xpd(const struct unit_descriptor* unit_descriptor,
|
||||
const xproto_table_t *proto_table) {
|
||||
int ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
|
||||
|
||||
return
|
||||
(ports + proto_table->ports_per_subunit - 1)
|
||||
/ proto_table->ports_per_subunit;
|
||||
}
|
||||
|
||||
static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
|
||||
{
|
||||
int unit = unit_descriptor->addr.unit;
|
||||
xpd_type_t xpd_type;
|
||||
__u8 hw_type;
|
||||
__u8 numchips;
|
||||
__u8 ports_per_chip;
|
||||
__u8 ports;
|
||||
__u8 port_dir;
|
||||
const xproto_table_t *proto_table;
|
||||
int i;
|
||||
int subunits;
|
||||
@@ -758,19 +665,12 @@ static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
|
||||
int remaining_ports;
|
||||
const struct echoops *echoops;
|
||||
|
||||
/* Translate parameters from "unit_descriptor" */
|
||||
hw_type = unit_descriptor->type;
|
||||
numchips = unit_descriptor->numchips;
|
||||
ports_per_chip = unit_descriptor->ports_per_chip;
|
||||
port_dir = unit_descriptor->port_dir;
|
||||
ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
|
||||
xpd_type = xpd_hw2xpd_type(unit_descriptor);
|
||||
proto_table = xproto_get(xpd_type);
|
||||
proto_table = xproto_get(type);
|
||||
if (!proto_table) {
|
||||
XBUS_NOTICE(xbus,
|
||||
"CARD %d: missing protocol table for xpd_type %d. "
|
||||
"CARD %d: missing protocol table for type %d. "
|
||||
"Ignored.\n",
|
||||
unit, xpd_type);
|
||||
unit, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
echoops = proto_table->echoops;
|
||||
@@ -778,24 +678,26 @@ static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
|
||||
XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit);
|
||||
if (ECHOOPS(xbus)) {
|
||||
XBUS_NOTICE(xbus,
|
||||
"CARD %d: tryies to define echoops (xpd_type %d) "
|
||||
"CARD %d: tryies to define echoops (type %d) "
|
||||
"but we already have one. Ignored.\n",
|
||||
unit, xpd_type);
|
||||
unit, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
xbus->echo_state.echoops = echoops;
|
||||
xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
|
||||
}
|
||||
remaining_ports = ports;
|
||||
subunits = subunits_of_xpd(unit_descriptor, proto_table);
|
||||
subunits =
|
||||
(ports + proto_table->ports_per_subunit -
|
||||
1) / proto_table->ports_per_subunit;
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"CARD %d xpd_type=%d/hw_type=%d ports=%d (%dx%d), "
|
||||
"CARD %d type=%d.%d ports=%d (%dx%d), "
|
||||
"%d subunits, port-dir=0x%02X\n",
|
||||
unit, xpd_type, hw_type, ports, numchips, ports_per_chip, subunits,
|
||||
unit, type, subtype, ports, numchips, ports_per_chip, subunits,
|
||||
port_dir);
|
||||
if (xpd_type == XPD_TYPE_PRI || xpd_type == XPD_TYPE_BRI)
|
||||
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
|
||||
xbus->quirks.has_digital_span = 1;
|
||||
if (xpd_type == XPD_TYPE_FXO)
|
||||
if (type == XPD_TYPE_FXO)
|
||||
xbus->quirks.has_fxo = 1;
|
||||
xbus->worker.num_units += subunits - 1;
|
||||
for (i = 0; i < subunits; i++) {
|
||||
@@ -819,10 +721,11 @@ static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
|
||||
goto out;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"Creating XPD=%d%d xpd_type=%d.%d hw_type=%d (%d ports)\n", unit, i,
|
||||
xpd_type, unit_descriptor->subtype, hw_type, subunit_ports);
|
||||
"Creating XPD=%d%d type=%d.%d (%d ports)\n", unit, i,
|
||||
type, subtype, subunit_ports);
|
||||
ret =
|
||||
create_xpd(xbus, proto_table, unit_descriptor, unit, i, xpd_type);
|
||||
create_xpd(xbus, proto_table, unit, i, type, subtype,
|
||||
subunits, subunit_ports, port_dir);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit,
|
||||
i, ret);
|
||||
@@ -960,12 +863,12 @@ static int xbus_initialize(xbus_t *xbus)
|
||||
int unit;
|
||||
int subunit;
|
||||
xpd_t *xpd;
|
||||
ktime_t time_start;
|
||||
ktime_t time_end;
|
||||
struct timeval time_start;
|
||||
struct timeval time_end;
|
||||
unsigned long timediff;
|
||||
int res = 0;
|
||||
|
||||
time_start = ktime_get();
|
||||
do_gettimeofday(&time_start);
|
||||
XBUS_DBG(DEVICES, xbus, "refcount_xbus=%d\n", refcount_xbus(xbus));
|
||||
if (xbus_aquire_xpds(xbus) < 0) /* Until end of initialization */
|
||||
return -EBUSY;
|
||||
@@ -1003,7 +906,7 @@ static int xbus_initialize(xbus_t *xbus)
|
||||
}
|
||||
}
|
||||
xbus_echocancel(xbus, 1);
|
||||
time_end = ktime_get();
|
||||
do_gettimeofday(&time_end);
|
||||
timediff = usec_diff(&time_end, &time_start);
|
||||
timediff /= 1000 * 100;
|
||||
XBUS_INFO(xbus, "Initialized in %ld.%1ld sec\n", timediff / 10,
|
||||
@@ -1034,8 +937,6 @@ static void xbus_free_ddev(xbus_t *xbus)
|
||||
xbus->ddev = NULL;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(dahdi_registration_mutex);
|
||||
|
||||
int xbus_register_dahdi_device(xbus_t *xbus)
|
||||
{
|
||||
int i;
|
||||
@@ -1043,20 +944,11 @@ int xbus_register_dahdi_device(xbus_t *xbus)
|
||||
int ret;
|
||||
|
||||
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
||||
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
|
||||
goto err;
|
||||
}
|
||||
if (xbus_is_registered(xbus)) {
|
||||
/*
|
||||
* Ignore duplicate registrations (from dahdi_registration)
|
||||
* Until we completely migrate to dahdi_autoreg=1 and
|
||||
* hotplug-based span-assignments
|
||||
*/
|
||||
XBUS_DBG(DEVICES, xbus, "Already registered to DAHDI\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
XBUS_ERR(xbus, "Already registered to DAHDI\n");
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
xbus->ddev = dahdi_create_device();
|
||||
if (!xbus->ddev) {
|
||||
@@ -1116,49 +1008,31 @@ int xbus_register_dahdi_device(xbus_t *xbus)
|
||||
xpd_dahdi_postregister(xpd);
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
mutex_unlock(&dahdi_registration_mutex);
|
||||
return ret;
|
||||
return 0;
|
||||
err:
|
||||
xbus_free_ddev(xbus);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void xbus_unregister_dahdi_device(xbus_t *xbus)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
XBUS_DBG(DEVICES, xbus, "%s\n", __func__);
|
||||
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
|
||||
return;
|
||||
}
|
||||
if (!xbus_is_registered(xbus)) {
|
||||
/*
|
||||
* Ignore duplicate unregistrations
|
||||
*/
|
||||
XBUS_DBG(DEVICES, xbus, "Already unregistered to DAHDI\n");
|
||||
goto err;
|
||||
}
|
||||
XBUS_NOTICE(xbus, "%s\n", __func__);
|
||||
for (i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
xpd_dahdi_preunregister(xpd);
|
||||
}
|
||||
if (xbus->ddev) {
|
||||
dahdi_unregister_device(xbus->ddev);
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"%s: finished dahdi_unregister_device()\n", __func__);
|
||||
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n",
|
||||
__func__);
|
||||
xbus_free_ddev(xbus);
|
||||
}
|
||||
for (i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
xpd_dahdi_postunregister(xpd);
|
||||
}
|
||||
err:
|
||||
mutex_unlock(&dahdi_registration_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1166,10 +1040,16 @@ err:
|
||||
* it returns only when all XPD's on the bus are detected and
|
||||
* initialized.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
|
||||
static void xbus_populate(struct work_struct *work)
|
||||
{
|
||||
struct xbus_workqueue *worker =
|
||||
container_of(work, struct xbus_workqueue, xpds_init_work);
|
||||
#else
|
||||
void xbus_populate(void *data)
|
||||
{
|
||||
struct xbus_workqueue *worker = data;
|
||||
#endif
|
||||
xbus_t *xbus;
|
||||
struct list_head *card;
|
||||
struct list_head *next_card;
|
||||
@@ -1188,7 +1068,11 @@ static void xbus_populate(struct work_struct *work)
|
||||
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
|
||||
/* Release/Reacquire locks around blocking calls */
|
||||
spin_unlock_irqrestore(&xbus->worker.worker_lock, flags);
|
||||
ret = new_card(xbus, &card_desc->unit_descriptor);
|
||||
ret =
|
||||
new_card(xbus, card_desc->xpd_addr.unit, card_desc->type,
|
||||
card_desc->subtype, card_desc->numchips,
|
||||
card_desc->ports_per_chip, card_desc->ports,
|
||||
card_desc->port_dir);
|
||||
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
|
||||
KZFREE(card_desc);
|
||||
if (ret)
|
||||
@@ -1216,7 +1100,7 @@ static void xbus_populate(struct work_struct *work)
|
||||
*/
|
||||
xbus_request_sync(xbus, SYNC_MODE_PLL);
|
||||
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
|
||||
if (!dahdi_get_auto_assign_spans())
|
||||
if (dahdi_autoreg)
|
||||
xbus_register_dahdi_device(xbus);
|
||||
out:
|
||||
XBUS_DBG(DEVICES, xbus, "Leaving\n");
|
||||
@@ -1246,7 +1130,11 @@ int xbus_process_worker(xbus_t *xbus)
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "\n");
|
||||
/* Initialize the work. (adapt to kernel API changes). */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
|
||||
INIT_WORK(&worker->xpds_init_work, xbus_populate);
|
||||
#else
|
||||
INIT_WORK(&worker->xpds_init_work, xbus_populate, worker);
|
||||
#endif
|
||||
BUG_ON(!xbus);
|
||||
/* Now send it */
|
||||
if (!queue_work(worker->wq, &worker->xpds_init_work)) {
|
||||
@@ -1270,7 +1158,8 @@ static void worker_reset(xbus_t *xbus)
|
||||
name = (xbus) ? xbus->busname : "detached";
|
||||
DBG(DEVICES, "%s\n", name);
|
||||
if (!worker->xpds_init_done) {
|
||||
XBUS_NOTICE(xbus, "XPDS initialization was not finished\n");
|
||||
NOTICE("%s: worker(%s)->xpds_init_done=%d\n", __func__, name,
|
||||
worker->xpds_init_done);
|
||||
}
|
||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||
list_for_each_safe(card, next_card, &worker->card_list) {
|
||||
@@ -1288,15 +1177,13 @@ static void worker_reset(xbus_t *xbus)
|
||||
spin_unlock_irqrestore(&worker->worker_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called only after worker_reset(xbus)
|
||||
*/
|
||||
static void worker_destroy(xbus_t *xbus)
|
||||
{
|
||||
struct xbus_workqueue *worker;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
worker = &xbus->worker;
|
||||
worker_reset(xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish...\n");
|
||||
down(&worker->running_initialization);
|
||||
XBUS_DBG(DEVICES, xbus, "Waiting for worker to finish -- done\n");
|
||||
@@ -1349,7 +1236,6 @@ static int worker_run(xbus_t *xbus)
|
||||
}
|
||||
return 1;
|
||||
err:
|
||||
worker_reset(xbus);
|
||||
worker_destroy(xbus);
|
||||
return 0;
|
||||
}
|
||||
@@ -1517,7 +1403,6 @@ void xbus_disconnect(xbus_t *xbus)
|
||||
del_timer_sync(&xbus->command_timer);
|
||||
transportops_put(xbus);
|
||||
transport_destroy(xbus);
|
||||
/* worker_reset(xbus) was called in xbus_deactivate(xbus) */
|
||||
worker_destroy(xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "Deactivated refcount_xbus=%d\n",
|
||||
refcount_xbus(xbus));
|
||||
@@ -1567,7 +1452,6 @@ void xbus_free(xbus_t *xbus)
|
||||
num = xbus->num;
|
||||
BUG_ON(!xbuses_array[num].xbus);
|
||||
BUG_ON(xbus != xbuses_array[num].xbus);
|
||||
init_xbus(num, NULL);
|
||||
spin_unlock_irqrestore(&xbuses_lock, flags);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (xbus->proc_xbus_dir) {
|
||||
@@ -1594,6 +1478,7 @@ void xbus_free(xbus_t *xbus)
|
||||
#endif
|
||||
spin_lock_irqsave(&xbuses_lock, flags);
|
||||
XBUS_DBG(DEVICES, xbus, "Going to free...\n");
|
||||
init_xbus(num, NULL);
|
||||
spin_unlock_irqrestore(&xbuses_lock, flags);
|
||||
KZFREE(xbus);
|
||||
}
|
||||
@@ -1616,6 +1501,7 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
|
||||
transport_init(xbus, ops, max_send_size, transport_device, priv);
|
||||
spin_lock_init(&xbus->lock);
|
||||
init_waitqueue_head(&xbus->command_queue_empty);
|
||||
init_timer(&xbus->command_timer);
|
||||
atomic_set(&xbus->pcm_rx_counter, 0);
|
||||
xbus->min_tx_sync = INT_MAX;
|
||||
xbus->min_rx_sync = INT_MAX;
|
||||
@@ -1723,6 +1609,10 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
||||
* FIXME: worker is created before ?????
|
||||
* So by now it exists and initialized.
|
||||
*/
|
||||
/* until end of waitfor_xpds_show(): */
|
||||
xbus = get_xbus(__func__, xbus->num);
|
||||
if (!xbus)
|
||||
return -ENODEV;
|
||||
worker = &xbus->worker;
|
||||
BUG_ON(!worker);
|
||||
if (!worker->wq) {
|
||||
@@ -1761,6 +1651,7 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
}
|
||||
out:
|
||||
put_xbus(__func__, xbus); /* from start of waitfor_xpds_show() */
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -1769,7 +1660,8 @@ out:
|
||||
static void xbus_fill_proc_queue(struct seq_file *sfile, struct xframe_queue *q)
|
||||
{
|
||||
seq_printf(sfile,
|
||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02lld.%lld ms\n",
|
||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d "
|
||||
"worst_lag %02ld.%ld ms\n",
|
||||
q->name, q->steady_state_count, q->count, q->max_count,
|
||||
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
|
||||
q->worst_lag_usec % 1000);
|
||||
@@ -1805,9 +1697,8 @@ static int xbus_proc_show(struct seq_file *sfile, void *data)
|
||||
seq_printf(sfile, "%5d ", xbus->cpu_rcv_tasklet[i]);
|
||||
seq_printf(sfile, "\n");
|
||||
}
|
||||
seq_printf(sfile, "self_ticking: %d (last_tick at %lld)\n",
|
||||
xbus->self_ticking, ktime_divns(xbus->ticker.last_sample,
|
||||
NSEC_PER_SEC));
|
||||
seq_printf(sfile, "self_ticking: %d (last_tick at %ld)\n",
|
||||
xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec);
|
||||
seq_printf(sfile, "command_tick: %d\n",
|
||||
xbus->command_tick_counter);
|
||||
seq_printf(sfile, "usec_nosend: %d\n", xbus->usec_nosend);
|
||||
@@ -1842,22 +1733,13 @@ static int xbus_read_proc_open(struct inode *inode, struct file *file)
|
||||
return single_open(file, xbus_proc_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops xbus_read_proc_ops = {
|
||||
.proc_open = xbus_read_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations xbus_read_proc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = xbus_read_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
.open = xbus_read_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
static ssize_t proc_xbus_command_write(struct file *file,
|
||||
@@ -1950,19 +1832,11 @@ static int proc_xbus_command_open(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops proc_xbus_command_ops = {
|
||||
.proc_open = proc_xbus_command_open,
|
||||
.proc_write = proc_xbus_command_write,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations proc_xbus_command_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_xbus_command_open,
|
||||
.write = proc_xbus_command_write,
|
||||
};
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
|
||||
#endif
|
||||
|
||||
static int xpp_proc_read_show(struct seq_file *sfile, void *data)
|
||||
@@ -1992,22 +1866,13 @@ static int xpp_proc_read_open(struct inode *inode, struct file *file)
|
||||
return single_open(file, xpp_proc_read_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
#ifdef DAHDI_HAVE_PROC_OPS
|
||||
static const struct proc_ops xpp_proc_read_ops = {
|
||||
.proc_open = xpp_proc_read_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static const struct file_operations xpp_proc_read_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = xpp_proc_read_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
.open = xpp_proc_read_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif /* DAHDI_HAVE_PROC_OPS */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2094,10 +1959,6 @@ int __init xbus_core_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dahdi_autoreg == 1) {
|
||||
NOTICE("WARNING: The dahdi_autoreg parameter is deprecated " \
|
||||
"-- just set dahdi.auto_assign_spans=0\n");
|
||||
}
|
||||
initialize_xbuses_array();
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
INFO("FEATURE: with PROTOCOL_DEBUG\n");
|
||||
|
||||
@@ -234,8 +234,8 @@ struct xbus {
|
||||
spinlock_t lock;
|
||||
|
||||
/* PCM metrics */
|
||||
ktime_t last_tx_sync;
|
||||
ktime_t last_rx_sync;
|
||||
struct timeval last_tx_sync;
|
||||
struct timeval last_rx_sync;
|
||||
unsigned long max_tx_sync;
|
||||
unsigned long min_tx_sync;
|
||||
unsigned long max_rx_sync;
|
||||
@@ -255,7 +255,7 @@ struct xbus {
|
||||
*/
|
||||
int sync_adjustment;
|
||||
int sync_adjustment_offset;
|
||||
ktime_t pll_updated_at;
|
||||
long pll_updated_at;
|
||||
|
||||
atomic_t num_xpds;
|
||||
|
||||
@@ -279,10 +279,10 @@ struct xframe {
|
||||
struct list_head frame_list;
|
||||
atomic_t frame_len;
|
||||
xbus_t *xbus;
|
||||
ktime_t kt_created;
|
||||
ktime_t kt_queued;
|
||||
ktime_t kt_submitted;
|
||||
ktime_t kt_received;
|
||||
struct timeval tv_created;
|
||||
struct timeval tv_queued;
|
||||
struct timeval tv_submitted;
|
||||
struct timeval tv_received;
|
||||
/* filled by transport layer */
|
||||
size_t frame_maxlen;
|
||||
__u8 *packets; /* max XFRAME_DATASIZE */
|
||||
@@ -338,8 +338,6 @@ int waitfor_xpds(xbus_t *xbus, char *buf);
|
||||
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
|
||||
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
|
||||
|
||||
int subunits_of_xpd(const struct unit_descriptor* unit_descriptor,
|
||||
const xproto_table_t *proto_table);
|
||||
/* sysfs */
|
||||
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
|
||||
void xpd_device_unregister(xpd_t *xpd);
|
||||
@@ -358,9 +356,4 @@ void xbus_sysfs_remove(xbus_t *xbus);
|
||||
|
||||
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
|
||||
|
||||
static inline s64 xpp_ktime_sec_delta(ktime_t later, ktime_t earlier)
|
||||
{
|
||||
return ktime_divns(ktime_sub(later, earlier), NSEC_PER_SEC);
|
||||
}
|
||||
|
||||
#endif /* XBUS_CORE_H */
|
||||
|
||||
@@ -111,23 +111,24 @@ static void xpp_ticker_init(struct xpp_ticker *ticker)
|
||||
{
|
||||
memset(ticker, 0, sizeof(*ticker));
|
||||
spin_lock_init(&ticker->lock);
|
||||
ticker->last_sample = ktime_get();
|
||||
do_gettimeofday(&ticker->last_sample.tv);
|
||||
ticker->first_sample = ticker->last_sample;
|
||||
ticker_set_cycle(ticker, SYNC_ADJ_QUICK);
|
||||
}
|
||||
|
||||
static int xpp_ticker_step(struct xpp_ticker *ticker, const ktime_t t)
|
||||
static int xpp_ticker_step(struct xpp_ticker *ticker, const struct timeval *t)
|
||||
{
|
||||
unsigned long flags;
|
||||
s64 usec;
|
||||
long usec;
|
||||
bool cycled = 0;
|
||||
|
||||
spin_lock_irqsave(&ticker->lock, flags);
|
||||
ticker->last_sample = t;
|
||||
ticker->last_sample.tv = *t;
|
||||
/* rate adjust */
|
||||
if ((ticker->count % ticker->cycle) == ticker->cycle - 1) {
|
||||
usec = ktime_us_delta(ticker->last_sample,
|
||||
ticker->first_sample);
|
||||
usec =
|
||||
(long)usec_diff(&ticker->last_sample.tv,
|
||||
&ticker->first_sample.tv);
|
||||
ticker->first_sample = ticker->last_sample;
|
||||
ticker->tick_period = usec / ticker->cycle;
|
||||
cycled = 1;
|
||||
@@ -146,7 +147,7 @@ static inline void xbus_drift_clear(xbus_t *xbus)
|
||||
{
|
||||
struct xpp_drift *di = &xbus->drift;
|
||||
|
||||
di->last_lost_tick = ktime_get();
|
||||
do_gettimeofday(&di->last_lost_tick.tv);
|
||||
ticker_set_cycle(&xbus->ticker, SYNC_ADJ_QUICK);
|
||||
di->max_speed = -SYNC_ADJ_MAX;
|
||||
di->min_speed = SYNC_ADJ_MAX;
|
||||
@@ -189,14 +190,14 @@ static void sample_tick(xbus_t *xbus, int sample)
|
||||
* including abrupt changes in sync -- to verify the stability of the
|
||||
* algorithm.
|
||||
*/
|
||||
static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
|
||||
static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
|
||||
{
|
||||
struct xpp_drift *di = &xbus->drift;
|
||||
struct xpp_ticker *ticker = &xbus->ticker;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&di->lock, flags);
|
||||
xpp_ticker_step(&xbus->ticker, kt);
|
||||
xpp_ticker_step(&xbus->ticker, tv);
|
||||
/*
|
||||
* Do we need to be synchronized and is there an established reference
|
||||
* ticker (another Astribank or another DAHDI device) already?
|
||||
@@ -205,7 +206,7 @@ static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
|
||||
&& xbus->sync_mode == SYNC_MODE_PLL) {
|
||||
int new_delta_tick = ticker->count - ref_ticker->count;
|
||||
int lost_ticks = new_delta_tick - di->delta_tick;
|
||||
s64 usec_delta;
|
||||
long usec_delta;
|
||||
|
||||
di->delta_tick = new_delta_tick;
|
||||
if (lost_ticks) {
|
||||
@@ -232,8 +233,9 @@ static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
|
||||
}
|
||||
} else {
|
||||
/* Sample a delta */
|
||||
usec_delta = ktime_us_delta(ticker->last_sample,
|
||||
ref_ticker->last_sample);
|
||||
usec_delta =
|
||||
(long)usec_diff(&ticker->last_sample.tv,
|
||||
&ref_ticker->last_sample.tv);
|
||||
sample_tick(xbus, usec_delta);
|
||||
if ((ticker->count % SYNC_CYCLE) >
|
||||
(SYNC_CYCLE - SYNC_CYCLE_SAMPLE))
|
||||
@@ -280,7 +282,8 @@ static void xpp_drift_step(xbus_t *xbus, const ktime_t kt)
|
||||
di->offset_min = offset;
|
||||
|
||||
XBUS_DBG(SYNC, xbus,
|
||||
"offset: %d, min_speed=%d, max_speed=%d, usec_delta(last)=%lld\n",
|
||||
"offset: %d, min_speed=%d, "
|
||||
"max_speed=%d, usec_delta(last)=%ld\n",
|
||||
offset_prev, di->min_speed,
|
||||
di->max_speed, usec_delta);
|
||||
XBUS_DBG(SYNC, xbus,
|
||||
@@ -350,11 +353,13 @@ static void xpp_set_syncer(xbus_t *xbus, bool on)
|
||||
(syncer) ? syncer->busname : "NO-SYNC");
|
||||
}
|
||||
|
||||
static void xbus_command_timer(TIMER_DATA_TYPE timer)
|
||||
static void xbus_command_timer(unsigned long param)
|
||||
{
|
||||
xbus_t *xbus = from_timer(xbus, timer, command_timer);
|
||||
xbus_t *xbus = (xbus_t *)param;
|
||||
struct timeval now;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
do_gettimeofday(&now);
|
||||
xbus_command_queue_tick(xbus);
|
||||
if (!xbus->self_ticking) /* Must be 1KHz rate */
|
||||
mod_timer(&xbus->command_timer, jiffies + 1);
|
||||
@@ -366,9 +371,10 @@ void xbus_set_command_timer(xbus_t *xbus, bool on)
|
||||
if (on) {
|
||||
if (!timer_pending(&xbus->command_timer)) {
|
||||
XBUS_DBG(SYNC, xbus, "add_timer\n");
|
||||
timer_setup(&xbus->command_timer,
|
||||
xbus_command_timer, 0);
|
||||
mod_timer(&xbus->command_timer, jiffies + 1);
|
||||
xbus->command_timer.function = xbus_command_timer;
|
||||
xbus->command_timer.data = (unsigned long)xbus;
|
||||
xbus->command_timer.expires = jiffies + 1;
|
||||
add_timer(&xbus->command_timer);
|
||||
}
|
||||
} else if (timer_pending(&xbus->command_timer)) {
|
||||
XBUS_DBG(SYNC, xbus, "del_timer\n");
|
||||
@@ -484,34 +490,34 @@ static void reset_sync_counters(void)
|
||||
|
||||
static void send_drift(xbus_t *xbus, int drift)
|
||||
{
|
||||
const ktime_t now = ktime_get();
|
||||
struct timeval now;
|
||||
const char *msg;
|
||||
s64 msec_delta;
|
||||
|
||||
BUG_ON(abs(drift) > SYNC_ADJ_MAX);
|
||||
do_gettimeofday(&now);
|
||||
if (drift > xbus->sync_adjustment)
|
||||
msg = "up";
|
||||
else
|
||||
msg = "down";
|
||||
msec_delta = ktime_ms_delta(now, xbus->pll_updated_at);
|
||||
XBUS_DBG(SYNC, xbus,
|
||||
"%sDRIFT adjust %s (%d) (last update %lld seconds ago)\n",
|
||||
"%sDRIFT adjust %s (%d) (last update %ld seconds ago)\n",
|
||||
(disable_pll_sync) ? "Fake " : "", msg, drift,
|
||||
msec_delta / MSEC_PER_SEC);
|
||||
now.tv_sec - xbus->pll_updated_at);
|
||||
if (!disable_pll_sync)
|
||||
CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL,
|
||||
drift);
|
||||
xbus->pll_updated_at = now;
|
||||
xbus->pll_updated_at = now.tv_sec;
|
||||
}
|
||||
|
||||
static void global_tick(void)
|
||||
{
|
||||
ktime_t now = ktime_get();
|
||||
struct timeval now;
|
||||
|
||||
do_gettimeofday(&now);
|
||||
atomic_inc(&xpp_tick_counter);
|
||||
if ((atomic_read(&xpp_tick_counter) % BIG_TICK_INTERVAL) == 0)
|
||||
reset_sync_counters();
|
||||
xpp_ticker_step(&global_ticks_series, now);
|
||||
xpp_ticker_step(&global_ticks_series, &now);
|
||||
}
|
||||
|
||||
#ifdef DAHDI_SYNC_TICK
|
||||
@@ -520,11 +526,11 @@ void dahdi_sync_tick(struct dahdi_span *span, int is_master)
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
static int redundant_ticks; /* for extra spans */
|
||||
ktime_t now;
|
||||
struct timeval now;
|
||||
|
||||
if (!force_dahdi_sync)
|
||||
goto noop;
|
||||
now = ktime_get();
|
||||
do_gettimeofday(&now);
|
||||
BUG_ON(!xpd);
|
||||
/*
|
||||
* Detect if any of our spans is dahdi sync master
|
||||
@@ -557,7 +563,7 @@ void dahdi_sync_tick(struct dahdi_span *span, int is_master)
|
||||
#endif
|
||||
goto noop;
|
||||
}
|
||||
xpp_ticker_step(&dahdi_ticker, now);
|
||||
xpp_ticker_step(&dahdi_ticker, &now);
|
||||
dahdi_tick_count++;
|
||||
//flip_parport_bit(1);
|
||||
noop:
|
||||
@@ -849,14 +855,15 @@ static bool pcm_valid(xpd_t *xpd, xpacket_t *pack)
|
||||
static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
|
||||
{
|
||||
unsigned long flags;
|
||||
const ktime_t now = ktime_get();
|
||||
s64 usec;
|
||||
struct timeval now;
|
||||
unsigned long usec;
|
||||
|
||||
spin_lock_irqsave(&xbus->lock, flags);
|
||||
do_gettimeofday(&now);
|
||||
if (unlikely(disable_pcm || !XBUS_IS(xbus, READY)))
|
||||
goto dropit;
|
||||
if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
|
||||
usec = ktime_us_delta(now, xbus->last_tx_sync);
|
||||
usec = usec_diff(&now, &xbus->last_tx_sync);
|
||||
xbus->last_tx_sync = now;
|
||||
/* ignore startup statistics */
|
||||
if (likely
|
||||
@@ -866,7 +873,8 @@ static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
|
||||
|
||||
if ((rate_limit++ % 5003) == 0)
|
||||
XBUS_DBG(SYNC, xbus,
|
||||
"Bad PCM TX timing(%d): usec=%lld.\n",
|
||||
"Bad PCM TX timing(%d): "
|
||||
"usec=%ld.\n",
|
||||
rate_limit, usec);
|
||||
}
|
||||
if (usec > xbus->max_tx_sync)
|
||||
@@ -1180,10 +1188,11 @@ static void xbus_tick(xbus_t *xbus)
|
||||
while ((xframe = xframe_dequeue(&xbus->pcm_tospan)) != NULL) {
|
||||
copy_pcm_tospan(xbus, xframe);
|
||||
if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
|
||||
ktime_t now = ktime_get();
|
||||
s64 usec;
|
||||
struct timeval now;
|
||||
unsigned long usec;
|
||||
|
||||
usec = ktime_us_delta(now, xbus->last_rx_sync);
|
||||
do_gettimeofday(&now);
|
||||
usec = usec_diff(&now, &xbus->last_rx_sync);
|
||||
xbus->last_rx_sync = now;
|
||||
/* ignore startup statistics */
|
||||
if (likely
|
||||
@@ -1194,7 +1203,9 @@ static void xbus_tick(xbus_t *xbus)
|
||||
|
||||
if ((rate_limit++ % 5003) == 0)
|
||||
XBUS_DBG(SYNC, xbus,
|
||||
"Bad PCM RX timing(%d): usec=%lld.\n",
|
||||
"Bad PCM RX "
|
||||
"timing(%d): "
|
||||
"usec=%ld.\n",
|
||||
rate_limit, usec);
|
||||
}
|
||||
if (usec > xbus->max_rx_sync)
|
||||
@@ -1225,7 +1236,7 @@ static void xbus_tick(xbus_t *xbus)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_tick(xbus_t *xbus, const ktime_t kt_received)
|
||||
static void do_tick(xbus_t *xbus, const struct timeval *tv_received)
|
||||
{
|
||||
int counter = atomic_read(&xpp_tick_counter);
|
||||
unsigned long flags;
|
||||
@@ -1234,7 +1245,7 @@ static void do_tick(xbus_t *xbus, const ktime_t kt_received)
|
||||
if (global_ticker == xbus)
|
||||
global_tick(); /* called from here or dahdi_sync_tick() */
|
||||
spin_lock_irqsave(&ref_ticker_lock, flags);
|
||||
xpp_drift_step(xbus, kt_received);
|
||||
xpp_drift_step(xbus, tv_received);
|
||||
spin_unlock_irqrestore(&ref_ticker_lock, flags);
|
||||
if (likely(xbus->self_ticking))
|
||||
xbus_tick(xbus);
|
||||
@@ -1258,7 +1269,7 @@ void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe)
|
||||
* FIXME: what about PRI split?
|
||||
*/
|
||||
if (XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
|
||||
do_tick(xbus, xframe->kt_received);
|
||||
do_tick(xbus, &xframe->tv_received);
|
||||
atomic_inc(&xbus->pcm_rx_counter);
|
||||
} else
|
||||
xbus->xbus_frag_count++;
|
||||
|
||||
@@ -39,6 +39,16 @@ enum sync_mode {
|
||||
SYNC_MODE_QUERY = 0x80,
|
||||
};
|
||||
|
||||
/*
|
||||
* Abstract representation of timestamp.
|
||||
* It would (eventually) replace the hard-coded
|
||||
* timeval structs so we can migrate to better
|
||||
* time representations.
|
||||
*/
|
||||
struct xpp_timestamp {
|
||||
struct timeval tv;
|
||||
};
|
||||
|
||||
/*
|
||||
* A ticker encapsulates the timing information of some
|
||||
* abstract tick source. The following tickers are used:
|
||||
@@ -50,8 +60,8 @@ enum sync_mode {
|
||||
struct xpp_ticker { /* for rate calculation */
|
||||
int count;
|
||||
int cycle;
|
||||
ktime_t first_sample;
|
||||
ktime_t last_sample;
|
||||
struct xpp_timestamp first_sample;
|
||||
struct xpp_timestamp last_sample;
|
||||
int tick_period; /* usec/tick */
|
||||
spinlock_t lock;
|
||||
};
|
||||
@@ -65,7 +75,7 @@ struct xpp_drift {
|
||||
int lost_ticks; /* occurances */
|
||||
int lost_tick_count;
|
||||
int sync_inaccuracy;
|
||||
ktime_t last_lost_tick;
|
||||
struct xpp_timestamp last_lost_tick;
|
||||
long delta_sum;
|
||||
int offset_prev;
|
||||
int offset_range;
|
||||
@@ -78,10 +88,15 @@ struct xpp_drift {
|
||||
|
||||
void xpp_drift_init(xbus_t *xbus);
|
||||
|
||||
static inline long usec_diff(const ktime_t *tv1,
|
||||
const ktime_t *tv2)
|
||||
static inline long usec_diff(const struct timeval *tv1,
|
||||
const struct timeval *tv2)
|
||||
{
|
||||
return ktime_us_delta(*tv1, *tv2);
|
||||
long diff_sec;
|
||||
long diff_usec;
|
||||
|
||||
diff_sec = tv1->tv_sec - tv2->tv_sec;
|
||||
diff_usec = tv1->tv_usec - tv2->tv_usec;
|
||||
return diff_sec * 1000000 + diff_usec;
|
||||
}
|
||||
|
||||
int xbus_pcm_init(void *top);
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h> /* for msleep() to debug */
|
||||
#include <linux/sched.h>
|
||||
#include <dahdi/kernel.h>
|
||||
#include "xpd.h"
|
||||
#include "xpp_dahdi.h"
|
||||
#include "xbus-core.h"
|
||||
@@ -56,19 +54,10 @@ static ssize_t sync_store(struct device_driver *driver, const char *buf,
|
||||
return exec_sync_command(buf, count);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
static struct driver_attribute xpp_attrs[] = {
|
||||
__ATTR(sync, S_IRUGO | S_IWUSR, sync_show, sync_store),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DRIVER_ATTR_RW(sync);
|
||||
static struct attribute *xpp_attrs[] = {
|
||||
&driver_attr_sync.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xpp);
|
||||
#endif
|
||||
|
||||
/*--------- Sysfs Bus handling ----*/
|
||||
static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
|
||||
@@ -118,28 +107,24 @@ static DEVICE_ATTR_READER(timing_show, dev, buf)
|
||||
xbus_t *xbus;
|
||||
struct xpp_drift *driftinfo;
|
||||
int len = 0;
|
||||
ktime_t now;
|
||||
struct timeval now;
|
||||
|
||||
now = ktime_get();
|
||||
do_gettimeofday(&now);
|
||||
xbus = dev_to_xbus(dev);
|
||||
driftinfo = &xbus->drift;
|
||||
len +=
|
||||
snprintf(buf + len, PAGE_SIZE - len, "%-3s",
|
||||
sync_mode_name(xbus->sync_mode));
|
||||
if (xbus->sync_mode == SYNC_MODE_PLL) {
|
||||
bool pll_updated = !dahdi_ktime_equal(xbus->pll_updated_at,
|
||||
ktime_set(0, 0));
|
||||
s64 update_delta =
|
||||
(!pll_updated) ? 0 :
|
||||
xpp_ktime_sec_delta(now, xbus->pll_updated_at);
|
||||
len +=
|
||||
snprintf(buf + len, PAGE_SIZE - len,
|
||||
" %5d: lost (%4d,%4d) : ", xbus->ticker.cycle,
|
||||
driftinfo->lost_ticks, driftinfo->lost_tick_count);
|
||||
len +=
|
||||
snprintf(buf + len, PAGE_SIZE - len,
|
||||
"DRIFT %3d %lld sec ago", xbus->sync_adjustment,
|
||||
update_delta);
|
||||
"DRIFT %3d %ld sec ago", xbus->sync_adjustment,
|
||||
(xbus->pll_updated_at ==
|
||||
0) ? 0 : now.tv_sec - xbus->pll_updated_at);
|
||||
}
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
||||
return len;
|
||||
@@ -234,7 +219,7 @@ static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
|
||||
xbus_t *xbus;
|
||||
struct xpp_drift *di;
|
||||
struct xpp_ticker *ticker;
|
||||
ktime_t now = ktime_get();
|
||||
struct timeval now;
|
||||
int len = 0;
|
||||
int hours;
|
||||
int minutes;
|
||||
@@ -249,7 +234,8 @@ static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
|
||||
/*
|
||||
* Calculate lost ticks time
|
||||
*/
|
||||
seconds = ktime_ms_delta(now, di->last_lost_tick) / 1000;
|
||||
do_gettimeofday(&now);
|
||||
seconds = now.tv_sec - di->last_lost_tick.tv.tv_sec;
|
||||
minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
hours = minutes / 60;
|
||||
@@ -307,43 +293,6 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
xbus_attr(connector, "%s\n");
|
||||
xbus_attr(label, "%s\n");
|
||||
|
||||
static DEVICE_ATTR_WRITER(dahdi_registration_store, dev, buf, count)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int dahdi_reg;
|
||||
int ret;
|
||||
|
||||
xbus = dev_to_xbus(dev);
|
||||
if (!xbus)
|
||||
return -ENODEV;
|
||||
ret = sscanf(buf, "%d", &dahdi_reg);
|
||||
if (ret != 1)
|
||||
return -EINVAL;
|
||||
if (dahdi_reg) {
|
||||
ret = xbus_register_dahdi_device(xbus);
|
||||
if (ret < 0) {
|
||||
XBUS_ERR(xbus,
|
||||
"xbus_register_dahdi_device() failed (ret = %d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
xbus_unregister_dahdi_device(xbus);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int len;
|
||||
|
||||
xbus = dev_to_xbus(dev);
|
||||
len = sprintf(buf, "%d\n", xbus_is_registered(xbus));
|
||||
return len;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute xbus_dev_attrs[] = {
|
||||
__ATTR_RO(connector),
|
||||
__ATTR_RO(label),
|
||||
@@ -358,44 +307,8 @@ static struct device_attribute xbus_dev_attrs[] = {
|
||||
#ifdef SAMPLE_TICKS
|
||||
__ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
|
||||
#endif
|
||||
__ATTR(dahdi_registration, S_IRUGO | S_IWUSR,
|
||||
dahdi_registration_show,
|
||||
dahdi_registration_store),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RO(connector);
|
||||
static DEVICE_ATTR_RO(label);
|
||||
static DEVICE_ATTR_RO(status);
|
||||
static DEVICE_ATTR_RO(timing);
|
||||
static DEVICE_ATTR_RO(refcount_xbus);
|
||||
static DEVICE_ATTR_RO(waitfor_xpds);
|
||||
static DEVICE_ATTR_RO(driftinfo);
|
||||
static DEVICE_ATTR_WO(cls);
|
||||
static DEVICE_ATTR_RW(xbus_state);
|
||||
#ifdef SAMPLE_TICKS
|
||||
static DEVICE_ATTR_RO(samples);
|
||||
#endif
|
||||
static DEVICE_ATTR_RW(dahdi_registration);
|
||||
|
||||
static struct attribute *xbus_dev_attrs[] = {
|
||||
&dev_attr_connector.attr,
|
||||
&dev_attr_label.attr,
|
||||
&dev_attr_status.attr,
|
||||
&dev_attr_timing.attr,
|
||||
&dev_attr_refcount_xbus.attr,
|
||||
&dev_attr_waitfor_xpds.attr,
|
||||
&dev_attr_driftinfo.attr,
|
||||
&dev_attr_cls.attr,
|
||||
&dev_attr_xbus_state.attr,
|
||||
#ifdef SAMPLE_TICKS
|
||||
&dev_attr_samples.attr,
|
||||
#endif
|
||||
&dev_attr_dahdi_registration.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xbus_dev);
|
||||
#endif
|
||||
|
||||
static int astribank_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
@@ -411,6 +324,34 @@ static int astribank_match(struct device *dev, struct device_driver *driver)
|
||||
XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); \
|
||||
} while (0)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
#define XBUS_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(envp, num_envp, &i, \
|
||||
buffer, buffer_size, &len, \
|
||||
fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int astribank_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int i = 0;
|
||||
int len = 0;
|
||||
extern char *initdir;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
xbus = dev_to_xbus(dev);
|
||||
DBG(GENERAL, "SYFS bus_id=%s xbus=%s\n", dev_name(dev), xbus->busname);
|
||||
XBUS_VAR_BLOCK;
|
||||
envp[i] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define XBUS_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(kenv, fmt, val); \
|
||||
@@ -431,6 +372,8 @@ static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
|
||||
{
|
||||
struct kobject *kobj;
|
||||
@@ -465,16 +408,8 @@ static struct bus_type toplevel_bus_type = {
|
||||
.name = "astribanks",
|
||||
.match = astribank_match,
|
||||
.uevent = astribank_uevent,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = xbus_dev_attrs,
|
||||
#else
|
||||
.dev_groups = xbus_dev_groups,
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
.drv_attrs = xpp_attrs,
|
||||
#else
|
||||
.drv_groups = xpp_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int astribank_probe(struct device *dev)
|
||||
@@ -530,25 +465,13 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||
REG_FIELD(regs, data_high));
|
||||
} else
|
||||
datah_str[0] = '\0';
|
||||
if (regs->h.bytes == REG_CMD_SIZE(RAM)) {
|
||||
len +=
|
||||
sprintf(buf + len, "#CH\tOP\tAL\tAH\tD0\tD1\tD2\tD3\n");
|
||||
len +=
|
||||
sprintf(buf + len, "%2d\tRR\t%02X\t%02X\t%02X\t%02X\t%02X\t%02X\n",
|
||||
regs->h.portnum,
|
||||
REG_FIELD_RAM(regs, addr_low),
|
||||
REG_FIELD_RAM(regs, addr_high),
|
||||
REG_FIELD_RAM(regs, data_0),
|
||||
REG_FIELD_RAM(regs, data_1),
|
||||
REG_FIELD_RAM(regs, data_2),
|
||||
REG_FIELD_RAM(regs, data_3));
|
||||
} else if (REG_FIELD(regs, do_subreg)) {
|
||||
if (REG_FIELD(regs, do_subreg)) {
|
||||
len +=
|
||||
sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
|
||||
(do_datah) ? "\tDH" : "");
|
||||
len +=
|
||||
sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
|
||||
regs->h.portnum, REG_FIELD(regs, regnum),
|
||||
regs->portnum, REG_FIELD(regs, regnum),
|
||||
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
|
||||
datah_str);
|
||||
} else {
|
||||
@@ -556,7 +479,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
||||
(do_datah) ? "\tDH" : "");
|
||||
len +=
|
||||
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->h.portnum,
|
||||
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
|
||||
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
|
||||
datah_str);
|
||||
}
|
||||
@@ -678,12 +601,25 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
||||
return -EINVAL;
|
||||
if (!XBUS_IS(xpd->xbus, READY))
|
||||
return -ENODEV;
|
||||
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n",
|
||||
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use pinned-spans)\n",
|
||||
(dahdi_reg) ? "register" : "unregister");
|
||||
if (dahdi_reg)
|
||||
xbus_register_dahdi_device(xpd->xbus);
|
||||
else
|
||||
xbus_unregister_dahdi_device(xpd->xbus);
|
||||
if (xbus_is_registered(xpd->xbus)) {
|
||||
if (dahdi_reg) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"already registered %s. Ignored.\n",
|
||||
xpd->xbus->busname);
|
||||
} else {
|
||||
xbus_unregister_dahdi_device(xpd->xbus);
|
||||
}
|
||||
} else {
|
||||
if (!dahdi_reg) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"already unregistered %s. Ignored.\n",
|
||||
xpd->xbus->busname);
|
||||
} else {
|
||||
xbus_register_dahdi_device(xpd->xbus);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -700,19 +636,6 @@ static DEVICE_ATTR_READER(type_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(hwid_show, dev, buf)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
int len = 0;
|
||||
|
||||
BUG_ON(!dev);
|
||||
xpd = dev_to_xpd(dev);
|
||||
if (!xpd)
|
||||
return -ENODEV;
|
||||
len += sprintf(buf, "%d.%d\n", XPD_HW(xpd).type, XPD_HW(xpd).subtype);
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(offhook_show, dev, buf)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
@@ -768,63 +691,34 @@ static int xpd_match(struct device *dev, struct device_driver *driver)
|
||||
|
||||
xpd_driver = driver_to_xpd_driver(driver);
|
||||
xpd = dev_to_xpd(dev);
|
||||
if (xpd_driver->xpd_type != xpd->xpd_type) {
|
||||
if (xpd_driver->type != xpd->type) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"SYSFS match fail: xpd->xpd_type = %d, "
|
||||
"xpd_driver->xpd_type = %d\n",
|
||||
xpd->xpd_type, xpd_driver->xpd_type);
|
||||
"SYSFS match fail: xpd->type = %d, "
|
||||
"xpd_driver->type = %d\n",
|
||||
xpd->type, xpd_driver->type);
|
||||
return 0;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"SYSFS MATCH: xpd_type=%d dev->bus_id = %s, driver->name = %s\n",
|
||||
xpd->xpd_type, dev_name(dev), driver->name);
|
||||
"SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
|
||||
xpd->type, dev_name(dev), driver->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
static struct device_attribute xpd_dev_attrs[] = {
|
||||
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
|
||||
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
|
||||
__ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
|
||||
__ATTR_RO(type),
|
||||
__ATTR_RO(hwid),
|
||||
__ATTR_RO(offhook),
|
||||
__ATTR_RO(timing_priority),
|
||||
__ATTR_RO(refcount_xpd),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#else
|
||||
static DEVICE_ATTR_RW(chipregs);
|
||||
static DEVICE_ATTR_RW(blink);
|
||||
static DEVICE_ATTR_RW(span);
|
||||
static DEVICE_ATTR_RO(type);
|
||||
static DEVICE_ATTR_RO(hwid);
|
||||
static DEVICE_ATTR_RO(offhook);
|
||||
static DEVICE_ATTR_RO(timing_priority);
|
||||
static DEVICE_ATTR_RO(refcount_xpd);
|
||||
|
||||
static struct attribute *xpd_dev_attrs[] = {
|
||||
&dev_attr_chipregs.attr,
|
||||
&dev_attr_blink.attr,
|
||||
&dev_attr_span.attr,
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_hwid.attr,
|
||||
&dev_attr_offhook.attr,
|
||||
&dev_attr_timing_priority.attr,
|
||||
&dev_attr_refcount_xpd.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xpd_dev);
|
||||
#endif
|
||||
|
||||
static struct bus_type xpd_type = {
|
||||
.name = "xpds",
|
||||
.match = xpd_match,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
|
||||
.dev_attrs = xpd_dev_attrs,
|
||||
#else
|
||||
.dev_groups = xpd_dev_groups,
|
||||
#endif
|
||||
};
|
||||
|
||||
int xpd_driver_register(struct device_driver *driver)
|
||||
@@ -1034,13 +928,10 @@ void xbus_sysfs_remove(xbus_t *xbus)
|
||||
struct device *astribank;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "\n");
|
||||
astribank = &xbus->astribank;
|
||||
if (!dev_get_drvdata(astribank)) {
|
||||
XBUS_NOTICE(xbus, "%s: already removed\n", __func__);
|
||||
if (!dev_get_drvdata(astribank))
|
||||
return;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n",
|
||||
refcount_read(&astribank->kobj.kref.refcount));
|
||||
BUG_ON(dev_get_drvdata(astribank) != xbus);
|
||||
device_unregister(astribank);
|
||||
dev_set_drvdata(astribank, NULL);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xpp_version.h"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -103,7 +105,11 @@ typedef char *charp;
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* Kernel versions... */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
#define KMEM_CACHE_T kmem_cache_t
|
||||
#else
|
||||
#define KMEM_CACHE_T struct kmem_cache
|
||||
#endif
|
||||
|
||||
#define KZALLOC(size, gfp) my_kzalloc(size, gfp)
|
||||
#define KZFREE(p) \
|
||||
@@ -112,6 +118,7 @@ typedef char *charp;
|
||||
kfree(p); \
|
||||
} while (0);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf)
|
||||
@@ -119,6 +126,12 @@ typedef char *charp;
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count)
|
||||
#else
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, const char *buf, size_t count)
|
||||
#endif
|
||||
#define DRIVER_ATTR_READER(name, drv, buf) \
|
||||
ssize_t name(struct device_driver *drv, char * buf)
|
||||
|
||||
@@ -131,9 +144,19 @@ typedef char *charp;
|
||||
#define SET_PROC_DIRENTRY_OWNER(p) do { } while (0);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
/* Also don't define this for later RHEL >= 5.2. */
|
||||
#if defined(RHEL_RELEASE_CODE) && defined(RHEL_RELEASE_VERSION)
|
||||
#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 3)
|
||||
typedef int bool;
|
||||
#endif
|
||||
#else
|
||||
typedef int bool;
|
||||
#endif /* ifdef __KERNEL__ */
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
typedef int bool;
|
||||
#endif
|
||||
typedef struct xbus xbus_t;
|
||||
typedef struct xpd xpd_t;
|
||||
typedef struct xframe xframe_t;
|
||||
|
||||
@@ -34,15 +34,15 @@ static void __xframe_dump_queue(struct xframe_queue *q)
|
||||
xframe_t *xframe;
|
||||
int i = 0;
|
||||
char prefix[30];
|
||||
ktime_t now = ktime_get();
|
||||
struct timeval now;
|
||||
|
||||
do_gettimeofday(&now);
|
||||
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
|
||||
THIS_MODULE->name, q->name);
|
||||
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
|
||||
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
|
||||
s64 usec = ktime_us_delta(now, xframe->kt_queued);
|
||||
|
||||
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5lld.%03lld msec",
|
||||
long usec = usec_diff(&now, &xframe->tv_queued);
|
||||
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
|
||||
i++, usec / 1000, usec % 1000);
|
||||
dump_packet(prefix, pack, 1);
|
||||
}
|
||||
@@ -60,7 +60,9 @@ static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
||||
if (q->count >= q->max_count) {
|
||||
q->overflows++;
|
||||
if ((overflow_cnt++ % 1000) < 5) {
|
||||
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02lld.%lld ms\n",
|
||||
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d "
|
||||
"worst %3d, overflows %3d "
|
||||
"worst_lag %02ld.%ld ms\n",
|
||||
q->name, q->steady_state_count, q->count,
|
||||
q->max_count, q->worst_count, q->overflows,
|
||||
q->worst_lag_usec / 1000,
|
||||
@@ -73,7 +75,7 @@ static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
||||
if (++q->count > q->worst_count)
|
||||
q->worst_count = q->count;
|
||||
list_add_tail(&xframe->frame_list, &q->head);
|
||||
xframe->kt_queued = ktime_get();
|
||||
do_gettimeofday(&xframe->tv_queued);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -94,8 +96,8 @@ static xframe_t *__xframe_dequeue(struct xframe_queue *q)
|
||||
{
|
||||
xframe_t *frm = NULL;
|
||||
struct list_head *h;
|
||||
ktime_t now;
|
||||
s64 usec_lag;
|
||||
struct timeval now;
|
||||
unsigned long usec_lag;
|
||||
|
||||
if (list_empty(&q->head))
|
||||
goto out;
|
||||
@@ -103,8 +105,12 @@ static xframe_t *__xframe_dequeue(struct xframe_queue *q)
|
||||
list_del_init(h);
|
||||
--q->count;
|
||||
frm = list_entry(h, xframe_t, frame_list);
|
||||
now = ktime_get();
|
||||
usec_lag = ktime_us_delta(now, frm->kt_queued);
|
||||
do_gettimeofday(&now);
|
||||
usec_lag =
|
||||
(now.tv_sec - frm->tv_queued.tv_sec) * 1000 * 1000 + (now.tv_usec -
|
||||
frm->
|
||||
tv_queued.
|
||||
tv_usec);
|
||||
if (q->worst_lag_usec < usec_lag)
|
||||
q->worst_lag_usec = usec_lag;
|
||||
out:
|
||||
@@ -278,7 +284,7 @@ xframe_t *get_xframe(struct xframe_queue *q)
|
||||
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
||||
atomic_set(&xframe->frame_len, 0);
|
||||
xframe->first_free = xframe->packets;
|
||||
xframe->kt_created = ktime_get();
|
||||
do_gettimeofday(&xframe->tv_created);
|
||||
/*
|
||||
* If later parts bother to correctly initialize their
|
||||
* headers, there is no need to memset() the whole data.
|
||||
|
||||
@@ -19,7 +19,7 @@ struct xframe_queue {
|
||||
/* statistics */
|
||||
unsigned int worst_count;
|
||||
unsigned int overflows;
|
||||
s64 worst_lag_usec; /* since xframe creation */
|
||||
unsigned long worst_lag_usec; /* since xframe creation */
|
||||
};
|
||||
|
||||
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
|
||||
|
||||
@@ -31,8 +31,11 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/slab.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#include <linux/semaphore.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#include <linux/moduleparam.h>
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
@@ -74,7 +77,14 @@
|
||||
struct card_desc_struct {
|
||||
struct list_head card_list;
|
||||
u32 magic;
|
||||
struct unit_descriptor unit_descriptor;
|
||||
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
|
||||
__u8 subtype;
|
||||
struct xpd_addr xpd_addr;
|
||||
__u8 numchips;
|
||||
__u8 ports_per_chip;
|
||||
__u8 ports;
|
||||
__u8 port_dir;
|
||||
struct xpd_addr ec_addr; /* echo canceler address */
|
||||
};
|
||||
|
||||
typedef enum xpd_direction {
|
||||
@@ -163,12 +173,11 @@ struct phonedev {
|
||||
struct xpd {
|
||||
char xpdname[XPD_NAMELEN];
|
||||
struct phonedev phonedev;
|
||||
struct unit_descriptor unit_descriptor;
|
||||
#define XPD_HW(xpd) ((xpd)->unit_descriptor)
|
||||
|
||||
const struct xops *xops;
|
||||
xpd_type_t xpd_type;
|
||||
xpd_type_t type;
|
||||
const char *type_name;
|
||||
__u8 subtype;
|
||||
int subunits; /* all siblings */
|
||||
enum xpd_state xpd_state;
|
||||
struct device xpd_dev;
|
||||
@@ -207,7 +216,7 @@ struct xpd {
|
||||
|
||||
#define for_each_line(xpd, i) \
|
||||
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
||||
#define IS_BRI(xpd) ((xpd)->xpd_type == XPD_TYPE_BRI)
|
||||
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
|
||||
#define TICK_TOLERANCE 500 /* usec */
|
||||
|
||||
#ifdef DEBUG_SYNC_PARPORT
|
||||
@@ -227,7 +236,7 @@ static inline void *my_kzalloc(size_t size, gfp_t flags)
|
||||
}
|
||||
|
||||
struct xpd_driver {
|
||||
xpd_type_t xpd_type;
|
||||
xpd_type_t type;
|
||||
|
||||
struct device_driver driver;
|
||||
#define driver_to_xpd_driver(driver) \
|
||||
|
||||
11
drivers/dahdi/xpp/xpp.rules
Normal file
11
drivers/dahdi/xpp/xpp.rules
Normal file
@@ -0,0 +1,11 @@
|
||||
# Load firmware into the Xorcom Astribank device:
|
||||
SUBSYSTEM=="usb", ACTION=="add", \
|
||||
ENV{PRODUCT}=="e4e4/11[3456][013]/*", ENV{DEVTYPE}!="usb_interface", \
|
||||
RUN+="/usr/share/dahdi/xpp_fxloader udev $env{PRODUCT}"
|
||||
|
||||
# Hotplug hook for Astribank up/down
|
||||
# If you need this functionality, copy the astribank_hook.sample
|
||||
# to $XPP_INIT_DIR/astribank_hook
|
||||
#
|
||||
# By default XPP_INIT_DIR="/usr/share/dahdi"
|
||||
KERNEL=="xbus*", RUN+="%E{XPP_INIT_DIR}/astribank_hook udev $kernel $sysfs{status} $sysfs{connector}"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user