Compare commits
67 Commits
switched_t
...
v2.7.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce3f1f2650 | ||
|
|
2ad4dc555f | ||
|
|
0469efb733 | ||
|
|
8ea23535dc | ||
|
|
431571b5fc | ||
|
|
ab927f796b | ||
|
|
040ba6f43a | ||
|
|
e2f492595c | ||
|
|
1f20b5f8fa | ||
|
|
ba2fdf2dac | ||
|
|
84ccc652b6 | ||
|
|
40da50faed | ||
|
|
ef71ce476c | ||
|
|
e3e35d031d | ||
|
|
2b0cca777f | ||
|
|
96652d88c6 | ||
|
|
c4a17f9442 | ||
|
|
9b11847aee | ||
|
|
a3ad32c370 | ||
|
|
9a7db0943b | ||
|
|
db040e5cd7 | ||
|
|
244f621eb1 | ||
|
|
bb5eeccef3 | ||
|
|
4641d5b396 | ||
|
|
f65299e8b2 | ||
|
|
f4d9cbbfb1 | ||
|
|
a8788692a1 | ||
|
|
be904538c7 | ||
|
|
76dda31533 | ||
|
|
8f07b4e019 | ||
|
|
9c031f66a0 | ||
|
|
300446b1a1 | ||
|
|
949aa4958f | ||
|
|
a34b846f61 | ||
|
|
f09daed735 | ||
|
|
7714d5d94e | ||
|
|
9b0d19c054 | ||
|
|
d5e5b19a02 | ||
|
|
a4feafc124 | ||
|
|
0498450db0 | ||
|
|
b6f6232441 | ||
|
|
37a783b0fe | ||
|
|
37371f19e9 | ||
|
|
66a300f338 | ||
|
|
8bf0434896 | ||
|
|
a6be603590 | ||
|
|
85e6cdde83 | ||
|
|
69fb09d011 | ||
|
|
da0aa6f231 | ||
|
|
a46f906a0d | ||
|
|
9de213b104 | ||
|
|
19cef998bd | ||
|
|
82cf3c7b13 | ||
|
|
f916f1e91f | ||
|
|
a8dfd61e53 | ||
|
|
6846663d1e | ||
|
|
e1245b9dd6 | ||
|
|
00221e8bfd | ||
|
|
4da324d4df | ||
|
|
d863af110f | ||
|
|
cb4e4d0068 | ||
|
|
3a94ac322d | ||
|
|
53219879c8 | ||
|
|
5f7ebe98da | ||
|
|
ef065a5e2a | ||
|
|
f44b252472 | ||
|
|
d889fb39d3 |
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# Files that are generated as part of the build process which we do not want git
|
||||
# to track.
|
||||
|
||||
*.[oa]
|
||||
*.mod
|
||||
*.mod.[oc]
|
||||
*.ko
|
||||
*.cmd
|
||||
*.order
|
||||
*.tar.gz
|
||||
tags
|
||||
cscope.*
|
||||
*.symvers
|
||||
*.markers
|
||||
.*.o.d
|
||||
|
||||
README.html
|
||||
modules.order
|
||||
Module.markers
|
||||
build_tools/checkpatch.pl
|
||||
drivers/dahdi/xpp/*.verified
|
||||
drivers/dahdi/.tmp_versions/
|
||||
drivers/dahdi/Module.symvers
|
||||
drivers/dahdi/makefw
|
||||
drivers/dahdi/radfw.h
|
||||
drivers/dahdi/tor2fw.h
|
||||
drivers/dahdi/xpp/init_fxo_modes
|
||||
drivers/dahdi/xpp/print_fxo_modes
|
||||
drivers/dahdi/xpp/xpp_version.h
|
||||
include/dahdi/version.h
|
||||
drivers/dahdi/vpmadt032_loader/vpmadt032_loader.h
|
||||
drivers/dahdi/vpmadt032_loader/vpmadt032_x86_32.o_shipped
|
||||
drivers/dahdi/vpmadt032_loader/vpmadt032_x86_64.o_shipped
|
||||
drivers/dahdi/firmware/dahdi-fw-hx8.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-oct6114-064.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-oct6114-128.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-oct6114-256.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-tc400m.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-te820.bin
|
||||
drivers/dahdi/firmware/dahdi-fw-vpmoct032.bin
|
||||
drivers/dahdi/firmware/make_firmware_object
|
||||
22
Makefile
22
Makefile
@@ -64,17 +64,7 @@ ASCIIDOC_CMD:=$(ASCIIDOC) -n -a toc -a toclevels=4
|
||||
|
||||
GENERATED_DOCS:=README.html
|
||||
|
||||
ifneq ($(wildcard .version),)
|
||||
DAHDIVERSION:=$(shell cat .version)
|
||||
else
|
||||
ifneq ($(wildcard .svn),)
|
||||
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
|
||||
else
|
||||
ifneq ($(wildcard .git),)
|
||||
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
|
||||
|
||||
all: modules
|
||||
|
||||
@@ -92,7 +82,7 @@ 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)
|
||||
@@ -128,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; \
|
||||
@@ -195,6 +192,7 @@ ifneq (no,$(HAS_KSRC))
|
||||
endif
|
||||
@rm -f $(GENERATED_DOCS)
|
||||
$(MAKE) -C drivers/dahdi/firmware clean
|
||||
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x' clean
|
||||
|
||||
distclean: dist-clean
|
||||
|
||||
|
||||
284
README
284
README
@@ -445,57 +445,17 @@ reside directly under /sys/module/'module_name' .
|
||||
|
||||
Useful module parameters:
|
||||
|
||||
debug (most modules)::
|
||||
Sets debug mode / debug level. With most modules 'debug' can be either
|
||||
disabled (0, the default value) or enabled (any other value).
|
||||
+
|
||||
+
|
||||
wctdm and wcte1xp print several extra debugging messages if the value
|
||||
of debug is more than 1.
|
||||
+
|
||||
+
|
||||
Some modules have "debugging flags" bits - the value of debug is a
|
||||
bitmask and several messages are printed if some bits are set:
|
||||
- wctdm24xxp:
|
||||
* 1: DEBUG_CARD
|
||||
* 2: DEBUG_ECHOCAN
|
||||
- wct4xxp:
|
||||
* 1: DEBUG_MAIN
|
||||
* 2: DEBUG_DTMF
|
||||
* 4: DEBUG_REGS
|
||||
* 8: DEBUG_TSI
|
||||
* 16: DEBUG_ECHOCAN
|
||||
* 32: DEBUG_RBS
|
||||
* 64: DEBUG_FRAMER
|
||||
- xpp: See also README.Astribank:
|
||||
* 1: GENERAL - General debug comments.
|
||||
* 2: PCM - PCM-related messages. Tend to flood logs.
|
||||
* 4: LEDS - Anything related to the LEDs status control. The driver
|
||||
produces a lot of messages when the option is enabled.
|
||||
* 8: SYNC - Synchronization related messages.
|
||||
* 16: SIGNAL - DAHDI signalling related messages.
|
||||
* 32: PROC - Messages related to the procfs interface.
|
||||
* 64: REGS - Reading and writing to chip registers. Tends to flood
|
||||
logs.
|
||||
* 128: DEVICES - Device instantiation, destruction and such.
|
||||
* 256 - COMMANDS - Protocol commands. Tends to flood logs.
|
||||
=== debug
|
||||
(most modules)
|
||||
|
||||
deftaps (dahdi)::
|
||||
The default size for the echo canceller. The number is in "taps", that
|
||||
is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms.
|
||||
+
|
||||
+
|
||||
Asterisk's chan_dahdi tends to pass its own value anyway, with a
|
||||
different default size. So normally setting this doesn't change
|
||||
anything.
|
||||
Sets debug mode / debug level. With most modules 'debug' can be either
|
||||
disabled (0, the default value) or enabled (any other value).
|
||||
|
||||
max_pseudo_channels (dahdi)::
|
||||
The maximum number of pseudo channels that dahdi will allow userspace to
|
||||
create. Pseudo channels are used when conferencing channels together.
|
||||
The default is 512.
|
||||
wctdm and wcte1xp print several extra debugging messages if the value
|
||||
of debug is more than 1.
|
||||
|
||||
auto_assign_spans (dahdi)::
|
||||
See <<_span_assignments,Span Assignments>> below.
|
||||
Some modules have "debugging flags" bits - the value of debug is a
|
||||
bitmask and several messages are printed if some bits are set:
|
||||
|
||||
To get a list of parameters supported by a module, use
|
||||
|
||||
@@ -503,13 +463,178 @@ To get a list of parameters supported by a module, use
|
||||
|
||||
Or, for a module you have just built:
|
||||
|
||||
modinfo ./module_name.ko
|
||||
modinfo ./drivers/dahdi/module_name.ko
|
||||
|
||||
For the xpp modules this will also include the description and default
|
||||
value of the module. You can find a list of useful xpp module parameters
|
||||
in README.Astribank .
|
||||
|
||||
|
||||
- wctdm24xxp:
|
||||
* 1: DEBUG_CARD
|
||||
* 2: DEBUG_ECHOCAN
|
||||
- wct4xxp:
|
||||
* 1: DEBUG_MAIN
|
||||
* 2: DEBUG_DTMF
|
||||
* 4: DEBUG_REGS
|
||||
* 8: DEBUG_TSI
|
||||
* 16: DEBUG_ECHOCAN
|
||||
* 32: DEBUG_RBS
|
||||
* 64: DEBUG_FRAMER
|
||||
- xpp: See also README.Astribank:
|
||||
* 1: GENERAL - General debug comments.
|
||||
* 2: PCM - PCM-related messages. Tend to flood logs.
|
||||
* 4: LEDS - Anything related to the LEDs status control. The driver
|
||||
produces a lot of messages when the option is enabled.
|
||||
* 8: SYNC - Synchronization related messages.
|
||||
* 16: SIGNAL - DAHDI signalling related messages.
|
||||
* 32: PROC - Messages related to the procfs interface.
|
||||
* 64: REGS - Reading and writing to chip registers. Tends to flood
|
||||
logs.
|
||||
* 128: DEVICES - Device instantiation, destruction and such.
|
||||
* 256 - COMMANDS - Protocol commands. Tends to flood logs.
|
||||
+
|
||||
+
|
||||
The script xpp_debug in the source tree can help settting them at run
|
||||
time.
|
||||
|
||||
=== deftaps
|
||||
(dahdi)
|
||||
|
||||
The default size for the echo canceller. The number is in "taps", that
|
||||
is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms.
|
||||
|
||||
Asterisk's chan_dahdi tends to pass its own value anyway, with a
|
||||
different default size. So normally setting this doesn't change
|
||||
anything.
|
||||
|
||||
=== max_pseudo_channels
|
||||
(dahdi)
|
||||
|
||||
The maximum number of pseudo channels that dahdi will allow userspace to
|
||||
create. Pseudo channels are used when conferencing channels together.
|
||||
The default is 512.
|
||||
|
||||
=== auto_assign_spans
|
||||
(dahdi)
|
||||
|
||||
See <<_span_assignments,Span Assignments>> below.
|
||||
|
||||
XPP (Astribank) module parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
==== debug
|
||||
(all modules) - see above.
|
||||
|
||||
==== dahdi_autoreg
|
||||
(xpp)
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
|
||||
==== rx_tasklet
|
||||
(xpp)
|
||||
|
||||
Enable (1) or disable (0) doing most of the packets processing in
|
||||
separate tasklets. This should probably help on higher-end systems with
|
||||
multiple Astribanks.
|
||||
|
||||
==== vmwi_ioctl
|
||||
(xpd_fxs)
|
||||
|
||||
Does userspace support VMWI notification via ioctl? Default: 1 (yes).
|
||||
|
||||
Disable this (0) to have the driver attempt to detect the voicemail
|
||||
message waiting indication status for this port from FSK messages
|
||||
userspace (Asterisk) sends. Set the ports to use AC neon-lamp style
|
||||
message waiting indication. The detection from the FSK messages takes
|
||||
extra CPU cycles but is required with e.g. Asterisk < 1.6.0 .
|
||||
|
||||
Also note that in order for this parameter to take effect, it must be
|
||||
set before the span is registered. This practically means that it
|
||||
should be set through modprobe.d files.
|
||||
|
||||
See also Voicemail Indication in README.Astribank.
|
||||
|
||||
==== usb1
|
||||
(xpp_usb)
|
||||
|
||||
Enable (1) or disable (0) support of USB1 devices. Disabled by default.
|
||||
|
||||
USB1 devices are not well-tested. It seems that they don't work at all
|
||||
for Astribank BRI. Generally they should work with the current code, but
|
||||
we expect the voice quality issues. Hence we would like to make it
|
||||
very clear that you if you have a USB1 port (rather than a USB2 one, as
|
||||
recommended) you will have to take an action to enable the device.
|
||||
|
||||
==== poll intervals
|
||||
(various)
|
||||
|
||||
There are various values which the driver occasionally polls the
|
||||
device for. For instance, the parameter poll_battery_interval for
|
||||
xpd_fxo to poll the battery, in order to know if the telco line is
|
||||
actually connected.
|
||||
|
||||
The value of those parameters is typically a number in milliseconds.
|
||||
0 is used to disable polling. Under normal operation there should be
|
||||
no reason to play with those parameters.
|
||||
|
||||
==== dtmf_detection
|
||||
(xpd_fxs)
|
||||
|
||||
Enable (1) or disable (0) support of hardware DTMF detection by the
|
||||
Astribank.
|
||||
|
||||
==== caller_id_style
|
||||
(xpd_fxo)
|
||||
|
||||
Various types of caller ID signalling styles require knowing the PCM
|
||||
even when the line is on-hook (which is usually a waste of CPU and
|
||||
bandwidth). This parameter allows fine-tuning the behaviour here:
|
||||
|
||||
* 0 (default) - Don't pass extra PCM when on-hook.
|
||||
* 1 ETSI-FSK: Wait for polarity reversal to come before a ring and
|
||||
then start passing PCM until the caller ID has been passed.
|
||||
* 2 ETSI-DTMF: Always pass PCM and generate a DTMF if polarity reversal is
|
||||
detected before ring.
|
||||
* 3 Passthrough: Always pass PCM as-is.
|
||||
|
||||
This parameter is read-only. It cannot be changed at run-time.
|
||||
|
||||
==== battery_threshold
|
||||
(xpd_fxo)
|
||||
|
||||
Minimum voltage that shows there is battery. Defaults to 3. Normally you
|
||||
should not need to change this, unless dealing with a funky PSTN
|
||||
provider.
|
||||
|
||||
==== battery_debounce
|
||||
(xpd_fxo)
|
||||
|
||||
Minimum interval (msec) for detection of battery off (as opposed to e.g.
|
||||
a temporary power denial to signal a hangup). Defaults to 1000. As with
|
||||
battery_threshold above, there's normally no need to tweak it.
|
||||
|
||||
==== use_polrev_firmware
|
||||
(xpd_fxo)
|
||||
|
||||
Enable (1, default) or disable (0) support for polarity reversal
|
||||
detection in the hardware. Only has effect with PIC_TYPE_2.hex rev. >=
|
||||
11039 and with the initialization changes (init_card_2_30) in rev.
|
||||
949aa49.
|
||||
|
||||
This parameter is read-only. It cannot be changed at run-time.
|
||||
|
||||
|
||||
Internals
|
||||
---------
|
||||
DAHDI Device Files
|
||||
@@ -521,9 +646,14 @@ or dynamically through the udev system.
|
||||
|
||||
* /dev/dahdi/ctl (196:0) - a general device file for various information and
|
||||
control operations on the DAHDI channels.
|
||||
* /dev/dahdi/chan/N/M - A device file for channel M in span N
|
||||
- Both N and M are zero padded 3 digit numbers
|
||||
- Both N and M start at 001
|
||||
- M is chanpos - numbering relative to the current span.
|
||||
* /dev/dahdi/NNN (196:NNN) - for NNN in the range 1-249. A device file for
|
||||
DAHDI channel NNN. It can be used to read data from the channel
|
||||
and write data to the channel.
|
||||
and write data to the channel. It is not generated by default but may
|
||||
be generated as a symlink using udev rules.
|
||||
* /dev/dahdi/transcode (196:250) - Used to connect to a DAHDI transcoding
|
||||
device.
|
||||
* /dev/dahdi/timer (196:253) - Allows setting timers. Used anywhere?
|
||||
@@ -851,6 +981,60 @@ A very short type string.
|
||||
Current sync source.
|
||||
|
||||
|
||||
Channels Bus
|
||||
^^^^^^^^^^^^
|
||||
Each DAHDI channel is represented by a node under
|
||||
/sys/bus/dahdi_channels/devices with the name 'dahdi!channels!N!M'
|
||||
(where N is the number of the span and M is the number of the channel
|
||||
in the span - chanpos). Channels of each span also reside under the node
|
||||
of the span.
|
||||
|
||||
Useful attributes in the channel node (All attributed listed below are
|
||||
read-only):
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/alarms
|
||||
List of names of the current active alarms (space separated). Normally
|
||||
(no alarms) empty. Example:
|
||||
|
||||
RED YELLOW
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/blocksize
|
||||
The block size set by userspace.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/channo
|
||||
The (global) channel number.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/chanpos
|
||||
The channel number within the span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/dev
|
||||
Major and minor device numbers.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/ec_factory
|
||||
The name of the echo canceller to be used in the channel, if one is
|
||||
configured. Example:
|
||||
|
||||
MG2
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/ec_state
|
||||
State of the echo canceller. ACTIVE: configured and inuse. INACTIVE
|
||||
otherwise.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/in_use
|
||||
1 if the channel is in use (was opepend by userspace), 0 otherwise.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/name
|
||||
A name string for the channel
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/sig
|
||||
The signalling types set for the channel. A space-separated list of
|
||||
signalling types.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/sigcap
|
||||
The signalling types this channel may be configured to handle. A space-
|
||||
separated list of signalling types.
|
||||
|
||||
|
||||
User-space Interface
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
User-space programs can only work with DAHDI channels. The basic
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -f ${1}/.version ]; then
|
||||
cat ${1}.version
|
||||
cat ${1}/.version
|
||||
elif [ -f ${1}/.svnrevision ]; then
|
||||
echo SVN-`cat ${1}/.svnbranch`-r`cat ${1}/.svnrevision`
|
||||
elif [ -d ${1}/.svn ]; then
|
||||
@@ -59,7 +59,7 @@ elif [ -d ${1}/.git ]; then
|
||||
MODIFIED=""
|
||||
SVN_REV=`git log --pretty=full -1 | grep -F "git-svn-id:" | sed -e "s/.*\@\([^\s]*\)\s.*/\1/g"`
|
||||
if [ -z "$SVN_REV" ]; then
|
||||
VERSION=`git describe --long --always --tags --dirty=M 2> /dev/null`
|
||||
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"
|
||||
@@ -115,4 +115,8 @@ elif [ -d ${1}/.git ]; then
|
||||
|
||||
echo SVN-${RESULT##-}-r${SVN_REV}${MODIFIED}
|
||||
fi
|
||||
else
|
||||
# Use the directory information in the absence of any other version
|
||||
# information
|
||||
pwd -P
|
||||
fi
|
||||
|
||||
@@ -11,6 +11,14 @@ 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 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_WCTDM) += wctdm.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/
|
||||
@@ -38,7 +46,7 @@ obj-m += $(DAHDI_MODULES_EXTRA)
|
||||
# well:
|
||||
ifneq (,$(wildcard $(src)/../staging/echo/echo.c))
|
||||
obj-m += dahdi_echocan_oslec.o
|
||||
obj-m += ../staging/echo/
|
||||
obj-m += ../staging/echo/echo.o
|
||||
endif
|
||||
|
||||
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src)
|
||||
|
||||
@@ -176,6 +176,17 @@ static sumtype *conf_sums_prev;
|
||||
static struct dahdi_span *master;
|
||||
struct file_operations *dahdi_transcode_fops = NULL;
|
||||
|
||||
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
static struct {
|
||||
int src; /* source conf number */
|
||||
int dst; /* dst conf number */
|
||||
} conf_links[DAHDI_MAX_CONF + 1];
|
||||
|
||||
static int maxlinks;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DAHDI_CORE_TIMER
|
||||
|
||||
static struct core_timer {
|
||||
@@ -283,6 +294,7 @@ static inline void dahdi_kernel_fpu_end(void)
|
||||
#endif
|
||||
|
||||
struct dahdi_timer {
|
||||
spinlock_t lock;
|
||||
int ms; /* Countdown */
|
||||
int pos; /* Position */
|
||||
int ping; /* Whether we've been ping'd */
|
||||
@@ -811,7 +823,7 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
|
||||
EXPORT_SYMBOL(lineconfig_str);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static const char *sigstr(int sig)
|
||||
const char *sigstr(int sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case DAHDI_SIG_FXSLS:
|
||||
@@ -858,7 +870,7 @@ static const char *sigstr(int sig)
|
||||
}
|
||||
}
|
||||
|
||||
static int fill_alarm_string(char *buf, int count, int alarms)
|
||||
int fill_alarm_string(char *buf, int count, int alarms)
|
||||
{
|
||||
int len;
|
||||
|
||||
@@ -888,7 +900,7 @@ static void seq_fill_alarm_string(struct seq_file *sfile, int alarms)
|
||||
seq_printf(sfile, "%s", tmp);
|
||||
}
|
||||
|
||||
static int dahdi_seq_show(struct seq_file *sfile, void *v)
|
||||
static int dahdi_seq_show(struct seq_file *sfile, void *data)
|
||||
{
|
||||
long spanno = (long)sfile->private;
|
||||
int x;
|
||||
@@ -932,8 +944,8 @@ static int dahdi_seq_show(struct seq_file *sfile, void *v)
|
||||
seq_printf(sfile, "\tFAS error count: %d\n", s->count.fas);
|
||||
if (s->parent->irqmisses)
|
||||
seq_printf(sfile, "\tIRQ misses: %d\n", s->parent->irqmisses);
|
||||
if (s->timingslips)
|
||||
seq_printf(sfile, "\tTiming slips: %d\n", s->timingslips);
|
||||
if (s->count.timingslips)
|
||||
seq_printf(sfile, "\tTiming slips: %d\n", s->count.timingslips);
|
||||
seq_printf(sfile, "\n");
|
||||
|
||||
for (x = 0; x < s->channels; x++) {
|
||||
@@ -980,7 +992,7 @@ static int dahdi_seq_show(struct seq_file *sfile, void *v)
|
||||
|
||||
static int dahdi_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dahdi_seq_show, PDE(inode)->data);
|
||||
return single_open(file, dahdi_seq_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations dahdi_proc_ops = {
|
||||
@@ -1060,10 +1072,29 @@ static unsigned long _chan_in_conf(struct dahdi_chan *chan, unsigned long x)
|
||||
confmode == DAHDI_CONF_REALANDPSEUDO)) ? 1 : 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
static void recalc_maxlinks(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = DAHDI_MAX_CONF - 1; x > 0; x--) {
|
||||
if (conf_links[x].src || conf_links[x].dst) {
|
||||
maxlinks = x + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
maxlinks = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dahdi_check_conf(int x)
|
||||
{
|
||||
unsigned long res;
|
||||
unsigned long flags;
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
int i;
|
||||
#endif
|
||||
|
||||
/* return if no valid conf number */
|
||||
if (x <= 0)
|
||||
@@ -1086,6 +1117,17 @@ static void dahdi_check_conf(int x)
|
||||
|
||||
/* Highest conference may have changed */
|
||||
recalc_maxconfs();
|
||||
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
/* And unlink it from any conflinks */
|
||||
for (i = DAHDI_MAX_CONF - 1; i > 0; i--) {
|
||||
if (conf_links[i].src == x)
|
||||
conf_links[i].src = 0;
|
||||
if (conf_links[i].dst == x)
|
||||
conf_links[i].dst = 0;
|
||||
}
|
||||
recalc_maxlinks();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* enqueue an event on a channel */
|
||||
@@ -1922,7 +1964,6 @@ static int dahdi_net_open(struct net_device *dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
ms->txbufpolicy = DAHDI_POLICY_IMMEDIATE;
|
||||
ms->rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
|
||||
|
||||
res = dahdi_reallocbufs(ms, DAHDI_DEFAULT_MTU_MRU, DAHDI_DEFAULT_NUM_BUFS);
|
||||
if (res)
|
||||
@@ -2957,50 +2998,42 @@ static int initialize_channel(struct dahdi_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dahdi_timing_open(struct file *file)
|
||||
static const struct file_operations dahdi_timer_fops;
|
||||
|
||||
static int dahdi_timer_open(struct file *file)
|
||||
{
|
||||
struct dahdi_timer *t;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(t = kzalloc(sizeof(*t), GFP_KERNEL)))
|
||||
struct dahdi_timer *t = kzalloc(sizeof(*t), GFP_KERNEL);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
init_waitqueue_head(&t->sel);
|
||||
INIT_LIST_HEAD(&t->list);
|
||||
init_waitqueue_head(&t->sel);
|
||||
file->private_data = t;
|
||||
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
list_add(&t->list, &dahdi_timers);
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_lock_init(&t->lock);
|
||||
file->f_op = &dahdi_timer_fops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dahdi_timer_release(struct file *file)
|
||||
static int dahdi_timer_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dahdi_timer *t, *cur, *next;
|
||||
struct dahdi_timer *timer = file->private_data;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(t = file->private_data))
|
||||
if (!timer)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(cur, next, &dahdi_timers, list) {
|
||||
if (t == cur) {
|
||||
list_del(&cur->list);
|
||||
break;
|
||||
}
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if (!list_empty(&timer->list)) {
|
||||
spin_unlock(&timer->lock);
|
||||
spin_lock(&dahdi_timer_lock);
|
||||
spin_lock(&timer->lock);
|
||||
list_del_init(&timer->list);
|
||||
spin_unlock(&dahdi_timer_lock);
|
||||
}
|
||||
file->private_data = NULL;
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
|
||||
if (!cur) {
|
||||
module_printk(KERN_NOTICE, "Timer: Not on list??\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
kfree(cur);
|
||||
kfree(timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3238,7 +3271,7 @@ static int dahdi_open(struct inode *inode, struct file *file)
|
||||
}
|
||||
if (unit == DAHDI_TIMER) {
|
||||
if (can_open_timer()) {
|
||||
return dahdi_timing_open(file);
|
||||
return dahdi_timer_open(file);
|
||||
} else {
|
||||
return -ENXIO;
|
||||
}
|
||||
@@ -3740,7 +3773,7 @@ static int dahdi_release(struct inode *inode, struct file *file)
|
||||
if (unit == DAHDI_CTL)
|
||||
return dahdi_ctl_release(file);
|
||||
if (unit == DAHDI_TIMER) {
|
||||
return dahdi_timer_release(file);
|
||||
return dahdi_timer_release(inode, file);
|
||||
}
|
||||
if (unit == DAHDI_TRANSCODE) {
|
||||
/* We should not be here because the dahdi_transcode.ko module
|
||||
@@ -3890,48 +3923,74 @@ void dahdi_alarm_notify(struct dahdi_span *span)
|
||||
}
|
||||
}
|
||||
|
||||
static int dahdi_timer_ioctl(struct file *file, unsigned int cmd, unsigned long data, struct dahdi_timer *timer)
|
||||
static long
|
||||
dahdi_timer_unlocked_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
int j;
|
||||
unsigned long flags;
|
||||
struct dahdi_timer *const timer = file->private_data;
|
||||
|
||||
switch(cmd) {
|
||||
case DAHDI_TIMERCONFIG:
|
||||
get_user(j, (int __user *)data);
|
||||
if (j < 0)
|
||||
j = 0;
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
timer->ms = timer->pos = j;
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if (timer->ms != j) {
|
||||
if (j && list_empty(&timer->list)) {
|
||||
/* The timer is being activated so add to the
|
||||
* global timer list. */
|
||||
spin_unlock(&timer->lock);
|
||||
spin_lock(&dahdi_timer_lock);
|
||||
spin_lock(&timer->lock);
|
||||
timer->ms = timer->pos = j;
|
||||
list_add(&timer->list, &dahdi_timers);
|
||||
spin_unlock(&dahdi_timer_lock);
|
||||
} else if (!j && !list_empty(&timer->list)) {
|
||||
/* The timer is being disabled so we can remove
|
||||
* from the global timer list. */
|
||||
spin_unlock(&timer->lock);
|
||||
spin_lock(&dahdi_timer_lock);
|
||||
spin_lock(&timer->lock);
|
||||
list_del_init(&timer->list);
|
||||
timer->ms = timer->pos = j;
|
||||
spin_unlock(&dahdi_timer_lock);
|
||||
} else {
|
||||
timer->ms = timer->pos = j;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
break;
|
||||
case DAHDI_TIMERACK:
|
||||
get_user(j, (int __user *)data);
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if ((j < 1) || (j > timer->tripped))
|
||||
j = timer->tripped;
|
||||
timer->tripped -= j;
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
break;
|
||||
case DAHDI_GETEVENT: /* Get event on queue */
|
||||
j = DAHDI_EVENT_NONE;
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
/* set up for no event */
|
||||
if (timer->tripped)
|
||||
j = DAHDI_EVENT_TIMER_EXPIRED;
|
||||
if (timer->ping)
|
||||
j = DAHDI_EVENT_TIMER_PING;
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
put_user(j, (int __user *)data);
|
||||
break;
|
||||
case DAHDI_TIMERPING:
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
timer->ping = 1;
|
||||
wake_up_interruptible(&timer->sel);
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
break;
|
||||
case DAHDI_TIMERPONG:
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
timer->ping = 0;
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
break;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
@@ -3939,6 +3998,14 @@ static int dahdi_timer_ioctl(struct file *file, unsigned int cmd, unsigned long
|
||||
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;
|
||||
@@ -4480,6 +4547,90 @@ static int dahdi_ioctl_spanstat_v1(struct file *file, unsigned long data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
static int dahdi_ioctl_conflink(struct file *file, unsigned long data)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
struct dahdi_confinfo conf;
|
||||
unsigned long flags;
|
||||
int res = 0;
|
||||
int i;
|
||||
|
||||
chan = chan_from_file(file);
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
if (!(chan->flags & DAHDI_FLAG_AUDIO))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&conf, (void __user *)data, sizeof(conf)))
|
||||
return -EFAULT;
|
||||
/* check sanity of arguments */
|
||||
if ((conf.chan < 0) || (conf.chan > DAHDI_MAX_CONF))
|
||||
return -EINVAL;
|
||||
if ((conf.confno < 0) || (conf.confno > DAHDI_MAX_CONF))
|
||||
return -EINVAL;
|
||||
/* cant listen to self!! */
|
||||
if (conf.chan && (conf.chan == conf.confno))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&chan_lock, flags);
|
||||
spin_lock(&chan->lock);
|
||||
|
||||
/* if to clear all links */
|
||||
if ((!conf.chan) && (!conf.confno)) {
|
||||
/* clear all the links */
|
||||
memset(conf_links, 0, sizeof(conf_links));
|
||||
recalc_maxlinks();
|
||||
spin_unlock(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
/* look for already existant specified combination */
|
||||
for (i = 1; i <= DAHDI_MAX_CONF; i++) {
|
||||
/* if found, exit */
|
||||
if ((conf_links[i].src == conf.chan) &&
|
||||
(conf_links[i].dst == conf.confno))
|
||||
break;
|
||||
}
|
||||
if (i <= DAHDI_MAX_CONF) { /* if found */
|
||||
if (!conf.confmode) { /* if to remove link */
|
||||
conf_links[i].src = 0;
|
||||
conf_links[i].dst = 0;
|
||||
} else { /* if to add and already there, error */
|
||||
res = -EEXIST;
|
||||
}
|
||||
} else { /* if not found */
|
||||
if (conf.confmode) { /* if to add link */
|
||||
/* look for empty location */
|
||||
for (i = 1; i <= DAHDI_MAX_CONF; i++) {
|
||||
/* if empty, exit loop */
|
||||
if ((!conf_links[i].src) &&
|
||||
(!conf_links[i].dst))
|
||||
break;
|
||||
}
|
||||
/* if empty spot found */
|
||||
if (i <= DAHDI_MAX_CONF) {
|
||||
conf_links[i].src = conf.chan;
|
||||
conf_links[i].dst = conf.confno;
|
||||
} else { /* if no empties -- error */
|
||||
res = -ENOSPC;
|
||||
}
|
||||
} else { /* if to remove, and not found -- error */
|
||||
res = -ENOENT;
|
||||
}
|
||||
}
|
||||
recalc_maxlinks();
|
||||
spin_unlock(&chan->lock);
|
||||
spin_unlock_irqrestore(&chan_lock, flags);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
static int dahdi_ioctl_conflink(struct file *file, unsigned long data)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int dahdi_common_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
@@ -4508,6 +4659,10 @@ static int dahdi_common_ioctl(struct file *file, unsigned int cmd,
|
||||
case DAHDI_CHANDIAG_V1: /* Intentional drop through. */
|
||||
case DAHDI_CHANDIAG:
|
||||
return dahdi_ioctl_chandiag(file, data);
|
||||
|
||||
case DAHDI_CONFLINK:
|
||||
return dahdi_ioctl_conflink(file, data);
|
||||
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
@@ -4981,11 +5136,28 @@ static int dahdi_ioctl_startup(struct file *file, unsigned long data)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int dahdi_shutdown_span(struct dahdi_span *s)
|
||||
{
|
||||
int res = 0;
|
||||
int x;
|
||||
|
||||
/* Unconfigure channels */
|
||||
for (x = 0; x < s->channels; x++)
|
||||
s->chans[x]->sig = 0;
|
||||
|
||||
if (s->ops->shutdown)
|
||||
res = s->ops->shutdown(s);
|
||||
|
||||
clear_bit(DAHDI_FLAGBIT_RUNNING, &s->flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int dahdi_ioctl_shutdown(unsigned long data)
|
||||
{
|
||||
int res;
|
||||
/* I/O CTL's for control interface */
|
||||
int j;
|
||||
int x;
|
||||
|
||||
struct dahdi_span *s;
|
||||
|
||||
if (get_user(j, (int __user *)data))
|
||||
@@ -4993,22 +5165,9 @@ static int dahdi_ioctl_shutdown(unsigned long data)
|
||||
s = span_find_and_get(j);
|
||||
if (!s)
|
||||
return -ENXIO;
|
||||
|
||||
/* Unconfigure channels */
|
||||
for (x = 0; x < s->channels; x++)
|
||||
s->chans[x]->sig = 0;
|
||||
|
||||
if (s->ops->shutdown) {
|
||||
int res = s->ops->shutdown(s);
|
||||
if (res) {
|
||||
put_span(s);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
s->flags &= ~DAHDI_FLAG_RUNNING;
|
||||
res = dahdi_shutdown_span(s);
|
||||
put_span(s);
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5210,7 +5369,8 @@ static int dahdi_ioctl_maint(unsigned long data)
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
/* save current maint state */
|
||||
i = s->maintstat;
|
||||
|
||||
/* set maint mode */
|
||||
s->maintstat = maint.command;
|
||||
switch (maint.command) {
|
||||
case DAHDI_MAINT_NONE:
|
||||
case DAHDI_MAINT_LOCALLOOP:
|
||||
@@ -5223,6 +5383,8 @@ static int dahdi_ioctl_maint(unsigned long data)
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
if (rv) {
|
||||
put_span(s);
|
||||
/* Restore the state on error */
|
||||
s->maintstat = i;
|
||||
return rv;
|
||||
}
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
@@ -5234,6 +5396,8 @@ static int dahdi_ioctl_maint(unsigned long data)
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
if (rv) {
|
||||
put_span(s);
|
||||
/* Restore the state on error */
|
||||
s->maintstat = i;
|
||||
return rv;
|
||||
}
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
@@ -5257,6 +5421,8 @@ static int dahdi_ioctl_maint(unsigned long data)
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
if (rv) {
|
||||
put_span(s);
|
||||
/* Restore the state on error */
|
||||
s->maintstat = i;
|
||||
return rv;
|
||||
}
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
@@ -5267,12 +5433,10 @@ static int dahdi_ioctl_maint(unsigned long data)
|
||||
"Unknown maintenance event: %d\n",
|
||||
maint.command);
|
||||
put_span(s);
|
||||
/* Restore the state on error */
|
||||
s->maintstat = i;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* set maint mode */
|
||||
s->maintstat = maint.command;
|
||||
|
||||
dahdi_alarm_notify(s); /* process alarm-related events */
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
put_span(s);
|
||||
@@ -5580,10 +5744,10 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data)
|
||||
for (i = ((j) ? j : 1); i <= ((j) ? j : DAHDI_MAX_CONF); i++) {
|
||||
struct dahdi_span *s;
|
||||
struct pseudo_chan *pseudo;
|
||||
int k;
|
||||
c = 0;
|
||||
spin_lock_irqsave(&chan_lock, flags);
|
||||
list_for_each_entry(s, &span_list, spans_node) {
|
||||
int k;
|
||||
for (k = 0; k < s->channels; k++) {
|
||||
chan = s->chans[k];
|
||||
if (chan->confna != i)
|
||||
@@ -5605,6 +5769,29 @@ static int dahdi_ioctl_confdiag(struct file *file, unsigned long data)
|
||||
module_printk(KERN_NOTICE, "chan %d, mode %x\n",
|
||||
pseudo->chan.channo, pseudo->chan.confmode);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
{
|
||||
int rv;
|
||||
rv = 0;
|
||||
for (k = 1; k <= DAHDI_MAX_CONF; k++) {
|
||||
if (conf_links[k].dst == i) {
|
||||
if (!c) {
|
||||
c = 1;
|
||||
module_printk(KERN_NOTICE,
|
||||
"Conf #%d:\n", i);
|
||||
}
|
||||
if (!rv) {
|
||||
rv = 1;
|
||||
module_printk(KERN_NOTICE,
|
||||
"Snooping on:\n");
|
||||
}
|
||||
module_printk(KERN_NOTICE, "conf %d\n",
|
||||
conf_links[k].src);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
spin_unlock_irqrestore(&chan_lock, flags);
|
||||
if (c)
|
||||
module_printk(KERN_NOTICE, "\n");
|
||||
@@ -6704,16 +6891,11 @@ static long
|
||||
dahdi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data)
|
||||
{
|
||||
int unit = UNIT(file);
|
||||
struct dahdi_timer *timer;
|
||||
int ret;
|
||||
|
||||
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
|
||||
lock_kernel();
|
||||
#endif
|
||||
|
||||
if (unit == DAHDI_CTL) {
|
||||
ret = dahdi_ctl_ioctl(file, cmd, data);
|
||||
goto unlock_exit;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (unit == DAHDI_TRANSCODE) {
|
||||
@@ -6721,45 +6903,41 @@ dahdi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long data)
|
||||
* this file object on open, so we shouldn't be here. */
|
||||
WARN_ON(1);
|
||||
ret = -EFAULT;
|
||||
goto unlock_exit;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (unit == DAHDI_TIMER) {
|
||||
timer = file->private_data;
|
||||
if (timer)
|
||||
ret = dahdi_timer_ioctl(file, cmd, data, timer);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
goto unlock_exit;
|
||||
/* The file operations for a timer device should have been
|
||||
* updated. */
|
||||
WARN_ON(1);
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
if (unit == DAHDI_CHANNEL) {
|
||||
if (file->private_data)
|
||||
ret = dahdi_chan_ioctl(file, cmd, data);
|
||||
else
|
||||
ret = dahdi_prechan_ioctl(file, cmd, data);
|
||||
goto unlock_exit;
|
||||
goto exit;
|
||||
}
|
||||
if (unit == DAHDI_PSEUDO) {
|
||||
if (!file->private_data) {
|
||||
module_printk(KERN_NOTICE, "No pseudo channel structure to read?\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock_exit;
|
||||
goto exit;
|
||||
}
|
||||
ret = dahdi_chanandpseudo_ioctl(file, cmd, data);
|
||||
goto unlock_exit;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!file->private_data) {
|
||||
ret = -ENXIO;
|
||||
goto unlock_exit;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = dahdi_chan_ioctl(file, cmd, data);
|
||||
|
||||
unlock_exit:
|
||||
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
|
||||
unlock_kernel();
|
||||
#endif
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -6843,7 +7021,7 @@ static int _assign_spanno_and_basechan(struct dahdi_span *span)
|
||||
}
|
||||
|
||||
next_channo = _get_next_channo(pos);
|
||||
if ((basechan + span->channels) >= next_channo)
|
||||
if ((basechan + span->channels) <= next_channo)
|
||||
break;
|
||||
|
||||
/* We can't fit here, let's look at the next location. */
|
||||
@@ -7081,15 +7259,14 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
|
||||
{
|
||||
char tempfile[17];
|
||||
snprintf(tempfile, sizeof(tempfile), "%d", span->spanno);
|
||||
span->proc_entry = create_proc_entry(tempfile, 0444,
|
||||
root_proc_entry);
|
||||
span->proc_entry = proc_create_data(tempfile, 0444,
|
||||
root_proc_entry, &dahdi_proc_ops,
|
||||
(void *)((unsigned long)span->spanno));
|
||||
if (!span->proc_entry) {
|
||||
res = -EFAULT;
|
||||
span_err(span, "Error creating procfs entry\n");
|
||||
goto cleanup;
|
||||
}
|
||||
span->proc_entry->data = (void *)(long)span->spanno;
|
||||
span->proc_entry->proc_fops = &dahdi_proc_ops;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7237,6 +7414,15 @@ static void disable_span(struct dahdi_span *span)
|
||||
module_printk(KERN_INFO, "%s: span %d\n", __func__, span->spanno);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
|
||||
static inline void proc_remove(struct proc_dir_entry *proc_entry)
|
||||
{
|
||||
remove_proc_entry(proc_entry->name, root_proc_entry);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* _dahdi_unassign_span() - unassign a DAHDI span
|
||||
* @span: the DAHDI span
|
||||
@@ -7249,6 +7435,7 @@ static void disable_span(struct dahdi_span *span)
|
||||
*/
|
||||
static int _dahdi_unassign_span(struct dahdi_span *span)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
struct dahdi_span *new_master, *s;
|
||||
unsigned long flags;
|
||||
@@ -7265,15 +7452,19 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
|
||||
span->spanno = 0;
|
||||
clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
|
||||
|
||||
/* Shutdown the span if it's running */
|
||||
if ((span->flags & DAHDI_FLAG_RUNNING) && span->ops->shutdown)
|
||||
span->ops->shutdown(span);
|
||||
res = dahdi_shutdown_span(span);
|
||||
if (res) {
|
||||
dev_err(span_device(span),
|
||||
"Failed to shutdown when unassigning.\n");
|
||||
}
|
||||
|
||||
if (debug & DEBUG_MAIN)
|
||||
module_printk(KERN_NOTICE, "Unassigning Span '%s' with %d channels\n", span->name, span->channels);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (span->proc_entry)
|
||||
remove_proc_entry(span->proc_entry->name, root_proc_entry);
|
||||
if (span->proc_entry) {
|
||||
proc_remove(span->proc_entry);
|
||||
span->proc_entry = NULL;
|
||||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
span_sysfs_remove(span);
|
||||
@@ -8353,7 +8544,6 @@ void dahdi_rbsbits(struct dahdi_chan *chan, int cursig)
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case DAHDI_SIG_EM: /* E and M */
|
||||
case DAHDI_SIG_EM_E1:
|
||||
case DAHDI_SIG_FXOLS: /* FXO Loopstart */
|
||||
case DAHDI_SIG_FXOKS: /* FXO Kewlstart */
|
||||
@@ -8362,7 +8552,13 @@ void dahdi_rbsbits(struct dahdi_chan *chan, int cursig)
|
||||
else /* on hook */
|
||||
__dahdi_hooksig_pvt(chan,DAHDI_RXSIG_ONHOOK);
|
||||
break;
|
||||
|
||||
case DAHDI_SIG_EM: /* E and M */
|
||||
/* Watch only the ABIT for changes. */
|
||||
if ((cursig & DAHDI_ABIT) == (chan->rxsig & DAHDI_ABIT))
|
||||
break;
|
||||
__dahdi_hooksig_pvt(chan, (cursig & DAHDI_ABIT) ?
|
||||
DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
|
||||
break;
|
||||
case DAHDI_SIG_FXSKS: /* FXS Kewlstart */
|
||||
case DAHDI_SIG_FXSGS: /* FXS Groundstart */
|
||||
/* Fall through */
|
||||
@@ -9302,14 +9498,14 @@ static void process_timers(void)
|
||||
|
||||
spin_lock(&dahdi_timer_lock);
|
||||
list_for_each_entry(cur, &dahdi_timers, list) {
|
||||
if (cur->ms) {
|
||||
cur->pos -= DAHDI_CHUNKSIZE;
|
||||
if (cur->pos <= 0) {
|
||||
cur->tripped++;
|
||||
cur->pos = cur->ms;
|
||||
wake_up_interruptible(&cur->sel);
|
||||
}
|
||||
spin_lock(&cur->lock);
|
||||
cur->pos -= DAHDI_CHUNKSIZE;
|
||||
if (cur->pos <= 0) {
|
||||
cur->tripped++;
|
||||
cur->pos = cur->ms;
|
||||
wake_up_interruptible(&cur->sel);
|
||||
}
|
||||
spin_unlock(&cur->lock);
|
||||
}
|
||||
spin_unlock(&dahdi_timer_lock);
|
||||
}
|
||||
@@ -9321,10 +9517,10 @@ static unsigned int dahdi_timer_poll(struct file *file, struct poll_table_struct
|
||||
int ret = 0;
|
||||
if (timer) {
|
||||
poll_wait(file, &timer->sel, wait_table);
|
||||
spin_lock_irqsave(&dahdi_timer_lock, flags);
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if (timer->tripped || timer->ping)
|
||||
ret |= POLLPRI;
|
||||
spin_unlock_irqrestore(&dahdi_timer_lock, flags);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
} else {
|
||||
/*
|
||||
* This should never happen. Surprise device removal
|
||||
@@ -9691,6 +9887,29 @@ static void _process_masterspan(void)
|
||||
spin_unlock(&pseudo->chan.lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DAHDI_CONFLINK
|
||||
if (maxlinks) {
|
||||
int z;
|
||||
int y;
|
||||
#ifdef CONFIG_DAHDI_MMX
|
||||
dahdi_kernel_fpu_begin();
|
||||
#endif
|
||||
/* process all the conf links */
|
||||
for (x = 1; x <= maxlinks; x++) {
|
||||
/* if we have a destination conf */
|
||||
z = confalias[conf_links[x].dst];
|
||||
if (z) {
|
||||
y = confalias[conf_links[x].src];
|
||||
if (y)
|
||||
ACSS(conf_sums[z], conf_sums[y]);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_DAHDI_MMX
|
||||
dahdi_kernel_fpu_end();
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_DAHDI_CONFLINK */
|
||||
|
||||
/* do all the pseudo/conferenced channel transmits (putbuf's) */
|
||||
list_for_each_entry(pseudo, &pseudo_chans, node) {
|
||||
pseudo_rx_audio(&pseudo->chan);
|
||||
@@ -9996,6 +10215,20 @@ static const struct file_operations dahdi_fops = {
|
||||
.poll = dahdi_poll,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/*
|
||||
* DAHDI stability should not depend on the calling process behaviour.
|
||||
* In case of suprise device removal, we should be able to return
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <dahdi/kernel.h>
|
||||
#include "dahdi.h"
|
||||
#include "dahdi-sysfs.h"
|
||||
@@ -38,22 +39,222 @@
|
||||
|
||||
static struct class *dahdi_class;
|
||||
|
||||
static dev_t dahdi_channels_devt; /*!< Device number of first channel */
|
||||
static struct cdev dahdi_channels_cdev; /*!< Channels chardev's */
|
||||
|
||||
/*
|
||||
* Flags to remember what initializations already
|
||||
* succeeded.
|
||||
*/
|
||||
static struct {
|
||||
u32 channel_driver:1;
|
||||
u32 channels_bus:1;
|
||||
u32 cdev:1;
|
||||
} should_cleanup;
|
||||
|
||||
#define chan_attr(field, format_string) \
|
||||
static BUS_ATTR_READER(field##_show, dev, buf) \
|
||||
{ \
|
||||
struct dahdi_chan *chan; \
|
||||
\
|
||||
chan = dev_to_chan(dev); \
|
||||
return sprintf(buf, format_string, chan->field); \
|
||||
}
|
||||
|
||||
chan_attr(name, "%s\n");
|
||||
chan_attr(channo, "%d\n");
|
||||
chan_attr(chanpos, "%d\n");
|
||||
chan_attr(blocksize, "%d\n");
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
chan_attr(chanmute, "%d\n");
|
||||
#endif
|
||||
|
||||
static BUS_ATTR_READER(sigcap_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len = 0;
|
||||
int i;
|
||||
uint sigtypes[] = {
|
||||
DAHDI_SIG_FXSLS,
|
||||
DAHDI_SIG_FXSGS,
|
||||
DAHDI_SIG_FXSKS,
|
||||
DAHDI_SIG_FXOLS,
|
||||
DAHDI_SIG_FXOGS,
|
||||
DAHDI_SIG_FXOKS,
|
||||
DAHDI_SIG_EM,
|
||||
DAHDI_SIG_CLEAR,
|
||||
DAHDI_SIG_HDLCRAW,
|
||||
DAHDI_SIG_HDLCFCS,
|
||||
DAHDI_SIG_HDLCNET,
|
||||
DAHDI_SIG_SLAVE,
|
||||
DAHDI_SIG_SF,
|
||||
DAHDI_SIG_CAS,
|
||||
DAHDI_SIG_EM_E1,
|
||||
DAHDI_SIG_DACS_RBS,
|
||||
DAHDI_SIG_HARDHDLC,
|
||||
DAHDI_SIG_MTP2,
|
||||
};
|
||||
chan = dev_to_chan(dev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sigtypes); i++) {
|
||||
uint x = chan->sigcap & sigtypes[i];
|
||||
if (x == sigtypes[i])
|
||||
len += sprintf(buf + len, "%s ", sigstr(x));
|
||||
}
|
||||
while (len > 0 && isspace(buf[len - 1])) /* trim */
|
||||
len--;
|
||||
len += sprintf(buf + len, "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(sig_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
return sprintf(buf, "%s\n", sigstr(chan->sig));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(in_use_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
return sprintf(buf, "%d\n", test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(alarms_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
len = fill_alarm_string(buf, PAGE_SIZE, chan->chan_alarms);
|
||||
buf[len++] = '\n';
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(ec_factory_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len = 0;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
if (chan->ec_factory)
|
||||
len += sprintf(buf, "%s", chan->ec_factory->get_name(chan));
|
||||
buf[len++] = '\n';
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(ec_state_show, dev, buf)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
int len = 0;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
if (chan->ec_factory)
|
||||
len += sprintf(buf, "%sACTIVE", (chan->ec_state) ? "" : "IN");
|
||||
buf[len++] = '\n';
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct device_attribute chan_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(channo),
|
||||
__ATTR_RO(chanpos),
|
||||
__ATTR_RO(sig),
|
||||
__ATTR_RO(sigcap),
|
||||
__ATTR_RO(alarms),
|
||||
__ATTR_RO(ec_factory),
|
||||
__ATTR_RO(ec_state),
|
||||
__ATTR_RO(blocksize),
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
__ATTR_RO(chanmute),
|
||||
#endif
|
||||
__ATTR_RO(in_use),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static void chan_release(struct device *dev)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
BUG_ON(!dev);
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
}
|
||||
|
||||
static int chan_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct bus_type chan_bus_type = {
|
||||
.name = "dahdi_channels",
|
||||
.match = chan_match,
|
||||
.dev_attrs = chan_dev_attrs,
|
||||
};
|
||||
|
||||
static int chan_probe(struct device *dev)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chan_remove(struct device *dev)
|
||||
{
|
||||
struct dahdi_chan *chan;
|
||||
|
||||
chan = dev_to_chan(dev);
|
||||
chan_dbg(DEVICES, chan, "SYSFS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver chan_driver = {
|
||||
.name = "dahdi",
|
||||
.bus = &chan_bus_type,
|
||||
#ifndef OLD_HOTPLUG_SUPPORT
|
||||
.owner = THIS_MODULE,
|
||||
#endif
|
||||
.probe = chan_probe,
|
||||
.remove = chan_remove
|
||||
};
|
||||
|
||||
int chan_sysfs_create(struct dahdi_chan *chan)
|
||||
{
|
||||
char chan_name[32];
|
||||
void *dummy;
|
||||
int res = 0;
|
||||
struct device *dev;
|
||||
struct dahdi_span *span;
|
||||
int res;
|
||||
dev_t devt;
|
||||
|
||||
if (chan->channo >= 250)
|
||||
return 0;
|
||||
chan_dbg(DEVICES, chan, "Creating channel %d\n", chan->channo);
|
||||
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
return 0;
|
||||
snprintf(chan_name, sizeof(chan_name), "dahdi!%d", chan->channo);
|
||||
dummy = (void *)MAKE_DAHDI_DEV(chan->channo, chan_name);
|
||||
if (IS_ERR(dummy)) {
|
||||
res = PTR_ERR(dummy);
|
||||
chan_err(chan, "Failed creating sysfs device: %d\n",
|
||||
res);
|
||||
span = chan->span;
|
||||
devt = MKDEV(MAJOR(dahdi_channels_devt), chan->channo);
|
||||
dev = &chan->chan_device;
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->devt = devt;
|
||||
dev->bus = &chan_bus_type;
|
||||
dev->parent = span->span_device;
|
||||
/*
|
||||
* FIXME: the name cannot be longer than KOBJ_NAME_LEN
|
||||
*/
|
||||
dev_set_name(dev, "dahdi!chan!%03d!%03d", span->spanno, chan->chanpos);
|
||||
dev_set_drvdata(dev, chan);
|
||||
dev->release = chan_release;
|
||||
res = device_register(dev);
|
||||
if (res) {
|
||||
chan_err(chan, "%s: device_register failed: %d\n",
|
||||
__func__, res);
|
||||
put_device(dev);
|
||||
return res;
|
||||
}
|
||||
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
@@ -62,9 +263,18 @@ int chan_sysfs_create(struct dahdi_chan *chan)
|
||||
|
||||
void chan_sysfs_remove(struct dahdi_chan *chan)
|
||||
{
|
||||
struct device *dev = &chan->chan_device;
|
||||
|
||||
chan_dbg(DEVICES, chan, "Destroying channel %d\n", chan->channo);
|
||||
if (!dev_get_drvdata(dev))
|
||||
return;
|
||||
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
return;
|
||||
DEL_DAHDI_DEV(chan->channo);
|
||||
dev = &chan->chan_device;
|
||||
BUG_ON(dev_get_drvdata(dev) != chan);
|
||||
device_unregister(dev);
|
||||
/* FIXME: should have been done earlier in dahdi_chan_unreg */
|
||||
chan->channo = -1;
|
||||
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
}
|
||||
|
||||
@@ -77,7 +287,7 @@ int dahdi_register_chardev(struct dahdi_chardev *dev)
|
||||
char *udevname;
|
||||
|
||||
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
|
||||
GFP_KERNEL);
|
||||
GFP_KERNEL);
|
||||
if (!udevname)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -181,28 +391,86 @@ cleanup:
|
||||
*/
|
||||
static void sysfs_channels_cleanup(void)
|
||||
{
|
||||
if (should_cleanup.cdev) {
|
||||
dahdi_dbg(DEVICES, "removing channels cdev\n");
|
||||
cdev_del(&dahdi_channels_cdev);
|
||||
should_cleanup.cdev = 0;
|
||||
}
|
||||
if (dahdi_channels_devt) {
|
||||
dahdi_dbg(DEVICES, "unregistering chrdev_region\n");
|
||||
unregister_chrdev_region(dahdi_channels_devt,
|
||||
DAHDI_MAX_CHANNELS);
|
||||
}
|
||||
|
||||
fixed_devfiles_remove();
|
||||
if (dahdi_class) {
|
||||
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
|
||||
class_destroy(dahdi_class);
|
||||
dahdi_class = NULL;
|
||||
}
|
||||
if (should_cleanup.channel_driver) {
|
||||
dahdi_dbg(DEVICES, "Removing channel driver\n");
|
||||
driver_unregister(&chan_driver);
|
||||
should_cleanup.channel_driver = 0;
|
||||
}
|
||||
if (should_cleanup.channels_bus) {
|
||||
dahdi_dbg(DEVICES, "Removing channels bus\n");
|
||||
bus_unregister(&chan_bus_type);
|
||||
should_cleanup.channels_bus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int __init dahdi_sysfs_chan_init(const struct file_operations *fops)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
dahdi_dbg(DEVICES, "Registering channels bus\n");
|
||||
res = bus_register(&chan_bus_type);
|
||||
if (res) {
|
||||
dahdi_err("%s: bus_register(%s) failed. Error number %d\n",
|
||||
__func__, chan_bus_type.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.channels_bus = 1;
|
||||
|
||||
dahdi_dbg(DEVICES, "Registering channel driver\n");
|
||||
res = driver_register(&chan_driver);
|
||||
if (res) {
|
||||
dahdi_err("%s: driver_register(%s) failed. Error number %d",
|
||||
__func__, chan_driver.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.channel_driver = 1;
|
||||
|
||||
dahdi_class = class_create(THIS_MODULE, "dahdi");
|
||||
if (IS_ERR(dahdi_class)) {
|
||||
res = PTR_ERR(dahdi_class);
|
||||
dahdi_err("%s: class_create(dahi_chan) failed. Error: %d\n",
|
||||
__func__, res);
|
||||
__func__, res);
|
||||
goto cleanup;
|
||||
}
|
||||
res = fixed_devfiles_create();
|
||||
if (res)
|
||||
goto cleanup;
|
||||
dahdi_dbg(DEVICES, "allocating chrdev_region\n");
|
||||
res = alloc_chrdev_region(&dahdi_channels_devt,
|
||||
0,
|
||||
DAHDI_MAX_CHANNELS,
|
||||
"dahdi_channels");
|
||||
if (res) {
|
||||
dahdi_err("%s: Failed allocating chrdev for %d channels (%d)",
|
||||
__func__, DAHDI_MAX_CHANNELS, res);
|
||||
goto cleanup;
|
||||
}
|
||||
dahdi_dbg(DEVICES, "adding channels cdev\n");
|
||||
cdev_init(&dahdi_channels_cdev, fops);
|
||||
res = cdev_add(&dahdi_channels_cdev, dahdi_channels_devt,
|
||||
DAHDI_MAX_CHANNELS);
|
||||
if (res) {
|
||||
dahdi_err("%s: cdev_add() failed (%d)", __func__, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.cdev = 1;
|
||||
return 0;
|
||||
cleanup:
|
||||
sysfs_channels_cleanup();
|
||||
|
||||
@@ -88,6 +88,8 @@ static int txerrors;
|
||||
static struct tasklet_struct dahdi_dynamic_tlet;
|
||||
|
||||
static void dahdi_dynamic_tasklet(unsigned long data);
|
||||
#else
|
||||
static struct tasklet_struct dahdi_dynamic_flush_tlet;
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(dspan_mutex);
|
||||
@@ -208,12 +210,25 @@ static void __dahdi_dynamic_run(void)
|
||||
dahdi_dynamic_sendmessage(d);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TASKLETS
|
||||
/* If tasklets are not enabled, the above section will be called in
|
||||
* interrupt context and the flushing of each driver will be called in a
|
||||
* separate tasklet that only handles that. This is necessary since some
|
||||
* of the dynamic spans need to call functions that require interrupts
|
||||
* to be enabled but dahdi_transmit / ...sendmessage needs to be called
|
||||
* each time the masterspan is processed which happens with interrupts
|
||||
* disabled.
|
||||
*
|
||||
*/
|
||||
tasklet_hi_schedule(&dahdi_dynamic_flush_tlet);
|
||||
#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();
|
||||
}
|
||||
|
||||
@@ -708,6 +723,20 @@ static void dahdi_dynamic_tasklet(unsigned long data)
|
||||
}
|
||||
taskletpending = 0;
|
||||
}
|
||||
#else
|
||||
static void dahdi_dynamic_flush_tasklet(unsigned long data)
|
||||
{
|
||||
struct dahdi_dynamic_driver *drv;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(drv, &driver_list, list) {
|
||||
/* Flush any traffic still pending in the driver */
|
||||
if (drv->flush) {
|
||||
drv->flush();
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data)
|
||||
@@ -840,6 +869,8 @@ static int dahdi_dynamic_init(void)
|
||||
mod_timer(&alarmcheck, jiffies + 1 * HZ);
|
||||
#ifdef ENABLE_TASKLETS
|
||||
tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
|
||||
#else
|
||||
tasklet_init(&dahdi_dynamic_flush_tlet, dahdi_dynamic_flush_tasklet, 0);
|
||||
#endif
|
||||
dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
|
||||
|
||||
@@ -856,6 +887,9 @@ static void dahdi_dynamic_cleanup(void)
|
||||
tasklet_disable(&dahdi_dynamic_tlet);
|
||||
tasklet_kill(&dahdi_dynamic_tlet);
|
||||
}
|
||||
#else
|
||||
tasklet_disable(&dahdi_dynamic_flush_tlet);
|
||||
tasklet_kill(&dahdi_dynamic_flush_tlet);
|
||||
#endif
|
||||
del_timer_sync(&alarmcheck);
|
||||
/* Must call again in case it was running before and rescheduled
|
||||
|
||||
@@ -185,44 +185,16 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* dahdi_dynamic_flush_work_fn - Flush all pending transactions.
|
||||
*
|
||||
* This function is run in a work queue since we can't guarantee interrupts
|
||||
* will be enabled when we're called, and dev_queue_xmit() requires that
|
||||
* interrupts be enabled.
|
||||
*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void dahdi_dynamic_flush_work_fn(void *data)
|
||||
#else
|
||||
static void dahdi_dynamic_flush_work_fn(struct work_struct *work)
|
||||
#endif
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
/* Handle all transmissions now */
|
||||
while ((skb = skb_dequeue(&skbs))) {
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
|
||||
dahdi_dynamic_flush_work_fn, NULL);
|
||||
#else
|
||||
static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
|
||||
dahdi_dynamic_flush_work_fn);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ztdeth_flush - Flush all pending transactions.
|
||||
*
|
||||
* This function is called in interrupt context while processing the master
|
||||
* span.
|
||||
* This function is always called in softirq context.
|
||||
*/
|
||||
static int ztdeth_flush(void)
|
||||
{
|
||||
schedule_work(&dahdi_dynamic_eth_flush_work);
|
||||
struct sk_buff *skb;
|
||||
while ((skb = skb_dequeue(&skbs)))
|
||||
dev_queue_xmit(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -446,11 +418,6 @@ static int __init ztdeth_init(void)
|
||||
|
||||
static void __exit ztdeth_exit(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
flush_scheduled_work();
|
||||
#else
|
||||
cancel_work_sync(&dahdi_dynamic_eth_flush_work);
|
||||
#endif
|
||||
dahdi_dynamic_unregister_driver(&ztd_eth);
|
||||
unregister_netdevice_notifier(&ztdeth_nblock);
|
||||
dev_remove_pack(&ztdeth_ptype);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
/**
|
||||
* Undefine USE_PROC_FS, if you do not want the /proc/dahdi/dynamic-ethmf
|
||||
@@ -696,71 +697,69 @@ static void timer_callback(unsigned long param)
|
||||
#ifdef USE_PROC_FS
|
||||
static struct proc_dir_entry *proc_entry;
|
||||
static const char *ztdethmf_procname = "dahdi/dynamic-ethmf";
|
||||
static int ztdethmf_proc_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
|
||||
static int ztdethmf_proc_show(struct seq_file *sfile, void *not_used)
|
||||
{
|
||||
struct ztdeth *z = NULL;
|
||||
int len = 0, i = 0;
|
||||
int i = 0;
|
||||
unsigned int group = 0, c = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
len += sprintf(page + len, "Errors: %d\n\n", atomic_read(&errcount));
|
||||
seq_printf(sfile, "Errors: %d\n\n", atomic_read(&errcount));
|
||||
|
||||
for (group = 0; group < ETHMF_MAX_GROUPS; ++group) {
|
||||
if (atomic_read(&(ethmf_groups[group].spans))) {
|
||||
len += sprintf(page + len, "Group #%d (0x%x)\n", i++, ethmf_groups[group].hash_addr);
|
||||
len += sprintf(page + len, " Spans: %d\n",
|
||||
atomic_read(&(ethmf_groups[group].spans)));
|
||||
seq_printf(sfile, "Group #%d (0x%x)\n", i++,
|
||||
ethmf_groups[group].hash_addr);
|
||||
seq_printf(sfile, "Spans: %d\n",
|
||||
atomic_read(&(ethmf_groups[group].spans)));
|
||||
|
||||
c = 1;
|
||||
list_for_each_entry_rcu(z, ðmf_list, list) {
|
||||
if (z->addr_hash == ethmf_groups[group].hash_addr) {
|
||||
if (c == 1) {
|
||||
len += sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
" Device: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x)\n",
|
||||
z->ethdev,
|
||||
z->addr[0], z->addr[1], z->addr[2],
|
||||
z->addr[3], z->addr[4], z->addr[5]);
|
||||
}
|
||||
len += sprintf(page + len, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
|
||||
seq_printf(sfile, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
|
||||
c++, ntohs(z->subaddr),
|
||||
atomic_read(&z->ready), atomic_read(&z->delay),
|
||||
z->real_channels, atomic_read(&z->no_front_padding));
|
||||
}
|
||||
}
|
||||
len += sprintf(page + len, " Device UPs: %u\n",
|
||||
seq_printf(sfile, " Device UPs: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].devupcount)));
|
||||
len += sprintf(page + len, " Device DOWNs: %u\n",
|
||||
seq_printf(sfile, " Device DOWNs: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].devdowncount)));
|
||||
len += sprintf(page + len, " Rx Frames: %u\n",
|
||||
seq_printf(sfile, " Rx Frames: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].rxframecount)));
|
||||
len += sprintf(page + len, " Tx Frames: %u\n",
|
||||
seq_printf(sfile, " Tx Frames: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].txframecount)));
|
||||
len += sprintf(page + len, " Rx Bytes: %u\n",
|
||||
seq_printf(sfile, " Rx Bytes: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].rxbytecount)));
|
||||
len += sprintf(page + len, " Tx Bytes: %u\n",
|
||||
seq_printf(sfile, " Tx Bytes: %u\n",
|
||||
atomic_read(&(ethmf_groups[group].txbytecount)));
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
}
|
||||
if (len > off+count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (len <= off) {
|
||||
off -= len;
|
||||
len = 0;
|
||||
}
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ztdethmf_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, ztdethmf_proc_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations ztdethmf_proc_fops = {
|
||||
.open = ztdethmf_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init ztdethmf_init(void)
|
||||
@@ -778,8 +777,8 @@ static int __init ztdethmf_init(void)
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
#ifdef USE_PROC_FS
|
||||
proc_entry = create_proc_read_entry(ztdethmf_procname, 0444, NULL,
|
||||
ztdethmf_proc_read, NULL);
|
||||
proc_entry = proc_create_data(ztdethmf_procname, 0444, NULL,
|
||||
&ztdethmf_proc_fops, NULL);
|
||||
if (!proc_entry) {
|
||||
printk(KERN_ALERT "create_proc_read_entry failed.\n");
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
.PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object firmware-loaders
|
||||
|
||||
OCT6114_032_VERSION:=1.05.01
|
||||
OCT6114_064_VERSION:=1.05.01
|
||||
OCT6114_128_VERSION:=1.05.01
|
||||
OCT6114_256_VERSION:=1.05.01
|
||||
@@ -30,10 +31,12 @@ VPMADT032_VERSION:=1.25.0
|
||||
HX8_VERSION:=2.06
|
||||
VPMOCT032_VERSION:=1.12.0
|
||||
WCT820_VERSION:=1.76
|
||||
TE133_VERSION:=6f0017
|
||||
TE134_VERSION:=6f0017
|
||||
|
||||
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
|
||||
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820
|
||||
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
|
||||
@@ -42,17 +45,21 @@ ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRM
|
||||
# This means this is version MR5.6 of the tc400m firmware
|
||||
|
||||
# Build a list of firmware package filenames we need
|
||||
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
|
||||
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-HX8=dahdi-fw-hx8-$(HX8_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz)
|
||||
|
||||
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
|
||||
|
||||
# Build a list of object files if hotplug will not be used
|
||||
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032.o)
|
||||
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256.o)
|
||||
@@ -107,6 +114,17 @@ $(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)
|
||||
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
|
||||
@@ -185,6 +203,29 @@ 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:
|
||||
if [ -d $(DESTDIR)/usr/lib/hotplug/firmware ]; then \
|
||||
@@ -202,6 +243,11 @@ make_firmware_object: make_firmware_object.in ../dahdi-base.o
|
||||
sed -e s/BFDNAME/$${BFDNAME}/ -e s/BFDARCH/$${BFDARCH}/ $< > $@
|
||||
@chmod +x $@
|
||||
|
||||
# Build object file of an oct6114 032 firmware image for linking
|
||||
dahdi-fw-oct6114-032.o: dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz dahdi-fw-oct6114-032.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-032.bin
|
||||
./make_firmware_object dahdi-fw-oct6114-032.bin $@
|
||||
|
||||
# Build object file of an oct6114 064 firmware image for linking
|
||||
dahdi-fw-oct6114-064.o: dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz dahdi-fw-oct6114-064.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-064.bin
|
||||
|
||||
@@ -1,38 +1,30 @@
|
||||
CFLAGS=-V3.4 -ffunction-sections -I/lib/modules/$(shell uname -r)/build/include -Iinclude -Ioctdeviceapi -Ioctdeviceapi/oct6100api -DGFP_ATOMIC=0 -Dkmalloc=calloc -Dkfree=free
|
||||
LDFLAGS=-V3.4 -Wl,-Map -Wl,test.map -Wl,--gc-sections
|
||||
#
|
||||
# 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
|
||||
|
||||
APIDIR=octdeviceapi/oct6100api/oct6100_api
|
||||
|
||||
OCTASIC_OBJS=$(APIDIR)/oct6100_adpcm_chan.o \
|
||||
$(APIDIR)/oct6100_channel.o \
|
||||
$(APIDIR)/oct6100_chip_open.o \
|
||||
$(APIDIR)/oct6100_chip_stats.o \
|
||||
$(APIDIR)/oct6100_conf_bridge.o \
|
||||
$(APIDIR)/oct6100_debug.o \
|
||||
$(APIDIR)/oct6100_events.o \
|
||||
$(APIDIR)/oct6100_interrupts.o \
|
||||
$(APIDIR)/oct6100_memory.o \
|
||||
$(APIDIR)/oct6100_miscellaneous.o \
|
||||
$(APIDIR)/oct6100_mixer.o \
|
||||
$(APIDIR)/oct6100_phasing_tsst.o \
|
||||
$(APIDIR)/oct6100_playout_buf.o \
|
||||
$(APIDIR)/oct6100_remote_debug.o \
|
||||
$(APIDIR)/oct6100_tlv.o \
|
||||
$(APIDIR)/oct6100_tone_detection.o \
|
||||
$(APIDIR)/oct6100_tsi_cnct.o \
|
||||
$(APIDIR)/oct6100_tsst.o \
|
||||
$(APIDIR)/oct6100_user.o \
|
||||
apilib/bt/octapi_bt0.o \
|
||||
apilib/largmath/octapi_largmath.o \
|
||||
apilib/llman/octapi_llman.o
|
||||
|
||||
|
||||
all: test
|
||||
|
||||
test.o: test.c
|
||||
|
||||
test: test.o $(OCTASIC_OBJS)
|
||||
|
||||
clean:
|
||||
rm -rf test test.o
|
||||
rm -rf $(OCTASIC_OBJS)
|
||||
# TODO: ccflags was added in 2.6.24 in commit f77bf01425b11947eeb3b5b54. This
|
||||
# should be changed to a conditional compilation based on the Kernel Version.
|
||||
# ccflags-y := -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
|
||||
EXTRA_CFLAGS = -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
|
||||
lib-y := $(octapi_files)
|
||||
|
||||
@@ -1242,7 +1242,8 @@ static char *hfc_decode_st_state(struct b4xxp *b4, int port, unsigned char state
|
||||
"?", "?", "?", "?", "?", "?", "?", "?" }
|
||||
};
|
||||
|
||||
if (!(str = kmalloc(256, GFP_KERNEL))) {
|
||||
str = kmalloc(256, GFP_ATOMIC);
|
||||
if (!str) {
|
||||
dev_warn(&b4->pdev->dev, "could not allocate mem for ST state decode string!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
|
||||
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
|
||||
endif
|
||||
|
||||
wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x)
|
||||
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
|
||||
|
||||
@@ -390,7 +390,7 @@ static inline bool is_pcie(const struct t4 *wc)
|
||||
|
||||
static inline bool has_e1_span(const struct t4 *wc)
|
||||
{
|
||||
return (wc->t1e1) != 0;
|
||||
return (wc->t1e1 > 0);
|
||||
}
|
||||
|
||||
static inline bool is_octal(const struct t4 *wc)
|
||||
@@ -1121,6 +1121,7 @@ static int t4_echocan_create(struct dahdi_chan *chan,
|
||||
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;
|
||||
@@ -1141,19 +1142,19 @@ static int t4_echocan_create(struct dahdi_chan *chan,
|
||||
|
||||
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
|
||||
|
||||
if (wc->vpm) {
|
||||
if (is_octal(wc))
|
||||
channel = channel << 3;
|
||||
else
|
||||
channel = channel << 2;
|
||||
channel |= chan->span->offset;
|
||||
if (debug & DEBUG_ECHOCAN)
|
||||
dev_notice(&wc->dev->dev, "echocan: Card is %d, "
|
||||
"Channel is %d, Span is %d, offset is %d "
|
||||
"length %d\n", wc->num, chan->chanpos,
|
||||
chan->span->offset, channel, ecp->tap_length);
|
||||
vpm450m_setec(wc->vpm, channel, ecp->tap_length);
|
||||
if (is_octal(wc))
|
||||
channel = channel << 3;
|
||||
else
|
||||
channel = channel << 2;
|
||||
channel |= chan->span->offset;
|
||||
if (debug & DEBUG_ECHOCAN) {
|
||||
dev_notice(&wc->dev->dev,
|
||||
"echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n",
|
||||
wc->num, chan->chanpos, chan->span->offset,
|
||||
channel, ecp->tap_length);
|
||||
}
|
||||
vpm450m_set_alaw_companding(wc->vpm, channel, alaw);
|
||||
vpm450m_setec(wc->vpm, channel, ecp->tap_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1162,23 +1163,23 @@ static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec
|
||||
struct t4 *wc = chan->pvt;
|
||||
int channel;
|
||||
|
||||
memset(ec, 0, sizeof(*ec));
|
||||
if (!wc->vpm)
|
||||
return;
|
||||
|
||||
memset(ec, 0, sizeof(*ec));
|
||||
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
|
||||
|
||||
if (wc->vpm) {
|
||||
if (is_octal(wc))
|
||||
channel = channel << 3;
|
||||
else
|
||||
channel = channel << 2;
|
||||
channel |= chan->span->offset;
|
||||
if (debug & DEBUG_ECHOCAN)
|
||||
dev_notice(&wc->dev->dev, "echocan: Card is %d, "
|
||||
"Channel is %d, Span is %d, offset is %d "
|
||||
"length 0\n", wc->num, chan->chanpos,
|
||||
chan->span->offset, channel);
|
||||
vpm450m_setec(wc->vpm, channel, 0);
|
||||
if (is_octal(wc))
|
||||
channel = channel << 3;
|
||||
else
|
||||
channel = channel << 2;
|
||||
channel |= chan->span->offset;
|
||||
if (debug & DEBUG_ECHOCAN) {
|
||||
dev_notice(&wc->dev->dev,
|
||||
"echocan: Card is %d, Channel is %d, Span is %d, offset is %d length 0\n",
|
||||
wc->num, chan->chanpos, chan->span->offset, channel);
|
||||
}
|
||||
vpm450m_setec(wc->vpm, channel, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2059,7 +2060,7 @@ static void t4_span_assigned(struct dahdi_span *span)
|
||||
/* We use this to make sure all the spans are assigned before
|
||||
* running the serial setup. */
|
||||
list_for_each_entry(pos, &wc->ddev->spans, device_node) {
|
||||
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
|
||||
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &pos->flags))
|
||||
++unassigned_spans;
|
||||
}
|
||||
|
||||
@@ -2225,6 +2226,7 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
int res = 0;
|
||||
enum linemode mode;
|
||||
const char *old_name;
|
||||
static DEFINE_MUTEX(linemode_lock);
|
||||
|
||||
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name,
|
||||
dahdi_spantype2str(linemode));
|
||||
@@ -2232,22 +2234,27 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
if (span->spantype == linemode)
|
||||
return 0;
|
||||
|
||||
/* Do not allow the t1e1 member to be changed by multiple threads. */
|
||||
mutex_lock(&linemode_lock);
|
||||
old_name = dahdi_spantype2str(span->spantype);
|
||||
switch (linemode) {
|
||||
case SPANTYPE_DIGITAL_T1:
|
||||
dev_info(&wc->dev->dev,
|
||||
"Changing from %s to T1 line mode.\n", old_name);
|
||||
mode = T1;
|
||||
wc->t1e1 &= ~(1 << span->offset);
|
||||
break;
|
||||
case SPANTYPE_DIGITAL_E1:
|
||||
dev_info(&wc->dev->dev,
|
||||
"Changing from %s to E1 line mode.\n", old_name);
|
||||
mode = E1;
|
||||
wc->t1e1 |= (1 << span->offset);
|
||||
break;
|
||||
case SPANTYPE_DIGITAL_J1:
|
||||
dev_info(&wc->dev->dev,
|
||||
"Changing from %s to J1 line mode.\n", old_name);
|
||||
mode = J1;
|
||||
wc->t1e1 &= ~(1 << span->offset);
|
||||
break;
|
||||
default:
|
||||
dev_err(&wc->dev->dev,
|
||||
@@ -2261,6 +2268,7 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
dahdi_init_span(span);
|
||||
}
|
||||
|
||||
mutex_unlock(&linemode_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3682,7 +3690,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
}
|
||||
if (!ts->span.alarms) {
|
||||
if ((isr3 & 0x3) || (isr4 & 0xc0))
|
||||
ts->span.timingslips++;
|
||||
ts->span.count.timingslips++;
|
||||
|
||||
if (debug & DEBUG_MAIN) {
|
||||
if (isr3 & 0x02)
|
||||
@@ -3703,7 +3711,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
|
||||
wc->numspans, span + 1);
|
||||
}
|
||||
} else
|
||||
ts->span.timingslips = 0;
|
||||
ts->span.count.timingslips = 0;
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
/* HDLC controller checks - receive side */
|
||||
|
||||
@@ -19,12 +19,17 @@
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "vpm450m.h"
|
||||
#include "oct6100api/oct6100_api.h"
|
||||
|
||||
@@ -177,6 +182,7 @@ struct vpm450m {
|
||||
#define FLAG_DTMF (1 << 0)
|
||||
#define FLAG_MUTE (1 << 1)
|
||||
#define FLAG_ECHO (1 << 2)
|
||||
#define FLAG_ALAW (1 << 3)
|
||||
|
||||
static unsigned int tones[] = {
|
||||
SOUT_DTMF_1,
|
||||
@@ -216,6 +222,50 @@ static unsigned int tones[] = {
|
||||
ROUT_G168_1100GB_ON,
|
||||
};
|
||||
|
||||
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
|
||||
bool alaw)
|
||||
{
|
||||
tOCT6100_CHANNEL_MODIFY *modify;
|
||||
UINT32 ulResult;
|
||||
UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW :
|
||||
cOCT6100_PCM_U_LAW;
|
||||
|
||||
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
|
||||
pr_err("Channel out of bounds in %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
/* If we're already in this companding mode, no need to do anything. */
|
||||
if (alaw == ((vpm450m->chanflags[channel] & FLAG_ALAW) > 0))
|
||||
return;
|
||||
|
||||
modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
|
||||
if (!modify) {
|
||||
pr_notice("Unable to allocate memory for setec!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Oct6100ChannelModifyDef(modify);
|
||||
modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel];
|
||||
modify->fTdmConfigModified = TRUE;
|
||||
modify->TdmConfig.ulSinPcmLaw = law_to_use;
|
||||
modify->TdmConfig.ulRinPcmLaw = law_to_use;
|
||||
modify->TdmConfig.ulSoutPcmLaw = law_to_use;
|
||||
modify->TdmConfig.ulRoutPcmLaw = law_to_use;
|
||||
ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify);
|
||||
if (ulResult != GENERIC_OK) {
|
||||
pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n",
|
||||
vpm450m->aulEchoChanHndl[channel], channel, ulResult);
|
||||
} else {
|
||||
pr_info("Changed companding on channel %d to %s.\n", channel,
|
||||
(alaw) ? "alaw" : "ulaw");
|
||||
if (alaw)
|
||||
vpm450m->chanflags[channel] |= FLAG_ALAW;
|
||||
else
|
||||
vpm450m->chanflags[channel] &= ~(FLAG_ALAW);
|
||||
}
|
||||
kfree(modify);
|
||||
}
|
||||
|
||||
static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode)
|
||||
{
|
||||
tOCT6100_CHANNEL_MODIFY *modify;
|
||||
@@ -248,6 +298,11 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
|
||||
tOCT6100_CHANNEL_MODIFY *modify;
|
||||
UINT32 ulResult;
|
||||
|
||||
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
|
||||
pr_err("Channel out of bounds in %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL);
|
||||
if (!modify) {
|
||||
printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setdtmf!\n");
|
||||
@@ -286,6 +341,11 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
|
||||
|
||||
void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen)
|
||||
{
|
||||
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
|
||||
pr_err("Channel out of bounds in %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eclen) {
|
||||
vpm450m->chanflags[channel] |= FLAG_ECHO;
|
||||
vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
|
||||
@@ -524,10 +584,13 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
* therefore, the lower 2 bits tell us which span this
|
||||
* timeslot/channel
|
||||
*/
|
||||
if (isalaw[x & mask])
|
||||
if (isalaw[x & mask]) {
|
||||
law = cOCT6100_PCM_A_LAW;
|
||||
else
|
||||
vpm450m->chanflags[x] |= FLAG_ALAW;
|
||||
} else {
|
||||
law = cOCT6100_PCM_U_LAW;
|
||||
vpm450m->chanflags[x] &= ~(FLAG_ALAW);
|
||||
}
|
||||
Oct6100ChannelOpenDef(ChannelOpen);
|
||||
ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x];
|
||||
ChannelOpen->ulUserChanId = x;
|
||||
|
||||
@@ -39,5 +39,7 @@ void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int
|
||||
int vpm450m_checkirq(struct vpm450m *vpm450m);
|
||||
int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start);
|
||||
void release_vpm450m(struct vpm450m *instance);
|
||||
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
|
||||
int channel, bool alaw);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -866,6 +866,7 @@ wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev,
|
||||
memset(dr->desc, 0, (sizeof(*d) + dr->padding) * DRING_SIZE);
|
||||
for (i = 0; i < DRING_SIZE; ++i) {
|
||||
d = wctc4xxp_descriptor(dr, i);
|
||||
memset(d, 0, sizeof(*d));
|
||||
d->des1 = cpu_to_le32(des1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1961,19 +1961,26 @@ wctdm_check_battery_lost(struct wctdm *wc, struct wctdm_module *const mod)
|
||||
battery present or unknown, debounce timer (going to battery lost)
|
||||
*/
|
||||
switch (fxo->battery_state) {
|
||||
case BATTERY_DEBOUNCING_PRESENT_ALARM:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM;
|
||||
fxo->battdebounce_timer = wc->framecount + battdebounce;
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_PRESENT:
|
||||
/* we were going to BATTERY_PRESENT, but
|
||||
* battery was lost again. */
|
||||
fxo->battery_state = BATTERY_LOST;
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM;
|
||||
fxo->battdebounce_timer = wc->framecount +
|
||||
battalarm - battdebounce;
|
||||
break;
|
||||
case BATTERY_UNKNOWN:
|
||||
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
|
||||
case BATTERY_DEBOUNCING_PRESENT_ALARM: /* intentional drop through */
|
||||
case BATTERY_PRESENT:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_LOST;
|
||||
fxo->battdebounce_timer = wc->framecount + battdebounce;
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_LOST:
|
||||
case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM:
|
||||
case BATTERY_DEBOUNCING_LOST: /* Intentional drop through */
|
||||
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
|
||||
if (debug) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
@@ -2022,8 +2029,9 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
|
||||
struct fxo *const fxo = &mod->mod.fxo;
|
||||
|
||||
switch (fxo->battery_state) {
|
||||
case BATTERY_DEBOUNCING_PRESENT:
|
||||
if (time_after(jiffies, fxo->battdebounce_timer)) {
|
||||
case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM:
|
||||
case BATTERY_DEBOUNCING_PRESENT: /* intentional drop through */
|
||||
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
|
||||
if (debug) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
"BATTERY on %d/%d (%s)!\n",
|
||||
@@ -2048,12 +2056,12 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
|
||||
* of its time period has already passed while
|
||||
* debouncing occurred */
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM;
|
||||
fxo->battdebounce_timer = jiffies +
|
||||
msecs_to_jiffies(battalarm - battdebounce);
|
||||
fxo->battdebounce_timer = wc->framecount +
|
||||
battalarm - battdebounce;
|
||||
}
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_PRESENT_ALARM:
|
||||
if (time_after(jiffies, fxo->battdebounce_timer)) {
|
||||
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
|
||||
fxo->battery_state = BATTERY_PRESENT;
|
||||
dahdi_alarm_channel(get_dahdi_chan(wc, mod),
|
||||
DAHDI_ALARM_NONE);
|
||||
@@ -2061,18 +2069,23 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
|
||||
break;
|
||||
case BATTERY_PRESENT:
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_LOST_ALARM:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM;
|
||||
fxo->battdebounce_timer = wc->framecount + battdebounce;
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM;
|
||||
fxo->battdebounce_timer = wc->framecount +
|
||||
battalarm - battdebounce;
|
||||
break;
|
||||
case BATTERY_DEBOUNCING_LOST:
|
||||
/* we were going to BATTERY_LOST, but battery appeared again,
|
||||
* so clear the debounce timer */
|
||||
fxo->battery_state = BATTERY_PRESENT;
|
||||
break;
|
||||
case BATTERY_UNKNOWN:
|
||||
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
|
||||
case BATTERY_LOST: /* intentional drop through */
|
||||
case BATTERY_DEBOUNCING_LOST_ALARM:
|
||||
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT;
|
||||
fxo->battdebounce_timer = jiffies +
|
||||
msecs_to_jiffies(battdebounce);
|
||||
fxo->battdebounce_timer = wc->framecount + battdebounce;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,9 +106,11 @@ struct calregs {
|
||||
enum battery_state {
|
||||
BATTERY_UNKNOWN = 0,
|
||||
BATTERY_DEBOUNCING_PRESENT,
|
||||
BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM,
|
||||
BATTERY_DEBOUNCING_PRESENT_ALARM,
|
||||
BATTERY_PRESENT,
|
||||
BATTERY_DEBOUNCING_LOST,
|
||||
BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM,
|
||||
BATTERY_DEBOUNCING_LOST_ALARM,
|
||||
BATTERY_LOST,
|
||||
};
|
||||
|
||||
@@ -658,6 +658,17 @@ static int __t1_getresult(struct t1 *wc, struct command *cmd)
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (test_bit(IOERROR, &wc->bit_flags)) {
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
list_del_init(&cmd->node);
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
if (printk_ratelimit()) {
|
||||
dev_warn(&wc->vb.pdev->dev,
|
||||
"Timeout in %s\n", __func__);
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(&cmd->complete, HZ*10);
|
||||
if (unlikely(!ret)) {
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
@@ -666,13 +677,13 @@ static int __t1_getresult(struct t1 *wc, struct command *cmd)
|
||||
* can go ahead and free it right away. */
|
||||
list_del_init(&cmd->node);
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
free_cmd(wc, cmd);
|
||||
if (-ERESTARTSYS != ret) {
|
||||
if (printk_ratelimit()) {
|
||||
dev_warn(&wc->vb.pdev->dev,
|
||||
"Timeout in %s\n", __func__);
|
||||
}
|
||||
ret = -EIO;
|
||||
set_bit(IOERROR, &wc->bit_flags);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
@@ -683,7 +694,6 @@ static int __t1_getresult(struct t1 *wc, struct command *cmd)
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ*2);
|
||||
WARN_ON(!ret);
|
||||
ret = cmd->data;
|
||||
free_cmd(wc, cmd);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -841,6 +851,75 @@ static void free_wc(struct t1 *wc)
|
||||
kfree(wc);
|
||||
}
|
||||
|
||||
/**
|
||||
* t1_reset_registers - Put register back to their default values
|
||||
*
|
||||
* Since the card does not have an ability to reset just the framer
|
||||
* specifically, we need to write all the default values to the framer.
|
||||
*
|
||||
*/
|
||||
static void t1_reset_registers(struct t1 *wc)
|
||||
{
|
||||
int i;
|
||||
struct t1_reg {
|
||||
u8 address;
|
||||
u8 value;
|
||||
} __attribute__((packed));
|
||||
struct t1_reg *reg;
|
||||
static struct t1_reg DEFAULT_REGS[] = {
|
||||
{0x00, 0x7d}, {0x01, 0x7d}, {0x02, 0x00}, {0x03, 0x00},
|
||||
{0x04, 0xfd}, {0x05, 0xff}, {0x06, 0xff}, {0x07, 0xff},
|
||||
{0x08, 0x05}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
|
||||
{0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
|
||||
{0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
|
||||
{0x14, 0xff}, {0x15, 0xff}, {0x16, 0xff}, {0x17, 0xff},
|
||||
{0x18, 0xff}, {0x19, 0xff}, {0x1a, 0x00}, {0x1b, 0x00},
|
||||
{0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
|
||||
{0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x04},
|
||||
{0x24, 0x00}, {0x25, 0x05}, {0x26, 0x7b}, {0x27, 0x03},
|
||||
{0x28, 0x40}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
|
||||
{0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
|
||||
{0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
|
||||
{0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x80},
|
||||
{0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x20}, {0x3b, 0x00},
|
||||
{0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x0a}, {0x3f, 0x00},
|
||||
{0x40, 0x04}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
|
||||
{0x44, 0x30}, {0x45, 0x00}, {0x46, 0xc0}, {0x47, 0xff},
|
||||
{0x48, 0x00}, {0x49, 0x1c}, {0x4a, 0x05}, {0x4b, 0x03},
|
||||
{0x4c, 0xa3}, {0x4d, 0x28}, {0x4e, 0x00}, {0x4f, 0xc0},
|
||||
{0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
|
||||
{0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
|
||||
{0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
|
||||
{0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
|
||||
{0x60, 0x00}, {0x61, 0x20}, {0x62, 0x00}, {0x63, 0x00},
|
||||
{0x64, 0x5a}, {0x65, 0x02}, {0x66, 0x00}, {0x67, 0x00},
|
||||
{0x68, 0x10}, {0x69, 0x09}, {0x6a, 0x00}, {0x6b, 0x03},
|
||||
{0x6c, 0x00}, {0x6d, 0xc0}, {0x6e, 0x40}, {0x6f, 0x00},
|
||||
{0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
|
||||
{0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
|
||||
{0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
|
||||
{0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
|
||||
{0x80, 0x00}, {0x81, 0x22}, {0x82, 0x65}, {0x83, 0x35},
|
||||
{0x84, 0x31}, {0x85, 0x60}, {0x86, 0x03}, {0x87, 0x00},
|
||||
{0x88, 0x00}, {0x89, 0x00}, {0x8a, 0x00}, {0x8b, 0x00},
|
||||
{0x8c, 0x00}, {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x00},
|
||||
{0x90, 0x00}, {0x91, 0x00}, {0x92, 0x00}, {0x93, 0x18},
|
||||
{0x94, 0xfb}, {0x95, 0x0b}, {0x96, 0x00}, {0x97, 0x0b},
|
||||
{0x98, 0xdb}, {0x99, 0xdf}, {0x9a, 0x48}, {0x9b, 0x00},
|
||||
{0x9c, 0x3f}, {0x9d, 0x3f}, {0x9e, 0x77}, {0x9f, 0x77},
|
||||
{0xa0, 0x00}, {0xa1, 0xff}, {0xa2, 0xff}, {0xa3, 0xff},
|
||||
{0xa4, 0x00}, {0xa5, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
|
||||
{0xa8, 0x00}
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(DEFAULT_REGS); ++i) {
|
||||
reg = &DEFAULT_REGS[i];
|
||||
t1_setreg(wc, reg->address, reg->value);
|
||||
}
|
||||
/* Flush previous writes. */
|
||||
t1_getreg(wc, 0x1d);
|
||||
}
|
||||
|
||||
static void t4_serial_setup(struct t1 *wc)
|
||||
{
|
||||
t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
|
||||
@@ -2029,10 +2108,13 @@ static int t1xxp_set_linemode(struct dahdi_span *span, enum spantypes linemode)
|
||||
/* Stop the processing of the channels since we're going to change
|
||||
* them. */
|
||||
clear_bit(INITIALIZED, &wc->bit_flags);
|
||||
synchronize_irq(wc->vb.pdev->irq);
|
||||
smp_mb__after_clear_bit();
|
||||
del_timer_sync(&wc->timer);
|
||||
flush_workqueue(wc->wq);
|
||||
|
||||
t1_reset_registers(wc);
|
||||
|
||||
switch (linemode) {
|
||||
case SPANTYPE_DIGITAL_T1:
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
@@ -2206,27 +2288,32 @@ static void t1_check_alarms(struct t1 *wc)
|
||||
/* Detect loopup code if we're not sending one */
|
||||
if ((!wc->span.mainttimer) && (d & 0x08)) {
|
||||
/* Loop-up code detected */
|
||||
if ((wc->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
|
||||
if ((++wc->loopupcnt > 80) &&
|
||||
(wc->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
|
||||
t1_notice(wc, "Loopup detected,"\
|
||||
" enabling remote loop\n");
|
||||
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
|
||||
t1_setreg(wc, 0x37, 0xf6); /* LIM1: Enable remote loop */
|
||||
wc->span.maintstat = DAHDI_MAINT_REMOTELOOP;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
wc->loopupcnt = 0;
|
||||
}
|
||||
|
||||
/* Same for loopdown code */
|
||||
if ((!wc->span.mainttimer) && (d & 0x10)) {
|
||||
/* Loop-down code detected */
|
||||
if ((wc->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
|
||||
if ((++wc->loopdowncnt > 80) &&
|
||||
(wc->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
|
||||
t1_notice(wc, "Loopdown detected,"\
|
||||
" disabling remote loop\n");
|
||||
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
|
||||
t1_setreg(wc, 0x37, 0xf0); /* LIM1: Disable remote loop */
|
||||
wc->span.maintstat = DAHDI_MAINT_NONE;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
wc->loopdowncnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
|
||||
|
||||
@@ -114,6 +114,7 @@ struct t1 {
|
||||
#define INITIALIZED 1
|
||||
#define SHUTDOWN 2
|
||||
#define READY 3
|
||||
#define IOERROR 4
|
||||
unsigned long bit_flags;
|
||||
unsigned long alarmtimer;
|
||||
unsigned char ledstate;
|
||||
|
||||
3265
drivers/dahdi/wcte13xp-base.c
Normal file
3265
drivers/dahdi/wcte13xp-base.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "xpd.h"
|
||||
#include "xproto.h"
|
||||
#include "xpp_dahdi.h"
|
||||
@@ -152,8 +153,7 @@ static int write_state_register(xpd_t *xpd, __u8 value);
|
||||
static bool bri_packet_is_valid(xpacket_t *pack);
|
||||
static void bri_packet_dump(const char *msg, xpacket_t *pack);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_bri_info_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static const struct file_operations proc_bri_info_ops;
|
||||
#endif
|
||||
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
struct dahdi_lineconfig *lc);
|
||||
@@ -673,9 +673,8 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
XPD_DBG(PROC, xpd, "\n");
|
||||
#ifdef CONFIG_PROC_FS
|
||||
XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME);
|
||||
priv->bri_info =
|
||||
create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir,
|
||||
proc_bri_info_read, xpd);
|
||||
priv->bri_info = proc_create_data(PROC_BRI_INFO_FNAME, 0444,
|
||||
xpd->proc_xpd_dir, &proc_bri_info_ops, xpd);
|
||||
if (!priv->bri_info) {
|
||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||
PROC_BRI_INFO_FNAME);
|
||||
@@ -1667,12 +1666,10 @@ static void bri_packet_dump(const char *msg, xpacket_t *pack)
|
||||
/*------------------------- REGISTER Handling --------------------------*/
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_bri_info_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int proc_bri_info_show(struct seq_file *sfile, void *not_used)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long flags;
|
||||
xpd_t *xpd = data;
|
||||
xpd_t *xpd = sfile->private;
|
||||
struct BRI_priv_data *priv;
|
||||
|
||||
DBG(PROC, "\n");
|
||||
@@ -1681,69 +1678,65 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count,
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter);
|
||||
seq_printf(sfile, "%05d Layer 1: ", priv->poll_counter);
|
||||
if (priv->reg30_good) {
|
||||
len +=
|
||||
sprintf(page + len, "%-5s ",
|
||||
(priv->layer1_up) ? "UP" : "DOWN");
|
||||
len +=
|
||||
sprintf(page + len,
|
||||
"%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n",
|
||||
IS_NT(xpd) ? 'G' : 'F',
|
||||
priv->state_register.bits.v_su_sta,
|
||||
xhfc_state_name(IS_NT(xpd),
|
||||
priv->state_register.bits.v_su_sta),
|
||||
priv->state_register.bits.v_su_fr_sync,
|
||||
priv->state_register.bits.v_su_t2_exp,
|
||||
priv->state_register.bits.v_su_info0,
|
||||
priv->state_register.bits.v_g2_g3);
|
||||
} else
|
||||
len += sprintf(page + len, "Unknown\n");
|
||||
seq_printf(sfile, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN");
|
||||
seq_printf(sfile,
|
||||
"%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n",
|
||||
IS_NT(xpd) ? 'G' : 'F',
|
||||
priv->state_register.bits.v_su_sta,
|
||||
xhfc_state_name(IS_NT(xpd),
|
||||
priv->state_register.bits.v_su_sta),
|
||||
priv->state_register.bits.v_su_fr_sync,
|
||||
priv->state_register.bits.v_su_t2_exp,
|
||||
priv->state_register.bits.v_su_info0,
|
||||
priv->state_register.bits.v_g2_g3);
|
||||
} else {
|
||||
seq_printf(sfile, "Unknown\n");
|
||||
}
|
||||
if (IS_NT(xpd))
|
||||
len += sprintf(page + len, "T1 Timer: %d\n", priv->t1);
|
||||
seq_printf(sfile, "T1 Timer: %d\n", priv->t1);
|
||||
else
|
||||
len += sprintf(page + len, "T3 Timer: %d\n", priv->t3);
|
||||
len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter);
|
||||
len +=
|
||||
sprintf(page + len, "Last Poll Reply: %d ticks ago\n",
|
||||
seq_printf(sfile, "T3 Timer: %d\n", priv->t3);
|
||||
seq_printf(sfile, "Tick Counter: %d\n", priv->tick_counter);
|
||||
seq_printf(sfile, "Last Poll Reply: %d ticks ago\n",
|
||||
priv->reg30_ticks);
|
||||
len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good);
|
||||
len +=
|
||||
sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ",
|
||||
seq_printf(sfile, "reg30_good=%d\n", priv->reg30_good);
|
||||
seq_printf(sfile, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ",
|
||||
priv->dchan_tx_counter, priv->dchan_rx_counter,
|
||||
priv->dchan_rx_drops);
|
||||
if (priv->dchan_alive) {
|
||||
len +=
|
||||
sprintf(page + len, "(alive %d K-ticks)\n",
|
||||
seq_printf(sfile, "(alive %d K-ticks)\n",
|
||||
priv->dchan_alive_ticks / 1000);
|
||||
} else {
|
||||
len += sprintf(page + len, "(dead)\n");
|
||||
seq_printf(sfile, "(dead)\n");
|
||||
}
|
||||
len +=
|
||||
sprintf(page + len, "dchan_notx_ticks: %d\n",
|
||||
seq_printf(sfile, "dchan_notx_ticks: %d\n",
|
||||
priv->dchan_notx_ticks);
|
||||
len +=
|
||||
sprintf(page + len, "dchan_norx_ticks: %d\n",
|
||||
seq_printf(sfile, "dchan_norx_ticks: %d\n",
|
||||
priv->dchan_norx_ticks);
|
||||
len +=
|
||||
sprintf(page + len, "LED: %-10s = %d\n", "GREEN",
|
||||
seq_printf(sfile, "LED: %-10s = %d\n", "GREEN",
|
||||
priv->ledstate[GREEN_LED]);
|
||||
len +=
|
||||
sprintf(page + len, "LED: %-10s = %d\n", "RED",
|
||||
seq_printf(sfile, "LED: %-10s = %d\n", "RED",
|
||||
priv->ledstate[RED_LED]);
|
||||
len += sprintf(page + len, "\nDCHAN:\n");
|
||||
len += sprintf(page + len, "\n");
|
||||
seq_printf(sfile, "\nDCHAN:\n");
|
||||
seq_printf(sfile, "\n");
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_bri_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_bri_info_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int bri_xpd_probe(struct device *dev)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "xpd.h"
|
||||
#include "xproto.h"
|
||||
#include "xpp_dahdi.h"
|
||||
@@ -36,6 +38,10 @@ static const char rcsid[] = "$Id$";
|
||||
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||
static DEF_PARM(uint, poll_battery_interval, 500, 0644,
|
||||
"Poll battery interval in milliseconds (0 - disable)");
|
||||
static DEF_PARM_BOOL(use_polrev_firmware, 1, 0444,
|
||||
"Use firmware reports of polarity reversal");
|
||||
static DEF_PARM_BOOL(squelch_polrev, 0, 0644,
|
||||
"Never report polarity reversal");
|
||||
#ifdef WITH_METERING
|
||||
static DEF_PARM(uint, poll_metering_interval, 500, 0644,
|
||||
"Poll metering interval in milliseconds (0 - disable)");
|
||||
@@ -43,7 +49,11 @@ static DEF_PARM(uint, poll_metering_interval, 500, 0644,
|
||||
static DEF_PARM(int, ring_debounce, 50, 0644,
|
||||
"Number of ticks to debounce a false RING indication");
|
||||
static DEF_PARM(int, caller_id_style, 0, 0444,
|
||||
"Caller-Id detection style: 0 - [BELL], 1 - [ETSI_FSK], 2 - [ETSI_DTMF]");
|
||||
"Caller-Id detection style: "
|
||||
"0 - [BELL], "
|
||||
"1 - [ETSI_FSK], "
|
||||
"2 - [ETSI_DTMF], "
|
||||
"3 - [PASSTHROUGH]");
|
||||
static DEF_PARM(int, power_denial_safezone, 650, 0644,
|
||||
"msec after offhook to ignore power-denial ( (0 - disable power-denial)");
|
||||
static DEF_PARM(int, power_denial_minlen, 80, 0644,
|
||||
@@ -57,6 +67,8 @@ enum cid_style {
|
||||
CID_STYLE_BELL = 0, /* E.g: US (Bellcore) */
|
||||
CID_STYLE_ETSI_FSK = 1, /* E.g: UK (British Telecom) */
|
||||
CID_STYLE_ETSI_DTMF = 2, /* E.g: DK, Russia */
|
||||
CID_STYLE_PASSTHROUGH = 3, /* No change: Let asterisk */
|
||||
/* (>= 1.8) DSP handle this */
|
||||
};
|
||||
|
||||
/* Signaling is opposite (fxs signalling for fxo card) */
|
||||
@@ -95,14 +107,13 @@ enum fxo_leds {
|
||||
static bool fxo_packet_is_valid(xpacket_t *pack);
|
||||
static void fxo_packet_dump(const char *msg, xpacket_t *pack);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static const struct file_operations proc_fxo_info_ops;
|
||||
#ifdef WITH_METERING
|
||||
static int proc_xpd_metering_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data);
|
||||
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"
|
||||
@@ -110,6 +121,10 @@ static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
|
||||
#define PROC_METERING_FNAME "metering_read"
|
||||
#endif
|
||||
|
||||
#define REG_INTERRUPT_SRC 0x04 /* 4 - Interrupt Source */
|
||||
#define REG_INTERRUPT_SRC_POLI BIT(0) /* Polarity Reversal Detect Interrupt*/
|
||||
#define REG_INTERRUPT_SRC_RING BIT(7) /* Ring Detect Interrupt */
|
||||
|
||||
#define REG_DAA_CONTROL1 0x05 /* 5 - DAA Control 1 */
|
||||
#define REG_DAA_CONTROL1_OH BIT(0) /* Off-Hook. */
|
||||
#define REG_DAA_CONTROL1_ONHM BIT(3) /* On-Hook Line Monitor */
|
||||
@@ -148,6 +163,9 @@ struct FXO_priv_data {
|
||||
ushort nobattery_debounce[CHANNELS_PERXPD];
|
||||
enum polarity_state polarity[CHANNELS_PERXPD];
|
||||
ushort polarity_debounce[CHANNELS_PERXPD];
|
||||
int polarity_last_interval[CHANNELS_PERXPD];
|
||||
#define POLARITY_LAST_INTERVAL_NONE (-1)
|
||||
#define POLARITY_LAST_INTERVAL_MAX 40
|
||||
enum power_state power[CHANNELS_PERXPD];
|
||||
ushort power_denial_delay[CHANNELS_PERXPD];
|
||||
ushort power_denial_length[CHANNELS_PERXPD];
|
||||
@@ -345,6 +363,7 @@ static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_dahdi)
|
||||
MARK_BLINK(priv, pos, LED_GREEN, 0);
|
||||
if (update_dahdi)
|
||||
update_dahdi_ring(xpd, pos, on);
|
||||
priv->polarity_last_interval[pos] = POLARITY_LAST_INTERVAL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,8 +401,14 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
|
||||
DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1,
|
||||
value);
|
||||
mark_offhook(xpd, pos, to_offhook);
|
||||
if (caller_id_style != CID_STYLE_ETSI_DTMF)
|
||||
switch (caller_id_style) {
|
||||
case CID_STYLE_ETSI_DTMF:
|
||||
case CID_STYLE_PASSTHROUGH:
|
||||
break;
|
||||
default:
|
||||
oht_pcm(xpd, pos, 0);
|
||||
break;
|
||||
}
|
||||
#ifdef WITH_METERING
|
||||
priv->metering_count[pos] = 0;
|
||||
priv->metering_tone_state = 0L;
|
||||
@@ -415,7 +440,6 @@ static void fxo_proc_remove(xbus_t *xbus, xpd_t *xpd)
|
||||
#ifdef WITH_METERING
|
||||
if (priv->meteringfile) {
|
||||
XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
|
||||
priv->meteringfile->data = NULL;
|
||||
remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
|
||||
priv->meteringfile = NULL;
|
||||
}
|
||||
@@ -436,9 +460,9 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
priv = xpd->priv;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n");
|
||||
priv->fxo_info =
|
||||
create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir,
|
||||
proc_fxo_info_read, xpd);
|
||||
priv->fxo_info = proc_create_data(PROC_FXO_INFO_FNAME, 0444,
|
||||
xpd->proc_xpd_dir,
|
||||
&proc_fxo_info_ops, xpd);
|
||||
if (!priv->fxo_info) {
|
||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||
PROC_FXO_INFO_FNAME);
|
||||
@@ -448,9 +472,9 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
SET_PROC_DIRENTRY_OWNER(priv->fxo_info);
|
||||
#ifdef WITH_METERING
|
||||
XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
|
||||
priv->meteringfile =
|
||||
create_proc_read_entry(PROC_METERING_FNAME, 0444, xpd->proc_xpd_dir,
|
||||
proc_xpd_metering_read, xpd);
|
||||
priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0444,
|
||||
xpd->proc_xpd_dir,
|
||||
&proc_xpd_metering_ops, xpd);
|
||||
if (!priv->meteringfile) {
|
||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||
PROC_METERING_FNAME);
|
||||
@@ -513,8 +537,13 @@ static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
priv->battery[i] = BATTERY_UNKNOWN;
|
||||
/* will be updated on next battery sample */
|
||||
priv->power[i] = POWER_UNKNOWN;
|
||||
if (caller_id_style == CID_STYLE_ETSI_DTMF)
|
||||
switch (caller_id_style) {
|
||||
case CID_STYLE_ETSI_DTMF:
|
||||
case CID_STYLE_PASSTHROUGH:
|
||||
oht_pcm(xpd, i, 1);
|
||||
break;
|
||||
}
|
||||
priv->polarity_last_interval[i] = POLARITY_LAST_INTERVAL_NONE;
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "done\n");
|
||||
for_each_line(xpd, i) {
|
||||
@@ -684,6 +713,19 @@ static void handle_fxo_ring(xpd_t *xpd)
|
||||
|
||||
priv = xpd->priv;
|
||||
for_each_line(xpd, i) {
|
||||
if (likely(use_polrev_firmware)) {
|
||||
int *t = &priv->polarity_last_interval[i];
|
||||
if (*t != POLARITY_LAST_INTERVAL_NONE) {
|
||||
(*t)++;
|
||||
if (*t > POLARITY_LAST_INTERVAL_MAX) {
|
||||
LINE_DBG(SIGNAL, xpd, i,
|
||||
"polrev(GOOD): %d msec\n", *t);
|
||||
*t = POLARITY_LAST_INTERVAL_NONE;
|
||||
report_polarity_reversal(xpd,
|
||||
i, "firmware");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (atomic_read(&priv->ring_debounce[i]) > 0) {
|
||||
/* Maybe start ring */
|
||||
if (atomic_dec_and_test(&priv->ring_debounce[i]))
|
||||
@@ -799,9 +841,9 @@ static void check_etsi_dtmf(xpd_t *xpd)
|
||||
priv->cidtimer[portno] = timer_count;
|
||||
BIT_SET(priv->cidfound, portno);
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"Found DTMF CLIP (%d)\n", i);
|
||||
dahdi_qevent_lock(chan,
|
||||
DAHDI_EVENT_POLARITY);
|
||||
"Found DTMF CLIP (%d)\n", i);
|
||||
report_polarity_reversal(xpd, portno,
|
||||
"fake");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -951,6 +993,28 @@ HANDLER_DEF(FXO, SIG_CHANGED)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg)
|
||||
{
|
||||
/*
|
||||
* Inform dahdi/Asterisk:
|
||||
* 1. Maybe used for hangup detection during offhook
|
||||
* 2. In some countries used to report caller-id
|
||||
* during onhook but before first ring.
|
||||
*/
|
||||
if (caller_id_style == CID_STYLE_ETSI_FSK)
|
||||
/* will be cleared on ring/offhook */
|
||||
oht_pcm(xpd, portno, 1);
|
||||
if (SPAN_REGISTERED(xpd)) {
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"%s DAHDI_EVENT_POLARITY (%s)\n",
|
||||
(squelch_polrev) ? "Squelch" : "Send",
|
||||
msg);
|
||||
if (!squelch_polrev)
|
||||
dahdi_qevent_lock(XPD_CHAN(xpd, portno),
|
||||
DAHDI_EVENT_POLARITY);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_battery_voltage(xpd_t *xpd, __u8 data_low,
|
||||
xportno_t portno)
|
||||
{
|
||||
@@ -1048,22 +1112,8 @@ static void update_battery_voltage(xpd_t *xpd, __u8 data_low,
|
||||
BUG();
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"Polarity changed to %s\n", polname);
|
||||
/*
|
||||
* Inform dahdi/Asterisk:
|
||||
* 1. Maybe used for hangup detection during offhook
|
||||
* 2. In some countries used to report caller-id
|
||||
* during onhook but before first ring.
|
||||
*/
|
||||
if (caller_id_style == CID_STYLE_ETSI_FSK)
|
||||
/* will be cleared on ring/offhook */
|
||||
oht_pcm(xpd, portno, 1);
|
||||
if (SPAN_REGISTERED(xpd)) {
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"Send DAHDI_EVENT_POLARITY: %s\n",
|
||||
polname);
|
||||
dahdi_qevent_lock(XPD_CHAN(xpd, portno),
|
||||
DAHDI_EVENT_POLARITY);
|
||||
}
|
||||
if (!use_polrev_firmware)
|
||||
report_polarity_reversal(xpd, portno, polname);
|
||||
}
|
||||
priv->polarity[portno] = pol;
|
||||
}
|
||||
@@ -1146,6 +1196,50 @@ static void update_metering_state(xpd_t *xpd, __u8 data_low, lineno_t portno)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void got_chip_interrupt(xpd_t *xpd, __u8 data_low,
|
||||
xportno_t portno)
|
||||
{
|
||||
struct FXO_priv_data *priv;
|
||||
int t;
|
||||
|
||||
if (!use_polrev_firmware)
|
||||
return;
|
||||
priv = xpd->priv;
|
||||
LINE_DBG(SIGNAL, xpd, portno, "mask=0x%X\n", data_low);
|
||||
if (!(data_low & REG_INTERRUPT_SRC_POLI))
|
||||
return;
|
||||
t = priv->polarity_last_interval[portno];
|
||||
if (PHONEDEV(xpd).ringing[portno]) {
|
||||
priv->polarity_last_interval[portno] =
|
||||
POLARITY_LAST_INTERVAL_NONE;
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"polrev(false): %d msec (while ringing)\n", t);
|
||||
} else if (data_low & REG_INTERRUPT_SRC_RING) {
|
||||
priv->polarity_last_interval[portno] =
|
||||
POLARITY_LAST_INTERVAL_NONE;
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"polrev(false): %d msec (with chip-interrupt ring)\n",
|
||||
t);
|
||||
} else if (t == POLARITY_LAST_INTERVAL_NONE) {
|
||||
priv->polarity_last_interval[portno] = 0;
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"polrev(start)\n");
|
||||
} else if (t < POLARITY_LAST_INTERVAL_MAX) {
|
||||
/*
|
||||
* Start counting upward from -POLARITY_LAST_INTERVAL_MAX
|
||||
* Until we reach POLARITY_LAST_INTERVAL_NONE.
|
||||
* This way we filter bursts of false reports we get
|
||||
* during ringing.
|
||||
*/
|
||||
priv->polarity_last_interval[portno] =
|
||||
POLARITY_LAST_INTERVAL_NONE -
|
||||
POLARITY_LAST_INTERVAL_MAX;
|
||||
LINE_DBG(SIGNAL, xpd, portno,
|
||||
"polrev(false): %d msec (interval shorter than %d)\n",
|
||||
t, POLARITY_LAST_INTERVAL_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
{
|
||||
struct FXO_priv_data *priv;
|
||||
@@ -1155,6 +1249,9 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
BUG_ON(!priv);
|
||||
portno = info->portnum;
|
||||
switch (REG_FIELD(info, regnum)) {
|
||||
case REG_INTERRUPT_SRC:
|
||||
got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
|
||||
break;
|
||||
case DAA_REG_VBAT:
|
||||
update_battery_voltage(xpd, REG_FIELD(info, data_low), portno);
|
||||
break;
|
||||
@@ -1249,12 +1346,10 @@ static void fxo_packet_dump(const char *msg, xpacket_t *pack)
|
||||
/*------------------------- DAA Handling --------------------------*/
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int proc_fxo_info_show(struct seq_file *sfile, void *not_used)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long flags;
|
||||
xpd_t *xpd = data;
|
||||
xpd_t *xpd = sfile->private;
|
||||
struct FXO_priv_data *priv;
|
||||
int i;
|
||||
|
||||
@@ -1263,42 +1358,43 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
len += sprintf(page + len, "\t%-17s: ", "Channel");
|
||||
seq_printf(sfile, "\t%-17s: ", "Channel");
|
||||
for_each_line(xpd, i) {
|
||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, "%4d ", i % 10);
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
|
||||
seq_printf(sfile, "%4d ", i % 10);
|
||||
}
|
||||
}
|
||||
len += sprintf(page + len, "\nLeds:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "state");
|
||||
seq_printf(sfile, "\nLeds:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "state");
|
||||
for_each_line(xpd, i) {
|
||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len +=
|
||||
sprintf(page + len, " %d%d ",
|
||||
IS_SET(priv->ledstate[LED_GREEN], i),
|
||||
IS_SET(priv->ledstate[LED_RED], i));
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
|
||||
seq_printf(sfile, " %d%d ",
|
||||
IS_SET(priv->ledstate[LED_GREEN], i),
|
||||
IS_SET(priv->ledstate[LED_RED], i));
|
||||
}
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "blinking");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "blinking");
|
||||
for_each_line(xpd, i) {
|
||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len +=
|
||||
sprintf(page + len, " %d%d ",
|
||||
IS_BLINKING(priv, i, LED_GREEN),
|
||||
IS_BLINKING(priv, i, LED_RED));
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
|
||||
seq_printf(sfile, " %d%d ",
|
||||
IS_BLINKING(priv, i, LED_GREEN),
|
||||
IS_BLINKING(priv, i, LED_RED));
|
||||
}
|
||||
}
|
||||
len += sprintf(page + len, "\nBattery-Data:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "voltage");
|
||||
seq_printf(sfile, "\nBattery-Data:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "voltage");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d ", priv->battery_voltage[i]);
|
||||
seq_printf(sfile, "%4d ", priv->battery_voltage[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "current");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "current");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d ", priv->battery_current[i]);
|
||||
seq_printf(sfile, "%4d ", priv->battery_current[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\nBattery:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "on");
|
||||
seq_printf(sfile, "\nBattery:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "on");
|
||||
for_each_line(xpd, i) {
|
||||
char *bat;
|
||||
|
||||
@@ -1308,14 +1404,14 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||
bat = "-";
|
||||
else
|
||||
bat = ".";
|
||||
len += sprintf(page + len, "%4s ", bat);
|
||||
seq_printf(sfile, "%4s ", bat);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "debounce");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "debounce");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d ", priv->nobattery_debounce[i]);
|
||||
seq_printf(sfile, "%4d ", priv->nobattery_debounce[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\nPolarity-Reverse:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "polarity");
|
||||
seq_printf(sfile, "\nPolarity-Reverse:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "polarity");
|
||||
for_each_line(xpd, i) {
|
||||
char *polname;
|
||||
|
||||
@@ -1325,14 +1421,14 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||
polname = "-";
|
||||
else
|
||||
polname = ".";
|
||||
len += sprintf(page + len, "%4s ", polname);
|
||||
seq_printf(sfile, "%4s ", polname);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "debounce");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "debounce");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d ", priv->polarity_debounce[i]);
|
||||
seq_printf(sfile, "%4d ", priv->polarity_debounce[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\nPower-Denial:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "power");
|
||||
seq_printf(sfile, "\nPower-Denial:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "power");
|
||||
for_each_line(xpd, i) {
|
||||
char *curr;
|
||||
|
||||
@@ -1342,45 +1438,46 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||
curr = "-";
|
||||
else
|
||||
curr = ".";
|
||||
len += sprintf(page + len, "%4s ", curr);
|
||||
seq_printf(sfile, "%4s ", curr);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "safezone");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "safezone");
|
||||
for_each_line(xpd, i) {
|
||||
len +=
|
||||
sprintf(page + len, "%4d ", priv->power_denial_safezone[i]);
|
||||
seq_printf(sfile, "%4d ", priv->power_denial_safezone[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "delay");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "delay");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d ", priv->power_denial_delay[i]);
|
||||
seq_printf(sfile, "%4d ", priv->power_denial_delay[i]);
|
||||
}
|
||||
#ifdef WITH_METERING
|
||||
len += sprintf(page + len, "\nMetering:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "count");
|
||||
seq_printf(sfile, "\nMetering:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "count");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d ", priv->metering_count[i]);
|
||||
seq_printf(sfile, "%4d ", priv->metering_count[i]);
|
||||
}
|
||||
#endif
|
||||
len += sprintf(page + len, "\n");
|
||||
seq_printf(sfile, "\n");
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int proc_fxo_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_fxo_info_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
#ifdef WITH_METERING
|
||||
static int proc_xpd_metering_read(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
static int proc_xpd_metering_show(struct seq_file *sfile, void *not_used)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long flags;
|
||||
xpd_t *xpd = data;
|
||||
xpd_t *xpd = sfile->private;
|
||||
struct FXO_priv_data *priv;
|
||||
int i;
|
||||
|
||||
@@ -1389,25 +1486,31 @@ static int proc_xpd_metering_read(char *page, char **start, off_t off,
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
len += sprintf(page + len, "# Chan\tMeter (since last read)\n");
|
||||
seq_printf(sfile, "# Chan\tMeter (since last read)\n");
|
||||
for_each_line(xpd, i) {
|
||||
len +=
|
||||
sprintf(page + len, "%d\t%d\n", i, priv->metering_count[i]);
|
||||
seq_printf(sfile, "%d\t%d\n", i, priv->metering_count[i]);
|
||||
}
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
/* Zero meters */
|
||||
for_each_line(xpd, i)
|
||||
priv->metering_count[i] = 0;
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_xpd_metering_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_xpd_metering_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations proc_xpd_metering_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_xpd_metering_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static DEVICE_ATTR_READER(fxo_battery_show, dev, buf)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "xpd.h"
|
||||
#include "xproto.h"
|
||||
#include "xpp_dahdi.h"
|
||||
@@ -120,11 +121,9 @@ enum fxs_state {
|
||||
static bool fxs_packet_is_valid(xpacket_t *pack);
|
||||
static void fxs_packet_dump(const char *msg, xpacket_t *pack);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static const struct file_operations proc_fxs_info_ops;
|
||||
#ifdef WITH_METERING
|
||||
static int proc_xpd_metering_write(struct file *file,
|
||||
const char __user *buffer, unsigned long count, void *data);
|
||||
static const struct file_operations proc_xpd_metering_ops;
|
||||
#endif
|
||||
#endif
|
||||
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
|
||||
@@ -399,7 +398,6 @@ static void fxs_proc_remove(xbus_t *xbus, xpd_t *xpd)
|
||||
#ifdef WITH_METERING
|
||||
if (priv->meteringfile) {
|
||||
XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
|
||||
priv->meteringfile->data = NULL;
|
||||
remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
|
||||
priv->meteringfile = NULL;
|
||||
}
|
||||
@@ -421,9 +419,9 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n");
|
||||
priv->fxs_info =
|
||||
create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir,
|
||||
proc_fxs_info_read, xpd);
|
||||
priv->fxs_info = proc_create_data(PROC_FXS_INFO_FNAME, 0444,
|
||||
xpd->proc_xpd_dir,
|
||||
&proc_fxs_info_ops, xpd);
|
||||
if (!priv->fxs_info) {
|
||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||
PROC_FXS_INFO_FNAME);
|
||||
@@ -433,18 +431,15 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
SET_PROC_DIRENTRY_OWNER(priv->fxs_info);
|
||||
#ifdef WITH_METERING
|
||||
XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
|
||||
priv->meteringfile =
|
||||
create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir);
|
||||
priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0200,
|
||||
xpd->proc_xpd_dir,
|
||||
&proc_xpd_metering_ops, xpd);
|
||||
if (!priv->meteringfile) {
|
||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||
PROC_METERING_FNAME);
|
||||
fxs_proc_remove(xbus, xpd);
|
||||
return -EINVAL;
|
||||
}
|
||||
SET_PROC_DIRENTRY_OWNER(priv->meteringfile);
|
||||
priv->meteringfile->write_proc = proc_xpd_metering_write;
|
||||
priv->meteringfile->read_proc = NULL;
|
||||
priv->meteringfile->data = xpd;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
@@ -1691,12 +1686,10 @@ static void fxs_packet_dump(const char *msg, xpacket_t *pack)
|
||||
/*------------------------- SLIC Handling --------------------------*/
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int proc_fxs_info_show(struct seq_file *sfile, void *not_used)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long flags;
|
||||
xpd_t *xpd = data;
|
||||
xpd_t *xpd = sfile->private;
|
||||
struct FXS_priv_data *priv;
|
||||
int i;
|
||||
int led;
|
||||
@@ -1706,11 +1699,11 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
len += sprintf(page + len, "%-12s", "Channel:");
|
||||
seq_printf(sfile, "%-12s", "Channel:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d", i);
|
||||
seq_printf(sfile, "%4d", i);
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "");
|
||||
seq_printf(sfile, "\n%-12s", "");
|
||||
for_each_line(xpd, i) {
|
||||
char *chan_type;
|
||||
|
||||
@@ -1720,84 +1713,85 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
|
||||
chan_type = "in";
|
||||
else
|
||||
chan_type = "";
|
||||
len += sprintf(page + len, "%4s", chan_type);
|
||||
seq_printf(sfile, "%4s", chan_type);
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "idletxhook:");
|
||||
seq_printf(sfile, "\n%-12s", "idletxhook:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d", priv->idletxhookstate[i]);
|
||||
seq_printf(sfile, "%4d", priv->idletxhookstate[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "lasttxhook:");
|
||||
seq_printf(sfile, "\n%-12s", "lasttxhook:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d", priv->lasttxhook[i]);
|
||||
seq_printf(sfile, "%4d", priv->lasttxhook[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "ohttimer:");
|
||||
seq_printf(sfile, "\n%-12s", "ohttimer:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d", priv->ohttimer[i]);
|
||||
seq_printf(sfile, "%4d", priv->ohttimer[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "neon_blink:");
|
||||
seq_printf(sfile, "\n%-12s", "neon_blink:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d",
|
||||
seq_printf(sfile, "%4d",
|
||||
IS_SET(priv->neon_blinking, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "search_fsk:");
|
||||
seq_printf(sfile, "\n%-12s", "search_fsk:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d",
|
||||
seq_printf(sfile, "%4d",
|
||||
IS_SET(priv->search_fsk_pattern, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n%-12s", "vbat_h:");
|
||||
seq_printf(sfile, "\n%-12s", "vbat_h:");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%4d",
|
||||
seq_printf(sfile, "%4d",
|
||||
test_bit(i, (unsigned long *)&priv->vbat_h));
|
||||
}
|
||||
len += sprintf(page + len, "\n");
|
||||
seq_printf(sfile, "\n");
|
||||
for (led = 0; led < NUM_LEDS; led++) {
|
||||
len += sprintf(page + len, "\nLED #%d\t%-12s: ",
|
||||
seq_printf(sfile, "\nLED #%d\t%-12s: ",
|
||||
led, "ledstate");
|
||||
for_each_line(xpd, i) {
|
||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len +=
|
||||
sprintf(page + len, "%d ",
|
||||
seq_printf(sfile, "%d ",
|
||||
IS_SET(priv->ledstate[led], i));
|
||||
}
|
||||
len += sprintf(page + len, "\nLED #%d\t%-12s: ",
|
||||
seq_printf(sfile, "\nLED #%d\t%-12s: ",
|
||||
led, "ledcontrol");
|
||||
for_each_line(xpd, i) {
|
||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len +=
|
||||
sprintf(page + len, "%d ",
|
||||
seq_printf(sfile, "%d ",
|
||||
IS_SET(priv->ledcontrol[led], i));
|
||||
}
|
||||
len += sprintf(page + len, "\nLED #%d\t%-12s: ",
|
||||
seq_printf(sfile, "\nLED #%d\t%-12s: ",
|
||||
led, "led_counter");
|
||||
for_each_line(xpd, i) {
|
||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len +=
|
||||
sprintf(page + len, "%d ",
|
||||
seq_printf(sfile, "%d ",
|
||||
LED_COUNTER(priv, i, led));
|
||||
}
|
||||
}
|
||||
len += sprintf(page + len, "\n");
|
||||
seq_printf(sfile, "\n");
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int proc_fxs_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_fxs_info_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations proc_fxs_info_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_fxs_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
#ifdef WITH_METERING
|
||||
static int proc_xpd_metering_write(struct file *file, const char
|
||||
__user *buffer, unsigned long count, void *data)
|
||||
static ssize_t proc_xpd_metering_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *offset)
|
||||
{
|
||||
xpd_t *xpd = data;
|
||||
xpd_t *xpd = file->private_data;
|
||||
char buf[MAX_PROC_WRITE];
|
||||
lineno_t chan;
|
||||
int num;
|
||||
@@ -1806,7 +1800,7 @@ static int proc_xpd_metering_write(struct file *file, const char
|
||||
if (!xpd)
|
||||
return -ENODEV;
|
||||
if (count >= MAX_PROC_WRITE - 1) {
|
||||
XPD_ERR(xpd, "Metering string too long (%lu)\n", count);
|
||||
XPD_ERR(xpd, "Metering string too long (%zu)\n", count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (copy_from_user(&buf, buffer, count))
|
||||
@@ -1829,6 +1823,19 @@ static int proc_xpd_metering_write(struct file *file, const char
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int proc_xpd_metering_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = PDE_DATA(inode);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_xpd_metering_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_xpd_metering_open,
|
||||
.write = proc_xpd_metering_write,
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int fxs_xpd_probe(struct device *dev)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# $Id: PIC_TYPE_2.hex 9732 2011-08-24 19:13:55Z dima $
|
||||
# $Id: PIC_TYPE_2.hex 11078 2013-04-11 16:52:37Z dima $
|
||||
#
|
||||
:03000000A57A4896
|
||||
:03000000A5DA4836
|
||||
:03000100C41C41DB
|
||||
:030002000390392F
|
||||
:0300030067967984
|
||||
@@ -42,319 +42,375 @@
|
||||
:03002600CFC9013E
|
||||
:030027001652026C
|
||||
:0300280064403001
|
||||
:03002900A3290107
|
||||
:03002900A38901A7
|
||||
:03002A00704C40D7
|
||||
:03002B00A41FFF10
|
||||
:03002C00C011659B
|
||||
:03002D001E1C0294
|
||||
:03002E00C03FFFD1
|
||||
:03002F0016115057
|
||||
:030030002016B9DE
|
||||
:03003100125D025B
|
||||
:0300320020A022E9
|
||||
:03003300643C0228
|
||||
:03003400A3AD0178
|
||||
:03003500365162DF
|
||||
:030036003652053A
|
||||
:030037002C8030EA
|
||||
:03003800D00901EB
|
||||
:03003900A33204EB
|
||||
:03003A0020503023
|
||||
:03003B0072490106
|
||||
:03003C00A3E2023A
|
||||
:03003D00A40030EC
|
||||
:03003E0002D901E3
|
||||
:03003F00A4180002
|
||||
:0300400002E214C5
|
||||
:03004100800E70BE
|
||||
:030042000223088E
|
||||
:030043002063082F
|
||||
:030044006433081A
|
||||
:03004500A4A30869
|
||||
:0300460032203F26
|
||||
:030047002C880002
|
||||
:03004800D00C00D9
|
||||
:03004900A4403997
|
||||
:03004A00CFE038CC
|
||||
:03004B00162C0769
|
||||
:03004C00C01D4094
|
||||
:03004D00604034DC
|
||||
:03004E00122C0869
|
||||
:03004F00206038F6
|
||||
:03005000643219FE
|
||||
:03005100A56E0792
|
||||
:0300520036202035
|
||||
:030053002C83609B
|
||||
:03005400D0036076
|
||||
:03005500A50360A0
|
||||
:03005600800360C4
|
||||
:03005700C07C105A
|
||||
:03005800166038F7
|
||||
:03005900743219E5
|
||||
:03005A00A5FE07F9
|
||||
:03005B00C01120B1
|
||||
:03005C001CCC2099
|
||||
:03005D00E07180CF
|
||||
:03005E0002CE705F
|
||||
:03005F00206743D4
|
||||
:0300600090AA70F3
|
||||
:03006100205C021E
|
||||
:03006200D2018048
|
||||
:03006300D40E07B1
|
||||
:0300640003D6437D
|
||||
:03006500C1CA739A
|
||||
:03002B00A47FFFB0
|
||||
:03002C00C40165A7
|
||||
:03002D00150C02AD
|
||||
:03002E00743FFF1D
|
||||
:03002F00A32150BA
|
||||
:03003000C026B92E
|
||||
:03003100A33D02EA
|
||||
:03003200C01022D9
|
||||
:03003300121C029A
|
||||
:03003400C03D01CB
|
||||
:030035001611623F
|
||||
:0300360020120590
|
||||
:0300370012503034
|
||||
:0300380020A901FB
|
||||
:030039006432042A
|
||||
:03003A00A40030EF
|
||||
:03003B0036590132
|
||||
:03003C0036520237
|
||||
:03003D002C8030E4
|
||||
:03003E00D00901E5
|
||||
:03003F00A3980083
|
||||
:0300400020521437
|
||||
:03004100724E708C
|
||||
:03004200A44308CC
|
||||
:03004300A46308AB
|
||||
:0300440002D308DC
|
||||
:03004500A4730899
|
||||
:0300460002E03F96
|
||||
:030047008008002E
|
||||
:03004800022C0087
|
||||
:03004900206039FB
|
||||
:03004A00643038E7
|
||||
:03004B00A50C07FA
|
||||
:03004C00322D4012
|
||||
:03004D002C8034D0
|
||||
:03004E00D00C08CB
|
||||
:03004F00A4A03832
|
||||
:03005000CFE219E3
|
||||
:03005100162E0761
|
||||
:03005200C01020BB
|
||||
:03005300604360A7
|
||||
:0300540012236014
|
||||
:03005500206360C5
|
||||
:03005600643360B0
|
||||
:03005700A5CC1025
|
||||
:0300580036203817
|
||||
:030059002C8219DD
|
||||
:03005A00D00E07BE
|
||||
:03005B00A561207C
|
||||
:03005C00800C20F5
|
||||
:03005D00C07180EF
|
||||
:03005E00166E70AB
|
||||
:03005F00743743B0
|
||||
:03006000A65A702D
|
||||
:03006100C01C02BE
|
||||
:030062001CC1803E
|
||||
:03006300E07E0735
|
||||
:0300640002C6438E
|
||||
:03006500200A73FB
|
||||
:03006600022C0366
|
||||
:03006700C0018055
|
||||
:03006800024E073E
|
||||
:0300690021D6435A
|
||||
:03006A00030A7313
|
||||
:03006B00901C04E2
|
||||
:03006C00202180D0
|
||||
:03006D00030E0778
|
||||
:03006E00901643A6
|
||||
:03006F00204A73B1
|
||||
:03007000030C017D
|
||||
:03007100901038B4
|
||||
:03007200210A72EE
|
||||
:03007300024C1824
|
||||
:03007400C0303861
|
||||
:0300750008421925
|
||||
:03007600603E0FDA
|
||||
:03007700A7A0221D
|
||||
:03007800209C00C9
|
||||
:03007900A7C038E5
|
||||
:0300670020618095
|
||||
:03006800643E07EC
|
||||
:03006900A6E643C5
|
||||
:03006A00322A73C4
|
||||
:03006B002C8C04D6
|
||||
:03006C00D0018040
|
||||
:03006D00A68E0755
|
||||
:03006E00C0164376
|
||||
:03006F00142A73DD
|
||||
:03007000743C01DC
|
||||
:03007100ACB038F8
|
||||
:03007200206A728F
|
||||
:0300730090AC1836
|
||||
:03007400205038E1
|
||||
:03007500D202199B
|
||||
:03007600D40E0F96
|
||||
:0300770003D02291
|
||||
:03007800C04C0079
|
||||
:030079000220382A
|
||||
:03007A00C00200C1
|
||||
:03007B00A7CE0706
|
||||
:03007C00187F02E8
|
||||
:03007D0014974392
|
||||
:03007E00643A835E
|
||||
:03007F00AABC0018
|
||||
:030080001A7031C2
|
||||
:03008100C50C1299
|
||||
:03008200039A904E
|
||||
:030083007992006F
|
||||
:03008400A83E078C
|
||||
:0300850020BF0396
|
||||
:03008600D007435D
|
||||
:03008700038A8C5D
|
||||
:03008800219C00B8
|
||||
:03008900E07031F3
|
||||
:03008A00348C189B
|
||||
:03008B00348A9024
|
||||
:03008C00348C00B1
|
||||
:03008D003480318B
|
||||
:03008E00030C164A
|
||||
:03008F00206A9054
|
||||
:0300900034803B7E
|
||||
:03009100348E0F9B
|
||||
:0300920034808235
|
||||
:03009300348703AC
|
||||
:03009400D05A9AA5
|
||||
:03009500031C0F3A
|
||||
:03009600C00FFF99
|
||||
:0300970003215BE7
|
||||
:030098000331022F
|
||||
:03009900C70A9BF8
|
||||
:03009A0003921BB3
|
||||
:03009B00C500306D
|
||||
:03009C00039E0FB1
|
||||
:03009D00C1C03BA4
|
||||
:03009E00030C024E
|
||||
:03009F00C0003965
|
||||
:0300A000031C003E
|
||||
:0300A100204039C3
|
||||
:0300A200032C80AC
|
||||
:03007B00024E072B
|
||||
:03007C0021DF027F
|
||||
:03007D0003074333
|
||||
:03007E00901A8352
|
||||
:03007F00202C0032
|
||||
:0300800003003149
|
||||
:03008100901C12BE
|
||||
:03008200204A9081
|
||||
:0300830003020075
|
||||
:03008400901E07C4
|
||||
:03008500210F0345
|
||||
:03008600E017433D
|
||||
:03008700643A8C4C
|
||||
:03008800ACBC000D
|
||||
:0300890021003122
|
||||
:03008A00024C180D
|
||||
:03008B00E80A90F0
|
||||
:03008C00743C00C1
|
||||
:03008D00AB803114
|
||||
:03008E00C50C1688
|
||||
:03008F00039A9041
|
||||
:0300900079903B29
|
||||
:03009100A90E0FA6
|
||||
:0300920020B08219
|
||||
:03009300D0070390
|
||||
:03009400038A9A42
|
||||
:03009500219C0F9C
|
||||
:03009600E07FFF09
|
||||
:0300970034815B56
|
||||
:03009800348102AE
|
||||
:03009900348A9B0B
|
||||
:03009A0034821B92
|
||||
:03009B000300302F
|
||||
:03009C00206E0FC4
|
||||
:03009D0034803B71
|
||||
:03009E00348C029D
|
||||
:03009F0034803971
|
||||
:0300A000348C009D
|
||||
:0300A100D0503903
|
||||
:0300A200031C80BC
|
||||
:0300A300C00D0885
|
||||
:0300A400033039ED
|
||||
:0300A500C70C0085
|
||||
:0300A6000390398B
|
||||
:0300A700C50C4045
|
||||
:0300A80003903989
|
||||
:0300A900C407D9B0
|
||||
:0300AA00039AA90D
|
||||
:0300AB0020CC0066
|
||||
:0300AC0074302687
|
||||
:0300AD00B1702708
|
||||
:0300AE00C0002B64
|
||||
:0300AF00024020EC
|
||||
:0300B000C05C032E
|
||||
:0300B10002202CFE
|
||||
:0300B200205C20AF
|
||||
:0300B300D20D80EB
|
||||
:0300B400D4002550
|
||||
:0300B50003DC2049
|
||||
:0300B60021D02432
|
||||
:0300B700030C0037
|
||||
:0300B80090102283
|
||||
:0300B900202205FD
|
||||
:0300BA0003003010
|
||||
:0300BB0090190198
|
||||
:0300BC00204204DB
|
||||
:0300BD000300300D
|
||||
:0300BE0090190195
|
||||
:0300BF00C012026A
|
||||
:0300A400032039FD
|
||||
:0300A500033C0019
|
||||
:0300A600C7003957
|
||||
:0300A700039C4077
|
||||
:0300A800C5003957
|
||||
:0300A9000397D9E1
|
||||
:0300AA00C04AA9A0
|
||||
:0300AB00030C0043
|
||||
:0300AC00C000266B
|
||||
:0300AD0003102716
|
||||
:0300AE0020402BC4
|
||||
:0300AF000320200B
|
||||
:0300B000C00C037E
|
||||
:0300B10003302CED
|
||||
:0300B200C70C2058
|
||||
:0300B300039D802A
|
||||
:0300B400C500255F
|
||||
:0300B500039C2089
|
||||
:0300B600C400245F
|
||||
:0300B700039C00A7
|
||||
:0300B800C400225F
|
||||
:0300B900FFF2054E
|
||||
:0300BA00165030AD
|
||||
:0300BB00D2090166
|
||||
:0300BC0003D20468
|
||||
:0300BD00C0403010
|
||||
:0300BE0002290113
|
||||
:0300BF00C002027A
|
||||
:0300C000150030F8
|
||||
:0300C100024901F0
|
||||
:0300C20021AC402E
|
||||
:0300C3009420394D
|
||||
:0300C400202C01EC
|
||||
:0300C50003A0375E
|
||||
:0300C600206C604B
|
||||
:0300C7007432C8C8
|
||||
:0300C800AD5AC767
|
||||
:0300C900C9FC006F
|
||||
:0300CA0016B03736
|
||||
:0300CB00C006D993
|
||||
:0300CC006B0AD0EC
|
||||
:0300CD00D206F95F
|
||||
:0300CE006D0B4D6A
|
||||
:0300C20021DC40FE
|
||||
:0300C300030039FE
|
||||
:0300C400901C018C
|
||||
:0300C500202037C1
|
||||
:0300C600030C60C8
|
||||
:0300C7009012C8CC
|
||||
:0300C800204AC704
|
||||
:0300C900030C0025
|
||||
:0300CA009010375C
|
||||
:0300CB002066D9D3
|
||||
:0300CC0090AAD027
|
||||
:0300CD002056F9C1
|
||||
:0300CE00D20B4D05
|
||||
:0300CF00D40ACB85
|
||||
:0300D00012B94022
|
||||
:0300D100C80C2038
|
||||
:0300D2001AB195CB
|
||||
:0300D30020B64311
|
||||
:0300D400038ADFBD
|
||||
:0300D500206C019B
|
||||
:0300D60002A1DFA5
|
||||
:0300D700C0409B8B
|
||||
:0300D800086703B3
|
||||
:0300D900703ADF9B
|
||||
:0300DA00ADE7D3BC
|
||||
:0300DB00C00B480F
|
||||
:0300DC00024CFFD4
|
||||
:0300DD00AE202230
|
||||
:0300DE00C04B2AEA
|
||||
:0300DF000AA21F53
|
||||
:0300E000C0290A2A
|
||||
:0300E100024C20AE
|
||||
:0300E200917125F4
|
||||
:0300E300C016D371
|
||||
:0300E40003EAEA42
|
||||
:0300E500206C206C
|
||||
:0300E600643095EE
|
||||
:0300E700AEB6436F
|
||||
:0300E80037EAF202
|
||||
:0300E9002C8AEF6F
|
||||
:0300EA00AE8C4099
|
||||
:0300EB00C6012526
|
||||
:0300EC00150C00F0
|
||||
:0300ED0074302448
|
||||
:0300EE00AFFB1A4B
|
||||
:0300EF0021E217F4
|
||||
:0300F0001AF024DF
|
||||
:0300F10014FB1AE3
|
||||
:0300F200743C401B
|
||||
:0300F300B17105E3
|
||||
:0300F400C0403DCC
|
||||
:0300F500124C00AA
|
||||
:0300F600917024E2
|
||||
:0300F700C0021D27
|
||||
:0300F80002403093
|
||||
:0300F900200901DA
|
||||
:0300FA0094221538
|
||||
:0300FB0020203092
|
||||
:0300FC00020901F5
|
||||
:0300FD00035204A7
|
||||
:0300FE00B17030AE
|
||||
:0300FF00CFF90135
|
||||
:0301000019E210F1
|
||||
:0301010016F024D1
|
||||
:03010200C037F70C
|
||||
:03010300081B0BCB
|
||||
:03010400743C0246
|
||||
:03010500B0EFFF59
|
||||
:03010600C01164C1
|
||||
:03010700024C02A5
|
||||
:030108002001577C
|
||||
:030109009421241A
|
||||
:03010A00202B1790
|
||||
:03010B000207D711
|
||||
:03010C00035B177B
|
||||
:03010D00B17C01C1
|
||||
:03010E00C00FFF20
|
||||
:03010F0018116460
|
||||
:03011000643C014B
|
||||
:030111006B015728
|
||||
:03011200B14124D4
|
||||
:03011300B17B17A6
|
||||
:03011400C01217FF
|
||||
:0301150012402471
|
||||
:03011600917B17C3
|
||||
:03011700369C0211
|
||||
:03011800C01D0106
|
||||
:030119001E616400
|
||||
:03011A0021BC8085
|
||||
:03011B000866F380
|
||||
:03011C0074312516
|
||||
:03011D00A57205C3
|
||||
:03011E000260304C
|
||||
:03011F00C02901F3
|
||||
:03012000FFF215D6
|
||||
:0301210016B030E5
|
||||
:03012200C02901F0
|
||||
:0301230023A20410
|
||||
:0301240074303004
|
||||
:0301250012B9010B
|
||||
:0301260020B7D32C
|
||||
:03012700038B48FF
|
||||
:03012800C44210BE
|
||||
:030129000390221E
|
||||
:03012A00C40C50B2
|
||||
:03012B0003903905
|
||||
:03012C00C0079970
|
||||
:03012D00023B2C66
|
||||
:03012E00AC2212EE
|
||||
:03012F00B2F030FB
|
||||
:03013000000214B6
|
||||
:030131000000319A
|
||||
:03013200000213B5
|
||||
:0301330000003297
|
||||
:03013400000C00BC
|
||||
:0301350000003394
|
||||
:03013600000C704A
|
||||
:030137000000398C
|
||||
:03013800000C5068
|
||||
:030139000000398A
|
||||
:03013A00000215AB
|
||||
:03013B0000003091
|
||||
:03013C00000C00B4
|
||||
:03013D000000318E
|
||||
:03013E00000202BA
|
||||
:03013F000000328B
|
||||
:03014000000C00B0
|
||||
:0301410000003388
|
||||
:03014200000C703E
|
||||
:0301430000003980
|
||||
:03014400000C505C
|
||||
:030145000000397E
|
||||
:03014600000C406A
|
||||
:030147000000397C
|
||||
:03014800000C00A8
|
||||
:030149000000397A
|
||||
:03014A00000C00A6
|
||||
:03014B00000C00A5
|
||||
:03014C00000AC2E4
|
||||
:03014D00000C00A3
|
||||
:03014E0000002589
|
||||
:03014F00000C1091
|
||||
:0301500000003D6F
|
||||
:030151000009178B
|
||||
:03015200000C049A
|
||||
:0301530000002584
|
||||
:03015400000C009C
|
||||
:0301550000003D6A
|
||||
:0301560000091786
|
||||
:03015700000C0297
|
||||
:030158000000257F
|
||||
:03015900000C088F
|
||||
:03015A0000003D65
|
||||
:03015B0000091781
|
||||
:03015C00000C0094
|
||||
:03015D0000002679
|
||||
:03015E00000C0191
|
||||
:03015F0000002974
|
||||
:03016000000C2070
|
||||
:0301610000002378
|
||||
:03016200000A0090
|
||||
:03016300000B632B
|
||||
:0300D00003D94011
|
||||
:0300D100C1CC207F
|
||||
:0300D20002219573
|
||||
:0300D300C0064321
|
||||
:0300D400024ADFFE
|
||||
:0300D50021DC012A
|
||||
:0300D6000301DF44
|
||||
:0300D70090109BEB
|
||||
:0300D800202703DB
|
||||
:0300D900030ADF38
|
||||
:0300DA009017D3A9
|
||||
:0300DB00204B486F
|
||||
:0300DC00030CFF13
|
||||
:0300DD009010225E
|
||||
:0300DE00210B2AC9
|
||||
:0300DF0002421FBB
|
||||
:0300E000C0390A1A
|
||||
:0300E100084C20A8
|
||||
:0300E20060312565
|
||||
:0300E300AE66D333
|
||||
:0300E400209AEA75
|
||||
:0300E500AE8C20BE
|
||||
:0300E600C00095C2
|
||||
:0300E700AE86439F
|
||||
:0300E800187AF291
|
||||
:0300E900149AEF77
|
||||
:0300EA00643C4033
|
||||
:0300EB00B17125CB
|
||||
:0300EC001A7C007B
|
||||
:0300ED00C5002427
|
||||
:0300EE00039B1A57
|
||||
:0300EF00799217EC
|
||||
:0300F000AEF0244B
|
||||
:0300F10020BB1A17
|
||||
:0300F200D00C40EF
|
||||
:0300F30003810581
|
||||
:0300F40021903D1B
|
||||
:0300F500E07C00AC
|
||||
:0300F6003480242F
|
||||
:0300F70034821D33
|
||||
:0300F80034803021
|
||||
:0300F90034890146
|
||||
:0300FA00030215E9
|
||||
:0300FB0020603052
|
||||
:0300FC0034890143
|
||||
:0300FD0034820446
|
||||
:0300FE003480301B
|
||||
:0300FF0034890140
|
||||
:03010000D05210CA
|
||||
:03010100031024C4
|
||||
:03010200C007F73C
|
||||
:03010300032B0BC0
|
||||
:03010400033C02B7
|
||||
:03010500C70FFF22
|
||||
:03010600039164FE
|
||||
:03010700C50C0222
|
||||
:0301080003915709
|
||||
:03010900C1C1244D
|
||||
:03010A00030B17CD
|
||||
:03010B00C007D753
|
||||
:03010C00031B17BB
|
||||
:03010D00204C0182
|
||||
:03010E00032FFFBD
|
||||
:03010F00C00164C8
|
||||
:03011000033C01AC
|
||||
:03011100C70157CC
|
||||
:0301120003912432
|
||||
:03011300C50B1702
|
||||
:030114000392173C
|
||||
:03011500C40024FF
|
||||
:03011600039B1731
|
||||
:0301170020CC02F7
|
||||
:03011800743D0132
|
||||
:03011900B8316496
|
||||
:03011A00C00C8096
|
||||
:03011B000246F3A6
|
||||
:03011C00C05125AA
|
||||
:03011D00022205B6
|
||||
:03011E002050303E
|
||||
:03011F00D2090101
|
||||
:03012000D40215F1
|
||||
:0301210003D030D8
|
||||
:0301220021D901DF
|
||||
:03012300030204D0
|
||||
:0301240090103008
|
||||
:030125002029018D
|
||||
:030126000307D3F9
|
||||
:03012700901B48E2
|
||||
:0301280020421062
|
||||
:03012900030022AE
|
||||
:03012A00901C50D6
|
||||
:03012B00C01039C8
|
||||
:03012C001507991B
|
||||
:03012D00024B2C56
|
||||
:03012E0021A212F9
|
||||
:03012F0094803089
|
||||
:0301300020221476
|
||||
:0301310003A031F7
|
||||
:0301320020621335
|
||||
:03013300743032F3
|
||||
:03013400B41C00F8
|
||||
:03013500C9F033DB
|
||||
:0301360016BC7084
|
||||
:03013700C00039CC
|
||||
:030138006B0C50FD
|
||||
:03013900D20039B8
|
||||
:03013A006D02153E
|
||||
:03013B00D40030BD
|
||||
:03013C0012BC00F2
|
||||
:03013D00C80031C6
|
||||
:03013E001AB202F0
|
||||
:03013F0020B032BB
|
||||
:03014000038C002D
|
||||
:0301410020603308
|
||||
:0301420002AC709C
|
||||
:03014300C0403980
|
||||
:03014400086C50F4
|
||||
:03014500703039DE
|
||||
:03014600B4AC4016
|
||||
:03014700C00039BC
|
||||
:03014800024C0066
|
||||
:03014900B4E039E6
|
||||
:03014A00C04C00A6
|
||||
:03014B000AAC00FB
|
||||
:03014C00C02AC204
|
||||
:03014D00024C0061
|
||||
:03014E0091702588
|
||||
:03014F00C01C10C1
|
||||
:0301500003E03D8C
|
||||
:030151002069170B
|
||||
:03015200643C0406
|
||||
:03015300B570255F
|
||||
:0301540037EC0085
|
||||
:030155002C803DBE
|
||||
:03015600B5491791
|
||||
:03015700C60C02D1
|
||||
:030158001500256A
|
||||
:03015900743C08EB
|
||||
:03015A00B6B03DFF
|
||||
:03015B0021E91780
|
||||
:03015C001AFC008A
|
||||
:03015D0014F02675
|
||||
:03015E00743C01ED
|
||||
:03015F00B830298C
|
||||
:03016000C04C2070
|
||||
:0301610012402326
|
||||
:03016200917A008F
|
||||
:03016300C00B636B
|
||||
:0301640002400056
|
||||
:0301650020000077
|
||||
:0301660094800082
|
||||
:0301670020200055
|
||||
:0301680002000092
|
||||
:0301690003500040
|
||||
:03016A00B83000AA
|
||||
:03016B00CFF000D2
|
||||
:03016C0019E00097
|
||||
:03016D0016F00089
|
||||
:03016E00C030009E
|
||||
:03016F0008100075
|
||||
:03017000743000E8
|
||||
:03017100B7A00034
|
||||
:03017200C01000BA
|
||||
:0301730002400047
|
||||
:0301740020000068
|
||||
:0301750094800073
|
||||
:0301760020200046
|
||||
:0301770002000083
|
||||
:0301780003500031
|
||||
:03017900B830009B
|
||||
:03017A00C00000C2
|
||||
:03017B0018100059
|
||||
:03017C00643000EC
|
||||
:03017D006B000014
|
||||
:03017E00B80000C6
|
||||
:03017F00B8300095
|
||||
:03018000C01000AC
|
||||
:0301810012400029
|
||||
:0301820091700079
|
||||
:03018300369000B3
|
||||
:03018400C01000A8
|
||||
:030185001E6000F9
|
||||
:0301860021B000A5
|
||||
:030187000860000D
|
||||
:03018800743000D0
|
||||
:03018900A5D000FE
|
||||
:03018A0002600010
|
||||
:03018B00C0200091
|
||||
:03018C00FFF00081
|
||||
:03018D0016B000A9
|
||||
:03018E00C020008E
|
||||
:03018F0023A000AA
|
||||
:03019000743000C8
|
||||
:0301910012B000A9
|
||||
:0301920020B0009A
|
||||
:03019300038000E6
|
||||
:03019400C4400064
|
||||
:03019500039000D4
|
||||
:03019600C40000A2
|
||||
:03019700039000D2
|
||||
:03019800C00000A4
|
||||
:0301990002300031
|
||||
:03019A00AC200096
|
||||
:03019B00B9B000F8
|
||||
:00000001FF
|
||||
|
||||
@@ -415,6 +415,9 @@ close STDERR;
|
||||
exit 0;
|
||||
|
||||
__DATA__
|
||||
* WD 12 02 # Full wave rectified ring detection
|
||||
* WD 03 01 # Polarity reversal detect mask
|
||||
* WD 04 00 # Clear interrupt status
|
||||
* WD 21 08 # Disable PCM transfers
|
||||
* WD 18 99
|
||||
* WD 06 00
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
#include <linux/ctype.h>
|
||||
#endif
|
||||
@@ -47,8 +48,7 @@ static const char rcsid[] = "$Id$";
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#define PROC_XBUS_COMMAND "command"
|
||||
static int proc_xbus_command_write(struct file *file,
|
||||
const char __user *buffer, unsigned long count, void *data);
|
||||
static const struct file_operations proc_xbus_command_ops;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -63,8 +63,7 @@ static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
|
||||
"Register devices automatically (1) or not (0)");
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int xbus_read_proc(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static const struct file_operations xbus_read_proc_ops;
|
||||
#endif
|
||||
static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
|
||||
ushort max_send_size,
|
||||
@@ -1532,29 +1531,26 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
|
||||
err = -EIO;
|
||||
goto nobus;
|
||||
}
|
||||
xbus->proc_xbus_summary =
|
||||
create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir,
|
||||
xbus_read_proc,
|
||||
(void *)((unsigned long)(xbus->num)));
|
||||
xbus->proc_xbus_summary = proc_create_data(PROC_XBUS_SUMMARY, 0444,
|
||||
xbus->proc_xbus_dir,
|
||||
&xbus_read_proc_ops,
|
||||
(void *)((unsigned long)xbus->num));
|
||||
if (!xbus->proc_xbus_summary) {
|
||||
XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
|
||||
PROC_XBUS_SUMMARY);
|
||||
err = -EIO;
|
||||
goto nobus;
|
||||
}
|
||||
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_summary);
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
xbus->proc_xbus_command =
|
||||
create_proc_entry(PROC_XBUS_COMMAND, 0200, xbus->proc_xbus_dir);
|
||||
xbus->proc_xbus_command = proc_create_data(PROC_XBUS_COMMAND, 0200,
|
||||
xbus->proc_xbus_dir,
|
||||
&proc_xbus_command_ops, xbus);
|
||||
if (!xbus->proc_xbus_command) {
|
||||
XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
|
||||
PROC_XBUS_COMMAND);
|
||||
err = -EIO;
|
||||
goto nobus;
|
||||
}
|
||||
xbus->proc_xbus_command->write_proc = proc_xbus_command_write;
|
||||
xbus->proc_xbus_command->data = xbus;
|
||||
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_command);
|
||||
#endif
|
||||
#endif
|
||||
xframe_queue_init(&xbus->command_queue, 10, command_queue_length,
|
||||
@@ -1596,8 +1592,6 @@ static bool xpds_done(xbus_t *xbus)
|
||||
{
|
||||
if (XBUS_IS(xbus, FAIL))
|
||||
return 1; /* Nothing to wait for */
|
||||
if (!XBUS_IS(xbus, RECVD_DESC))
|
||||
return 1; /* We are not in the initialization phase */
|
||||
if (xbus->worker.xpds_init_done)
|
||||
return 1; /* All good */
|
||||
/* Keep waiting */
|
||||
@@ -1626,14 +1620,9 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
||||
len = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (worker->num_units == 0) {
|
||||
XBUS_ERR(xbus, "No cards. Skipping.\n");
|
||||
goto out;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus,
|
||||
"Waiting for card init of %d XPD's max %d seconds (%p)\n",
|
||||
worker->num_units, INITIALIZATION_TIMEOUT / HZ,
|
||||
&worker->wait_for_xpd_initialization);
|
||||
"Waiting for card init of XPDs max %d seconds\n",
|
||||
INITIALIZATION_TIMEOUT / HZ);
|
||||
ret =
|
||||
wait_event_interruptible_timeout(worker->
|
||||
wait_for_xpd_initialization,
|
||||
@@ -1668,106 +1657,96 @@ out:
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
static int xbus_fill_proc_queue(char *p, struct xframe_queue *q)
|
||||
static void xbus_fill_proc_queue(struct seq_file *sfile, struct xframe_queue *q)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = sprintf(p,
|
||||
seq_printf(sfile,
|
||||
"%-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);
|
||||
xframe_queue_clearstats(q);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int xbus_read_proc(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int xbus_proc_show(struct seq_file *sfile, void *data)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
unsigned long flags;
|
||||
int len = 0;
|
||||
int i = (int)((unsigned long)data);
|
||||
int i = (int)((unsigned long)sfile->private);
|
||||
|
||||
xbus = get_xbus(__func__, i); /* until end of xbus_read_proc */
|
||||
xbus = get_xbus(__func__, i); /* until end of xbus_proc_show() */
|
||||
if (!xbus)
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&xbus->lock, flags);
|
||||
|
||||
len +=
|
||||
sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
||||
seq_printf(sfile, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
||||
xbus->busname, xbus->connector, xbus->label,
|
||||
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing");
|
||||
len += xbus_fill_proc_queue(page + len, &xbus->send_pool);
|
||||
len += xbus_fill_proc_queue(page + len, &xbus->receive_pool);
|
||||
len += xbus_fill_proc_queue(page + len, &xbus->command_queue);
|
||||
len += xbus_fill_proc_queue(page + len, &xbus->receive_queue);
|
||||
len += xbus_fill_proc_queue(page + len, &xbus->pcm_tospan);
|
||||
xbus_fill_proc_queue(sfile, &xbus->send_pool);
|
||||
xbus_fill_proc_queue(sfile, &xbus->receive_pool);
|
||||
xbus_fill_proc_queue(sfile, &xbus->command_queue);
|
||||
xbus_fill_proc_queue(sfile, &xbus->receive_queue);
|
||||
xbus_fill_proc_queue(sfile, &xbus->pcm_tospan);
|
||||
if (rx_tasklet) {
|
||||
len += sprintf(page + len, "\ncpu_rcv_intr: ");
|
||||
seq_printf(sfile, "\ncpu_rcv_intr: ");
|
||||
for_each_online_cpu(i)
|
||||
len += sprintf(page + len, "%5d ", xbus->cpu_rcv_intr[i]);
|
||||
len += sprintf(page + len, "\ncpu_rcv_tasklet: ");
|
||||
seq_printf(sfile, "%5d ", xbus->cpu_rcv_intr[i]);
|
||||
seq_printf(sfile, "\ncpu_rcv_tasklet: ");
|
||||
for_each_online_cpu(i)
|
||||
len +=
|
||||
sprintf(page + len, "%5d ", xbus->cpu_rcv_tasklet[i]);
|
||||
len += sprintf(page + len, "\n");
|
||||
seq_printf(sfile, "%5d ", xbus->cpu_rcv_tasklet[i]);
|
||||
seq_printf(sfile, "\n");
|
||||
}
|
||||
len +=
|
||||
sprintf(page + len, "self_ticking: %d (last_tick at %ld)\n",
|
||||
seq_printf(sfile, "self_ticking: %d (last_tick at %ld)\n",
|
||||
xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec);
|
||||
len +=
|
||||
sprintf(page + len, "command_tick: %d\n",
|
||||
seq_printf(sfile, "command_tick: %d\n",
|
||||
xbus->command_tick_counter);
|
||||
len += sprintf(page + len, "usec_nosend: %d\n", xbus->usec_nosend);
|
||||
len +=
|
||||
sprintf(page + len, "xbus: pcm_rx_counter = %d, frag = %d\n",
|
||||
seq_printf(sfile, "usec_nosend: %d\n", xbus->usec_nosend);
|
||||
seq_printf(sfile, "xbus: pcm_rx_counter = %d, frag = %d\n",
|
||||
atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count);
|
||||
len +=
|
||||
sprintf(page + len, "max_rx_process = %2ld.%ld ms\n",
|
||||
seq_printf(sfile, "max_rx_process = %2ld.%ld ms\n",
|
||||
xbus->max_rx_process / 1000, xbus->max_rx_process % 1000);
|
||||
xbus->max_rx_process = 0;
|
||||
len +=
|
||||
sprintf(page + len, "\nTRANSPORT: max_send_size=%d refcount=%d\n",
|
||||
seq_printf(sfile, "\nTRANSPORT: max_send_size=%d refcount=%d\n",
|
||||
MAX_SEND_SIZE(xbus),
|
||||
atomic_read(&xbus->transport.transport_refcount)
|
||||
);
|
||||
len += sprintf(page + len, "PCM Metrices:\n");
|
||||
len +=
|
||||
sprintf(page + len, "\tPCM TX: min=%ld max=%ld\n",
|
||||
seq_printf(sfile, "PCM Metrices:\n");
|
||||
seq_printf(sfile, "\tPCM TX: min=%ld max=%ld\n",
|
||||
xbus->min_tx_sync, xbus->max_tx_sync);
|
||||
len +=
|
||||
sprintf(page + len, "\tPCM RX: min=%ld max=%ld\n",
|
||||
seq_printf(sfile, "\tPCM RX: min=%ld max=%ld\n",
|
||||
xbus->min_rx_sync, xbus->max_rx_sync);
|
||||
len += sprintf(page + len, "COUNTERS:\n");
|
||||
seq_printf(sfile, "COUNTERS:\n");
|
||||
for (i = 0; i < XBUS_COUNTER_MAX; i++) {
|
||||
len +=
|
||||
sprintf(page + len, "\t%-15s = %d\n", xbus_counters[i].name,
|
||||
seq_printf(sfile, "\t%-15s = %d\n", xbus_counters[i].name,
|
||||
xbus->counters[i]);
|
||||
}
|
||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||
seq_printf(sfile, "<-- len=%d\n", len);
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
put_xbus(__func__, xbus); /* from xbus_read_proc() */
|
||||
out:
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
put_xbus(__func__, xbus); /* from xbus_proc_show() */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int xbus_read_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, xbus_proc_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
static int proc_xbus_command_write(struct file *file,
|
||||
const char __user *buffer, unsigned long count, void *data)
|
||||
static ssize_t proc_xbus_command_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *offset)
|
||||
{
|
||||
char *buf;
|
||||
xbus_t *xbus = data;
|
||||
xbus_t *xbus = file->private_data;
|
||||
char *p;
|
||||
__u8 *pack_start;
|
||||
__u8 *q;
|
||||
@@ -1777,7 +1756,7 @@ static int proc_xbus_command_write(struct file *file,
|
||||
const size_t max_text = max_len * 3 + 10;
|
||||
|
||||
if (count > max_text) {
|
||||
XBUS_ERR(xbus, "%s: line too long (%ld > %zd)\n", __func__,
|
||||
XBUS_ERR(xbus, "%s: line too long (%zd > %zd)\n", __func__,
|
||||
count, max_len);
|
||||
return -EFBIG;
|
||||
}
|
||||
@@ -1790,7 +1769,7 @@ static int proc_xbus_command_write(struct file *file,
|
||||
goto out;
|
||||
}
|
||||
buf[count] = '\0';
|
||||
XBUS_DBG(GENERAL, xbus, "count=%ld\n", count);
|
||||
XBUS_DBG(GENERAL, xbus, "count=%zd\n", count);
|
||||
/*
|
||||
* We replace the content of buf[] from
|
||||
* ascii representation to packet content
|
||||
@@ -1846,20 +1825,29 @@ out:
|
||||
kfree(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static int proc_xbus_command_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = PDE_DATA(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations proc_xbus_command_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = proc_xbus_command_open,
|
||||
.write = proc_xbus_command_write,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int read_proc_xbuses(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int xpp_proc_read_show(struct seq_file *sfile, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_BUSES; i++) {
|
||||
xbus_t *xbus = get_xbus(__func__, i);
|
||||
|
||||
if (xbus) {
|
||||
len +=
|
||||
sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
"%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
||||
xbus->busname, xbus->connector, xbus->label,
|
||||
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected"
|
||||
@@ -1868,19 +1856,24 @@ static int read_proc_xbuses(char *page, char **start, off_t off, int count,
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||
seq_printf(sfile, "<-- len=%d\n", len);
|
||||
#endif
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xpp_proc_read_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, xpp_proc_read_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
|
||||
@@ -1971,15 +1964,13 @@ int __init xbus_core_init(void)
|
||||
INFO("FEATURE: with PROTOCOL_DEBUG\n");
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
proc_xbuses =
|
||||
create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel,
|
||||
read_proc_xbuses, NULL);
|
||||
proc_xbuses = proc_create_data(PROC_XBUSES, 0444, xpp_proc_toplevel,
|
||||
&xpp_proc_read_ops, NULL);
|
||||
if (!proc_xbuses) {
|
||||
ERR("Failed to create proc file %s\n", PROC_XBUSES);
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
SET_PROC_DIRENTRY_OWNER(proc_xbuses);
|
||||
#endif
|
||||
if ((ret = xpp_driver_init()) < 0)
|
||||
goto err;
|
||||
|
||||
@@ -145,10 +145,12 @@ typedef char *charp;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
/* Also don't define this for later RHEL >= 5.2 . hex_asc is from the
|
||||
* same linux-2.6-net-infrastructure-updates-to-mac80211-iwl4965.patch
|
||||
* as is the bool typedef. */
|
||||
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 18) || !defined(hex_asc)
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <linux/delay.h> /* for udelay */
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <dahdi/kernel.h>
|
||||
#include "xbus-core.h"
|
||||
#include "xproto.h"
|
||||
@@ -102,8 +103,7 @@ int total_registered_spans(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int xpd_read_proc(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static const struct file_operations xpd_read_proc_ops;
|
||||
#endif
|
||||
|
||||
/*------------------------- XPD Management -------------------------*/
|
||||
@@ -169,9 +169,9 @@ static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd)
|
||||
XPD_ERR(xpd, "Failed to create proc directory\n");
|
||||
goto err;
|
||||
}
|
||||
xpd->proc_xpd_summary =
|
||||
create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir,
|
||||
xpd_read_proc, xpd);
|
||||
xpd->proc_xpd_summary = proc_create_data(PROC_XPD_SUMMARY, 0444,
|
||||
xpd->proc_xpd_dir,
|
||||
&xpd_read_proc_ops, xpd);
|
||||
if (!xpd->proc_xpd_summary) {
|
||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||
PROC_XPD_SUMMARY);
|
||||
@@ -254,89 +254,72 @@ EXPORT_SYMBOL(create_xpd);
|
||||
|
||||
/**
|
||||
* Prints a general procfs entry for the bus, under xpp/BUSNAME/summary
|
||||
* @page TODO: figure out procfs
|
||||
* @start TODO: figure out procfs
|
||||
* @off TODO: figure out procfs
|
||||
* @count TODO: figure out procfs
|
||||
* @eof TODO: figure out procfs
|
||||
* @data an xbus_t pointer with the bus data.
|
||||
*/
|
||||
static int xpd_read_proc(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int xpd_read_proc_show(struct seq_file *sfile, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
xpd_t *xpd = data;
|
||||
xpd_t *xpd = sfile->private;
|
||||
int i;
|
||||
|
||||
if (!xpd)
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
|
||||
len +=
|
||||
sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
"%s (%s, card %s, span %d)\n" "timing_priority: %d\n"
|
||||
"timer_count: %d span->mainttimer=%d\n", xpd->xpdname,
|
||||
xpd->type_name, (xpd->card_present) ? "present" : "missing",
|
||||
(SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0,
|
||||
PHONEDEV(xpd).timing_priority, xpd->timer_count,
|
||||
PHONEDEV(xpd).span.mainttimer);
|
||||
len +=
|
||||
sprintf(page + len, "xpd_state: %s (%d)\n",
|
||||
seq_printf(sfile, "xpd_state: %s (%d)\n",
|
||||
xpd_statename(xpd->xpd_state), xpd->xpd_state);
|
||||
len +=
|
||||
sprintf(page + len, "open_counter=%d refcount=%d\n",
|
||||
seq_printf(sfile, "open_counter=%d refcount=%d\n",
|
||||
atomic_read(&PHONEDEV(xpd).open_counter),
|
||||
refcount_xpd(xpd));
|
||||
len +=
|
||||
sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit,
|
||||
seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit,
|
||||
xpd->addr.subunit);
|
||||
len += sprintf(page + len, "Subunits: %d\n", xpd->subunits);
|
||||
len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
|
||||
len += sprintf(page + len, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
|
||||
len +=
|
||||
sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n",
|
||||
seq_printf(sfile, "Subunits: %d\n", xpd->subunits);
|
||||
seq_printf(sfile, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
|
||||
seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
|
||||
seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n",
|
||||
PHONEDEV(xpd).wanted_pcm_mask);
|
||||
len +=
|
||||
sprintf(page + len, "mute_dtmf=0x%04X\n\n",
|
||||
seq_printf(sfile, "mute_dtmf=0x%04X\n\n",
|
||||
PHONEDEV(xpd).mute_dtmf);
|
||||
len += sprintf(page + len, "STATES:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "output_relays");
|
||||
seq_printf(sfile, "STATES:");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "output_relays");
|
||||
for_each_line(xpd, i) {
|
||||
len +=
|
||||
sprintf(page + len, "%d ",
|
||||
seq_printf(sfile, "%d ",
|
||||
IS_SET(PHONEDEV(xpd).digital_outputs, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "input_relays");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "input_relays");
|
||||
for_each_line(xpd, i) {
|
||||
len +=
|
||||
sprintf(page + len, "%d ",
|
||||
seq_printf(sfile, "%d ",
|
||||
IS_SET(PHONEDEV(xpd).digital_inputs, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "offhook");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "offhook");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", IS_OFFHOOK(xpd, i));
|
||||
seq_printf(sfile, "%d ", IS_OFFHOOK(xpd, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "oht_pcm_pass");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "oht_pcm_pass");
|
||||
for_each_line(xpd, i) {
|
||||
len +=
|
||||
sprintf(page + len, "%d ",
|
||||
seq_printf(sfile, "%d ",
|
||||
IS_SET(PHONEDEV(xpd).oht_pcm_pass, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "msg_waiting");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", PHONEDEV(xpd).msg_waiting[i]);
|
||||
seq_printf(sfile, "%d ", PHONEDEV(xpd).msg_waiting[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "ringing");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "ringing");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", PHONEDEV(xpd).ringing[i]);
|
||||
seq_printf(sfile, "%d ", PHONEDEV(xpd).ringing[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "no_pcm");
|
||||
seq_printf(sfile, "\n\t%-17s: ", "no_pcm");
|
||||
for_each_line(xpd, i) {
|
||||
len +=
|
||||
sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
|
||||
seq_printf(sfile, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
|
||||
}
|
||||
#if 1
|
||||
if (SPAN_REGISTERED(xpd)) {
|
||||
len += sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
"\nPCM:\n |"
|
||||
" [readchunk] |"
|
||||
" [writechunk] | W D");
|
||||
@@ -358,16 +341,16 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count,
|
||||
wp = chan->writechunk;
|
||||
memcpy(rchunk, rp, DAHDI_CHUNKSIZE);
|
||||
memcpy(wchunk, wp, DAHDI_CHUNKSIZE);
|
||||
len += sprintf(page + len, "\n port %2d> | ", i);
|
||||
seq_printf(sfile, "\n port %2d> | ", i);
|
||||
for (j = 0; j < DAHDI_CHUNKSIZE; j++)
|
||||
len += sprintf(page + len, "%02X ", rchunk[j]);
|
||||
len += sprintf(page + len, " | ");
|
||||
seq_printf(sfile, "%02X ", rchunk[j]);
|
||||
seq_printf(sfile, " | ");
|
||||
for (j = 0; j < DAHDI_CHUNKSIZE; j++)
|
||||
len += sprintf(page + len, "%02X ", wchunk[j]);
|
||||
len += sprintf(page + len, " | %c",
|
||||
seq_printf(sfile, "%02X ", wchunk[j]);
|
||||
seq_printf(sfile, " | %c",
|
||||
(IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i))
|
||||
? '+' : ' ');
|
||||
len += sprintf(page + len, " %c",
|
||||
seq_printf(sfile, " %c",
|
||||
(IS_SET(PHONEDEV(xpd).mute_dtmf, i))
|
||||
? '-' : ' ');
|
||||
}
|
||||
@@ -375,36 +358,37 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count,
|
||||
#endif
|
||||
#if 0
|
||||
if (SPAN_REGISTERED(xpd)) {
|
||||
len += sprintf(page + len, "\nSignalling:\n");
|
||||
seq_printf(sfile, "\nSignalling:\n");
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||
len +=
|
||||
sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
"\t%2d> sigcap=0x%04X sig=0x%04X\n", i,
|
||||
chan->sigcap, chan->sig);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
len += sprintf(page + len, "\nCOUNTERS:\n");
|
||||
seq_printf(sfile, "\nCOUNTERS:\n");
|
||||
for (i = 0; i < XPD_COUNTER_MAX; i++) {
|
||||
len +=
|
||||
sprintf(page + len, "\t\t%-20s = %d\n",
|
||||
seq_printf(sfile, "\t\t%-20s = %d\n",
|
||||
xpd_counters[i].name, xpd->counters[i]);
|
||||
}
|
||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||
out:
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
|
||||
seq_printf(sfile, "<-- len=%d\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xpd_read_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, xpd_read_proc_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations xpd_read_proc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = xpd_read_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
const char *xpd_statename(enum xpd_state st)
|
||||
|
||||
@@ -231,8 +231,7 @@ static int xusb_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id);
|
||||
static void xusb_disconnect(struct usb_interface *interface);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int xusb_read_proc(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data);
|
||||
static const struct file_operations xusb_read_proc_ops;
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
@@ -743,9 +742,9 @@ static int xusb_probe(struct usb_interface *interface,
|
||||
#ifdef CONFIG_PROC_FS
|
||||
DBG(PROC,
|
||||
"Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n");
|
||||
procsummary =
|
||||
create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444,
|
||||
xbus->proc_xbus_dir, xusb_read_proc, xusb);
|
||||
procsummary = proc_create_data(PROC_USBXPP_SUMMARY, 0444,
|
||||
xbus->proc_xbus_dir, &xusb_read_proc_ops,
|
||||
xusb);
|
||||
if (!procsummary) {
|
||||
XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
|
||||
PROC_USBXPP_SUMMARY);
|
||||
@@ -753,7 +752,6 @@ static int xusb_probe(struct usb_interface *interface,
|
||||
retval = -EIO;
|
||||
goto probe_failed;
|
||||
}
|
||||
SET_PROC_DIRENTRY_OWNER(procsummary);
|
||||
#endif
|
||||
bus_count++;
|
||||
xusb->xbus_num = xbus->num;
|
||||
@@ -1020,90 +1018,83 @@ static void __exit xpp_usb_shutdown(void)
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
static int xusb_read_proc(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int xusb_read_proc_show(struct seq_file *sfile, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
//unsigned long stamp = jiffies;
|
||||
xusb_t *xusb = data;
|
||||
xusb_t *xusb = sfile->private;
|
||||
uint usb_tx_delay[NUM_BUCKETS];
|
||||
const int mark_limit = tx_sluggish / USEC_BUCKET;
|
||||
|
||||
if (!xusb)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
// TODO: probably needs a per-xusb lock:
|
||||
spin_lock_irqsave(&xusb_lock, flags);
|
||||
len +=
|
||||
sprintf(page + len, "Device: %03d/%03d\n", xusb->udev->bus->busnum,
|
||||
seq_printf(sfile, "Device: %03d/%03d\n", xusb->udev->bus->busnum,
|
||||
xusb->udev->devnum);
|
||||
len +=
|
||||
sprintf(page + len, "USB: manufacturer=%s\n", xusb->manufacturer);
|
||||
len += sprintf(page + len, "USB: product=%s\n", xusb->product);
|
||||
len += sprintf(page + len, "USB: serial=%s\n", xusb->serial);
|
||||
len +=
|
||||
sprintf(page + len, "Minor: %d\nModel Info: %s\n", xusb->minor,
|
||||
seq_printf(sfile, "USB: manufacturer=%s\n", xusb->manufacturer);
|
||||
seq_printf(sfile, "USB: product=%s\n", xusb->product);
|
||||
seq_printf(sfile, "USB: serial=%s\n", xusb->serial);
|
||||
seq_printf(sfile, "Minor: %d\nModel Info: %s\n", xusb->minor,
|
||||
xusb->model_info->desc);
|
||||
len +=
|
||||
sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
"Endpoints:\n" "\tIn: 0x%02X - Size: %d)\n"
|
||||
"\tOut: 0x%02X - Size: %d)\n",
|
||||
xusb->endpoints[XUSB_RECV].ep_addr,
|
||||
xusb->endpoints[XUSB_RECV].max_size,
|
||||
xusb->endpoints[XUSB_SEND].ep_addr,
|
||||
xusb->endpoints[XUSB_SEND].max_size);
|
||||
len +=
|
||||
sprintf(page + len, "\npending_writes=%d\n",
|
||||
seq_printf(sfile, "\npending_writes=%d\n",
|
||||
atomic_read(&xusb->pending_writes));
|
||||
len +=
|
||||
sprintf(page + len, "pending_reads=%d\n",
|
||||
seq_printf(sfile, "pending_reads=%d\n",
|
||||
atomic_read(&xusb->pending_reads));
|
||||
len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay);
|
||||
seq_printf(sfile, "max_tx_delay=%d\n", xusb->max_tx_delay);
|
||||
xusb->max_tx_delay = 0;
|
||||
#ifdef DEBUG_PCM_TIMING
|
||||
len +=
|
||||
sprintf(page + len,
|
||||
seq_printf(sfile,
|
||||
"\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n",
|
||||
stamp_last_pcm_read, accumulate_diff);
|
||||
#endif
|
||||
memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay));
|
||||
len +=
|
||||
sprintf(page + len, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
|
||||
seq_printf(sfile, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
|
||||
BUCKET_START, NUM_BUCKETS);
|
||||
for (i = BUCKET_START; i < NUM_BUCKETS; i++) {
|
||||
len += sprintf(page + len, "%6d ", usb_tx_delay[i]);
|
||||
seq_printf(sfile, "%6d ", usb_tx_delay[i]);
|
||||
if (i == mark_limit)
|
||||
len += sprintf(page + len, "| ");
|
||||
seq_printf(sfile, "| ");
|
||||
}
|
||||
len +=
|
||||
sprintf(page + len, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
|
||||
seq_printf(sfile, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
|
||||
atomic_read(&xusb->pcm_tx_drops),
|
||||
atomic_read(&xusb->usb_sluggish_count)
|
||||
);
|
||||
len += sprintf(page + len, "\nCOUNTERS:\n");
|
||||
seq_printf(sfile, "\nCOUNTERS:\n");
|
||||
for (i = 0; i < XUSB_COUNTER_MAX; i++) {
|
||||
len +=
|
||||
sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name,
|
||||
seq_printf(sfile, "\t%-15s = %d\n", xusb_counters[i].name,
|
||||
xusb->counters[i]);
|
||||
}
|
||||
#if 0
|
||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||
seq_printf(sfile, "<-- len=%d\n", len);
|
||||
#endif
|
||||
spin_unlock_irqrestore(&xusb_lock, flags);
|
||||
out:
|
||||
if (len <= off + count)
|
||||
*eof = 1;
|
||||
*start = page + off;
|
||||
len -= off;
|
||||
if (len > count)
|
||||
len = count;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
return len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xusb_read_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, xusb_read_proc_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations xusb_read_proc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = xusb_read_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("XPP USB Transport Driver");
|
||||
|
||||
@@ -190,4 +190,10 @@
|
||||
*/
|
||||
/* #define CONFIG_DAHDI_MIRROR */
|
||||
|
||||
/*
|
||||
* Adds support for conference links. There are some non-Asterisk users of this
|
||||
* functionality.
|
||||
*/
|
||||
/* #define CONFIG_DAHDI_CONFLINK */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
@@ -100,6 +101,14 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* __dev* were removed in 3.8. They still have effect in 2.6.18. */
|
||||
#ifndef __devinit
|
||||
# define __devinit
|
||||
# define __devinitdata
|
||||
# define __devexit
|
||||
# define __devexit_p(x) x
|
||||
#endif
|
||||
|
||||
/*! Default chunk size for conferences and such -- static right now, might make
|
||||
variable sometime. 8 samples = 1 ms = most frequent service interval possible
|
||||
for a USB device */
|
||||
@@ -605,6 +614,8 @@ struct dahdi_chan {
|
||||
#else
|
||||
unsigned char *lin2x;
|
||||
#endif
|
||||
struct device chan_device; /*!< Kernel object for this chan */
|
||||
#define dev_to_chan(dev) container_of(dev, struct dahdi_chan, chan_device)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DAHDI_NET
|
||||
@@ -738,15 +749,16 @@ static inline int dahdi_have_netdev(const struct dahdi_chan *chan) { return 0; }
|
||||
#endif
|
||||
|
||||
struct dahdi_count {
|
||||
__u32 fe; /*!< Framing error counter */
|
||||
__u32 cv; /*!< Coding violations counter */
|
||||
__u32 bpv; /*!< Bipolar Violation counter */
|
||||
__u32 crc4; /*!< CRC4 error counter */
|
||||
__u32 ebit; /*!< current E-bit error count */
|
||||
__u32 fas; /*!< current FAS error count */
|
||||
__u32 be; /*!< current bit error count */
|
||||
__u32 prbs; /*!< current PRBS detected pattern */
|
||||
__u32 errsec; /*!< errored seconds */
|
||||
u32 fe; /*!< Framing error counter */
|
||||
u32 cv; /*!< Coding violations counter */
|
||||
u32 bpv; /*!< Bipolar Violation counter */
|
||||
u32 crc4; /*!< CRC4 error counter */
|
||||
u32 ebit; /*!< current E-bit error count */
|
||||
u32 fas; /*!< current FAS error count */
|
||||
u32 be; /*!< current bit error count */
|
||||
u32 prbs; /*!< current PRBS detected pattern */
|
||||
u32 errsec; /*!< errored seconds */
|
||||
u32 timingslips; /*!< Clock slips */
|
||||
};
|
||||
|
||||
/* map flagbits to flag masks */
|
||||
@@ -952,8 +964,6 @@ struct dahdi_span {
|
||||
int maintstat; /*!< Maintenance state */
|
||||
int mainttimer; /*!< Maintenance timer */
|
||||
|
||||
int timingslips; /*!< Clock slips */
|
||||
|
||||
struct dahdi_chan **chans; /*!< Member channel structures */
|
||||
|
||||
const struct dahdi_span_ops *ops; /*!< span callbacks. */
|
||||
@@ -1227,6 +1237,12 @@ void dahdi_init_tone_state(struct dahdi_tone_state *ts, struct dahdi_tone *zt);
|
||||
/*! \brief Get a given MF tone struct, suitable for dahdi_tone_nextsample. */
|
||||
struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int digitmode);
|
||||
|
||||
/*! \brief Convert signalling bits to human readable string */
|
||||
const char *sigstr(int sig);
|
||||
|
||||
/*! \brief Convert alarm bits to human readable string */
|
||||
int fill_alarm_string(char *buf, int count, int alarms);
|
||||
|
||||
/* Echo cancel a receive and transmit chunk for a given channel. This
|
||||
should be called by the low-level driver as close to the interface
|
||||
as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE
|
||||
@@ -1385,9 +1401,33 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
|
||||
/*! Maximum audio mask */
|
||||
#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
static inline void *PDE_DATA(const struct inode *inode)
|
||||
{
|
||||
return PDE(inode)->data;
|
||||
}
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
|
||||
#define KERN_CONT ""
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
static inline struct proc_dir_entry *proc_create_data(const char *name,
|
||||
mode_t mode,
|
||||
struct proc_dir_entry *parent,
|
||||
const struct file_operations *proc_fops,
|
||||
void *data)
|
||||
{
|
||||
struct proc_dir_entry *pde = create_proc_entry(name, mode, parent);
|
||||
if (!pde)
|
||||
return NULL;
|
||||
pde->proc_fops = proc_fops;
|
||||
pde->data = data;
|
||||
return pde;
|
||||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
#ifndef clamp
|
||||
#define clamp(x, low, high) min(max(low, x), high)
|
||||
#endif
|
||||
@@ -1440,10 +1480,7 @@ static inline int strcasecmp(const char *s1, const char *s2)
|
||||
#endif /* 2.6.25 */
|
||||
#endif /* 2.6.26 */
|
||||
#endif /* 2.6.31 */
|
||||
|
||||
#ifndef CONFIG_TRACING
|
||||
#define trace_printk printk
|
||||
#endif
|
||||
#endif /* 3.10.0 */
|
||||
|
||||
#ifndef DEFINE_SPINLOCK
|
||||
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
|
||||
|
||||
@@ -636,6 +636,11 @@ struct dahdi_confinfo {
|
||||
#define DAHDI_SETCONF_V1 _IOW(DAHDI_CODE, 12, struct dahdi_confinfo)
|
||||
#define DAHDI_SETCONF _IOWR(DAHDI_CODE, 13, struct dahdi_confinfo)
|
||||
|
||||
/*
|
||||
* Setup or Remove Conference Link
|
||||
*/
|
||||
#define DAHDI_CONFLINK _IOW(DAHDI_CODE, 14, struct dahdi_confinfo)
|
||||
|
||||
/*
|
||||
* Display Conference Diagnostic Information on Console
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user