Compare commits
202 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae8a02168b | ||
|
|
2a5638deef | ||
|
|
fcaec330e5 | ||
|
|
41639330a5 | ||
|
|
e3931e5d5f | ||
|
|
33b4edf463 | ||
|
|
46cfdca5d5 | ||
|
|
42be50ca28 | ||
|
|
f6511b1040 | ||
|
|
179a48862d | ||
|
|
f9632cdeb3 | ||
|
|
161698087d | ||
|
|
6262abb53c | ||
|
|
7ad722e684 | ||
|
|
3a3684a38e | ||
|
|
8db0c61fd8 | ||
|
|
319d51ae5d | ||
|
|
83090b71cf | ||
|
|
c0eebd73bb | ||
|
|
9aa57f62f1 | ||
|
|
79e20be476 | ||
|
|
396f1a76b1 | ||
|
|
ca95a19f41 | ||
|
|
41c3c2e879 | ||
|
|
c98b3a689e | ||
|
|
9deb9b2a4f | ||
|
|
0a92282cfe | ||
|
|
3c800538f7 | ||
|
|
6384cb034a | ||
|
|
0ecf2c67c8 | ||
|
|
89ea0430df | ||
|
|
05bac84ce8 | ||
|
|
5b675ab400 | ||
|
|
69774cd457 | ||
|
|
9dde3cff9c | ||
|
|
e15edb0d7a | ||
|
|
848d5ae115 | ||
|
|
fa86c13c3b | ||
|
|
bad3860f24 | ||
|
|
5fcf13fdef | ||
|
|
7c99a670b5 | ||
|
|
91a94133f1 | ||
|
|
4f487f8d7d | ||
|
|
77437503a8 | ||
|
|
8297239209 | ||
|
|
28d13b909c | ||
|
|
52b56c9848 | ||
|
|
eff796fd8f | ||
|
|
00ef2bfa13 | ||
|
|
a2bfd1d4c2 | ||
|
|
6009f56f8b | ||
|
|
7a497cee43 | ||
|
|
853b69a106 | ||
|
|
adfcd9d864 | ||
|
|
2b2054f28b | ||
|
|
6e1058eae0 | ||
|
|
8067ae3269 | ||
|
|
54b9983407 | ||
|
|
b4989839bc | ||
|
|
3876f253a6 | ||
|
|
005aa723ef | ||
|
|
808b2dd408 | ||
|
|
081977bc94 | ||
|
|
f06c8d50cf | ||
|
|
17a2ce9421 | ||
|
|
5ed0271397 | ||
|
|
48b3cb8777 | ||
|
|
d726b04767 | ||
|
|
e5ed586e31 | ||
|
|
6f2a52b764 | ||
|
|
b91ec305be | ||
|
|
afe3702873 | ||
|
|
892e49c356 | ||
|
|
9fd76d93c9 | ||
|
|
6706b03d9d | ||
|
|
2ae396112a | ||
|
|
b6f3466607 | ||
|
|
9ce15dc967 | ||
|
|
2b11667c47 | ||
|
|
6b6d047241 | ||
|
|
2983075256 | ||
|
|
b43c7f02a0 | ||
|
|
990af593a5 | ||
|
|
654486dc24 | ||
|
|
6d1713c2c0 | ||
|
|
da149b0d4d | ||
|
|
06961f8605 | ||
|
|
2a3a074f33 | ||
|
|
c4616c6c86 | ||
|
|
244c9bd254 | ||
|
|
cc7c73c4d8 | ||
|
|
66eb65dda7 | ||
|
|
1372573e68 | ||
|
|
1e22667c31 | ||
|
|
8bcab23272 | ||
|
|
1a79cb4fdc | ||
|
|
bc7c111d7e | ||
|
|
4b58524565 | ||
|
|
6ed54cc7e3 | ||
|
|
09e46f2213 | ||
|
|
875c1ec3b6 | ||
|
|
382125f880 | ||
|
|
1e561e4ed7 | ||
|
|
f0c61c85b8 | ||
|
|
74d86c535d | ||
|
|
0c89cad864 | ||
|
|
e74fb7d04d | ||
|
|
c7228589a9 | ||
|
|
6a1561b749 | ||
|
|
ce261cd03a | ||
|
|
a054cddc09 | ||
|
|
fde1081677 | ||
|
|
e3c07497ee | ||
|
|
11d8140b23 | ||
|
|
47beee98d7 | ||
|
|
f9326ca60f | ||
|
|
d556a1a57a | ||
|
|
3fc23b4465 | ||
|
|
4d10eab759 | ||
|
|
8f4a626087 | ||
|
|
bf3d8aa2cd | ||
|
|
aab9e51f30 | ||
|
|
bfae9c07da | ||
|
|
7c4c826d68 | ||
|
|
d91b3c53d3 | ||
|
|
39c4b93ed6 | ||
|
|
f9c52bb271 | ||
|
|
8d23f878d4 | ||
|
|
a6824019fb | ||
|
|
2794bb4937 | ||
|
|
935c9ba50a | ||
|
|
38c3cda8e2 | ||
|
|
3998c8fd11 | ||
|
|
33c31e9593 | ||
|
|
4b1a2f9127 | ||
|
|
35ffe2f550 | ||
|
|
f06aa486c7 | ||
|
|
e14f3fa541 | ||
|
|
955641b52c | ||
|
|
b7485aa383 | ||
|
|
a81fb56b5f | ||
|
|
ef426966d6 | ||
|
|
133be4bb27 | ||
|
|
73764a1dc9 | ||
|
|
19e874f682 | ||
|
|
22e054a958 | ||
|
|
20ee5f5b0c | ||
|
|
ac09987a59 | ||
|
|
eae6c0d1e7 | ||
|
|
0544f8c7cc | ||
|
|
a01f74d64a | ||
|
|
58514bc801 | ||
|
|
fabe174b83 | ||
|
|
d8c0898fb7 | ||
|
|
fbc506c865 | ||
|
|
2c4dad3c58 | ||
|
|
2c341b481e | ||
|
|
9c8eb34337 | ||
|
|
fba8fd1a70 | ||
|
|
534c7e7547 | ||
|
|
f02b476fee | ||
|
|
4231523c2f | ||
|
|
ae2785e0e7 | ||
|
|
4edd8a1973 | ||
|
|
17e0f2b7bb | ||
|
|
5afc62e856 | ||
|
|
dafb5f401b | ||
|
|
e025a651fb | ||
|
|
dfab257fef | ||
|
|
6fcd923dee | ||
|
|
1ba9a007d1 | ||
|
|
d4ee448c7e | ||
|
|
dc6ef91241 | ||
|
|
0c5b91cc80 | ||
|
|
57f80508b5 | ||
|
|
17f0170829 | ||
|
|
874b76bd22 | ||
|
|
cea4b8bda3 | ||
|
|
60caca49f4 | ||
|
|
b5bacb94a7 | ||
|
|
a2aba65e0c | ||
|
|
32bb7d4c10 | ||
|
|
fd3eb2da05 | ||
|
|
25cb4126c8 | ||
|
|
3d8629e864 | ||
|
|
1d03f6f8a8 | ||
|
|
cfafd3a7b7 | ||
|
|
a3fd58979d | ||
|
|
77ec2dce9f | ||
|
|
cdeaafb910 | ||
|
|
41c24c400e | ||
|
|
f74112b551 | ||
|
|
0bc7ff0816 | ||
|
|
ad4489c7f4 | ||
|
|
1862d8040c | ||
|
|
3b20fe39af | ||
|
|
eda8ceea1c | ||
|
|
e25a65b692 | ||
|
|
4f8b2dded1 | ||
|
|
77113b822f | ||
|
|
c793b1b173 | ||
|
|
d401ad4233 |
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
|
||||
6
Makefile
6
Makefile
@@ -67,13 +67,7 @@ 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
|
||||
|
||||
all: modules
|
||||
|
||||
176
README
176
README
@@ -17,6 +17,7 @@ Digital Cards
|
||||
* Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1
|
||||
* Digium TE220: PCI-Express dual-port T1/E1/J1
|
||||
* Digium TE420: PCI-Express quad-port T1/E1/J1
|
||||
* Digium TE820: PCI-Express eight-port T1/E1/J1
|
||||
- wcte12xp:
|
||||
* Digium TE120P: PCI single-port T1/E1/J1
|
||||
* Digium TE121: PCI-Express single-port T1/E1/J1
|
||||
@@ -535,6 +536,7 @@ timing device it will hang forever in the first cycle. Otherwise it will just
|
||||
give you in each cycle the percent of how close it was. Also try running it
|
||||
with the option -v for a verbose output.
|
||||
|
||||
|
||||
Spans and Channels
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
DAHDI provides telephony *channels* to the userspace applications.
|
||||
@@ -554,6 +556,81 @@ There are up to 128 spans and 1024 channels. This is a hard-wired limit
|
||||
number fits in a 16 bits number). Channel and span numbers start at 1.
|
||||
|
||||
|
||||
Span Assignments
|
||||
~~~~~~~~~~~~~~~~
|
||||
A DAHDI device (e.g. a PCI card) is represented within the DAHDI drivers
|
||||
as a 'DAHDI device'. Normally (with auto_assign_spans=1 in the module
|
||||
dahdi, which is the default), when a device is discovered and loaded,
|
||||
it registers with the DAHDI core and its spans automatically become
|
||||
available. However if you have more than one device, you may be
|
||||
interested to set explicit spans and channels numbers for them. To use
|
||||
manual span assigment, set 'auto_assign_spans' to 0 . e.g. in a file
|
||||
under /etc/modprobe.d/ include the following line:
|
||||
|
||||
options dahdi auto_assign_spans=0
|
||||
|
||||
You will then need to assign the spans manually at device startup. You
|
||||
will need to assign a span number and channel numbers for each
|
||||
available span on the system. On my test system I have one BRI PCI card
|
||||
and one Astribank BRI+FXS:
|
||||
|
||||
# grep . /sys/bus/dahdi_devices/devices/*/spantype
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:1:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:2:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:3:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:4:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:5:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:6:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:7:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:8:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:9:FXS
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:1:TE
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:2:TE
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:3:NT
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:4:NT
|
||||
|
||||
All spans here, except the FXS one, are BRI spans with 3 channels per span.
|
||||
|
||||
In order to assign a span, we write three numbers separated by colns to
|
||||
the file 'assign_span' in the SysFS node
|
||||
|
||||
local_num:span_num:base_chan_num
|
||||
|
||||
Thus:
|
||||
|
||||
echo 9:5:10 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
echo 2:8:40 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
|
||||
echo 1:1:1 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
echo 4:6:20 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
|
||||
echo 3:2:5 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
|
||||
As you can see, the order of span numbers or local span number is
|
||||
insignificant. However the order of channel numbers must be the same as
|
||||
that of span numbers.
|
||||
|
||||
Which indeed produced:
|
||||
|
||||
# head -n3 -q /proc/dahdi/*
|
||||
Span 1: XBUS-00/XPD-00 "Xorcom XPD [usb:LAB-0003].1: BRI_NT"
|
||||
|
||||
1 XPP_BRI_NT/00/00/0
|
||||
Span 2: XBUS-00/XPD-02 "Xorcom XPD [usb:LAB-0003].3: BRI_TE"
|
||||
|
||||
5 XPP_BRI_TE/00/02/0
|
||||
Span 5: XBUS-00/XPD-10 "Xorcom XPD [usb:LAB-0003].9: FXS" (MASTER)
|
||||
|
||||
10 XPP_FXS/00/10/0
|
||||
Span 6: B4/0/4 "B4XXP (PCI) Card 0 Span 4" RED
|
||||
|
||||
23 B4/0/4/1 YELLOW
|
||||
Span 8: B4/0/2 "B4XXP (PCI) Card 0 Span 2" RED
|
||||
|
||||
40 B4/0/2/1 RED
|
||||
|
||||
Likewise spans can be unassigned by writing to the 'unassign-span'
|
||||
"file".
|
||||
|
||||
|
||||
Dynamic Spans
|
||||
~~~~~~~~~~~~~
|
||||
Dynamic spans are spans that are not represented by real hardware.
|
||||
@@ -641,6 +718,103 @@ see an extra '(In use)':
|
||||
2 XPP_FXS/0/0/1 FXOLS (In use)
|
||||
|
||||
|
||||
SysFS Interface
|
||||
~~~~~~~~~~~~~~~
|
||||
DAHDI exposes several interfaces under the SysFS virtual file system.
|
||||
SysFS represents kernel objects in nodes - directories. There properties
|
||||
are often files. They may also contain other nodes or include symlinks
|
||||
to other nodes.
|
||||
|
||||
Class DAHDI
|
||||
^^^^^^^^^^^
|
||||
under /sys/class/dadhi there exists a node for each DAHDI device file
|
||||
under /dev/dahdi. The name is 'dahdi!foo' for the file '/dev/dahdi/foo'
|
||||
(udev translates exclamation marks to slashes). Those nodes are not, for
|
||||
the most part, proper SysFS nodes, and don't include any interesting
|
||||
properties.
|
||||
|
||||
|
||||
Devices Bus
|
||||
^^^^^^^^^^^
|
||||
Each DAHDI device (a physical device, such as a PCI card) is represented
|
||||
by a node under /sys/bus/dahdi_devices/devices named with the name of
|
||||
its device.
|
||||
|
||||
Its attributes include:
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/assgin-span
|
||||
Write-only attribute: this device's spans should now be assigned
|
||||
("registered"). See section about <<_span_assignments>>.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/auto-assign
|
||||
Write-only attribute. Spans in the device auto-assign ("register" as in
|
||||
the original interface). See section about <<_span_assignments>>.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/hardware_id
|
||||
A unique hardware-level identifier (e.g. serial number), if available.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/manufacturer
|
||||
The name of the manufacturer. Freeform-string.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
|
||||
A line for each available span: <num>:<type>. This has to be provided
|
||||
here as in the case of manual assignment, userspace may need to know
|
||||
it before span nodes are created.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
|
||||
Device type.
|
||||
|
||||
===== /sys/bus/dahdi_devices/devices/DEVICE/unassign-span
|
||||
Write-only attribute: the span whose device-local number is written
|
||||
should now be unassigned ("unregistered"). See section about
|
||||
<<_span_assignments>>.
|
||||
|
||||
|
||||
Spans Bus
|
||||
^^^^^^^^^
|
||||
Each DAHDI span is represented by a node under
|
||||
/sys/bus/dahdi_spans/devices with the name 'span-N' (where N is the
|
||||
number of the span). Spans of each device also reside under the node of
|
||||
the device.
|
||||
|
||||
Useful attributes in the span node:
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/alarms
|
||||
The alarms of the span. Currently this is a numeric representation.
|
||||
This may change in the future.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/basechan
|
||||
The channel number of the first channel. The channel numbers of the
|
||||
following channels are guaranteed to follow it.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/channels
|
||||
The number of the channels in the span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/desc
|
||||
A free-form description of the span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/is_digital
|
||||
1 if the span is digital, 0 if it isn't.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/is_sync_master
|
||||
1 if the span is the sync master, 0 if it isn't.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/lbo
|
||||
LBO setting for the channel.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/local_spanno
|
||||
The number of the span within the DAHDI device.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/name
|
||||
A concise name for this span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/spantype
|
||||
A very short type string.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
|
||||
Current sync source.
|
||||
|
||||
|
||||
User-space Interface
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
User-space programs can only work with DAHDI channels. The basic
|
||||
@@ -718,7 +892,7 @@ standard HDLC rate of 64k).
|
||||
Low-Level Drivers
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Low-level drivers create spans ('struct dahdi_span'). They register the
|
||||
spans with the DAHDI core using 'dahdi_register()'.
|
||||
spans with the DAHDI core using 'dahdi_device_register()'.
|
||||
|
||||
'struct dahdi_span' has a number of informative members that are updated
|
||||
solely by the low-level driver:
|
||||
|
||||
@@ -293,6 +293,10 @@ load)
|
||||
# TODO: A local copy of Asterisk, configured with dahdi_gnconf.
|
||||
# doable, but trickier.
|
||||
run_asterisk
|
||||
if [ "$LIVE_DAHDI_FREEPBXDB" = 'yes' ]; then
|
||||
GENCONF_PARAMETERS=$DESTDIR/etc/dahdi/genconf_parameters \
|
||||
dahdi_genconf freepbxdb
|
||||
fi
|
||||
;;
|
||||
genconf)
|
||||
genconf
|
||||
|
||||
@@ -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//"`
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -49,6 +49,305 @@ static struct class_simple *dahdi_class = NULL;
|
||||
#define class_destroy class_simple_destroy
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Very old hotplug support
|
||||
*/
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 9)
|
||||
#define OLD_HOTPLUG_SUPPORT /* for older kernels */
|
||||
#define OLD_HOTPLUG_SUPPORT_269
|
||||
#endif
|
||||
|
||||
#ifdef OLD_HOTPLUG_SUPPORT_269
|
||||
/* Copy from new kernels lib/kobject_uevent.c */
|
||||
enum kobject_action {
|
||||
KOBJ_ADD,
|
||||
KOBJ_REMOVE,
|
||||
KOBJ_CHANGE,
|
||||
KOBJ_MOUNT,
|
||||
KOBJ_UMOUNT,
|
||||
KOBJ_OFFLINE,
|
||||
KOBJ_ONLINE,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hotplug replaced with uevent in 2.6.16
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
|
||||
#define OLD_HOTPLUG_SUPPORT /* for older kernels */
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, struct device_attribute *attr,\
|
||||
char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, struct device_attribute *attr,\
|
||||
const char *buf, size_t count)
|
||||
#define BUS_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, struct device_attribute *attr, \
|
||||
char *buf)
|
||||
#define BUS_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, struct device_attribute *attr,\
|
||||
const char *buf, size_t count)
|
||||
#else
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, const char *buf, size_t count)
|
||||
#define BUS_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, char *buf)
|
||||
#define BUS_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, const char *buf, size_t count)
|
||||
#endif
|
||||
|
||||
#define DRIVER_ATTR_READER(name, drv, buf) \
|
||||
ssize_t name(struct device_driver *drv, char * buf)
|
||||
|
||||
|
||||
static char *initdir = "/usr/share/dahdi";
|
||||
module_param(initdir, charp, 0644);
|
||||
|
||||
static int span_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline struct dahdi_span *dev_to_span(struct device *dev)
|
||||
{
|
||||
return dev_get_drvdata(dev);
|
||||
}
|
||||
|
||||
#ifdef OLD_HOTPLUG_SUPPORT
|
||||
static int span_hotplug(struct device *dev, char **envp, int envnum,
|
||||
char *buff, int bufsize)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
span = dev_to_span(dev);
|
||||
envp[0] = buff;
|
||||
if (snprintf(buff, bufsize, "SPAN_NAME=%s", span->name) >= bufsize)
|
||||
return -ENOMEM;
|
||||
envp[1] = NULL;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
#define SPAN_VAR_BLOCK \
|
||||
do { \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
|
||||
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
|
||||
} while (0)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(envp, num_envp, &i, \
|
||||
buffer, buffer_size, &len, \
|
||||
fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int span_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int i = 0;
|
||||
int len = 0;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
if (!span)
|
||||
return -ENODEV;
|
||||
|
||||
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
|
||||
dev_name(dev), span->name);
|
||||
SPAN_VAR_BLOCK;
|
||||
envp[i] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(kenv, fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int span_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
span = dev_to_span(dev);
|
||||
if (!span)
|
||||
return -ENODEV;
|
||||
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
|
||||
dev_name(dev), span->name);
|
||||
SPAN_VAR_BLOCK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* OLD_HOTPLUG_SUPPORT */
|
||||
|
||||
#define span_attr(field, format_string) \
|
||||
static BUS_ATTR_READER(field##_show, dev, buf) \
|
||||
{ \
|
||||
struct dahdi_span *span; \
|
||||
\
|
||||
span = dev_to_span(dev); \
|
||||
return sprintf(buf, format_string, span->field); \
|
||||
}
|
||||
|
||||
span_attr(name, "%s\n");
|
||||
span_attr(desc, "%s\n");
|
||||
span_attr(spantype, "%s\n");
|
||||
span_attr(alarms, "0x%x\n");
|
||||
span_attr(lbo, "%d\n");
|
||||
span_attr(syncsrc, "%d\n");
|
||||
|
||||
static BUS_ATTR_READER(local_spanno_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
return sprintf(buf, "%d\n", local_spanno(span));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(is_digital_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
return sprintf(buf, "%d\n", dahdi_is_digital_span(span));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(is_sync_master_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
return sprintf(buf, "%d\n", dahdi_is_sync_master(span));
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(basechan_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
return sprintf(buf, "%d\n", span->chans[0]->channo);
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(channels_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
return sprintf(buf, "%d\n", span->channels);
|
||||
}
|
||||
|
||||
static struct device_attribute span_dev_attrs[] = {
|
||||
__ATTR_RO(name),
|
||||
__ATTR_RO(desc),
|
||||
__ATTR_RO(spantype),
|
||||
__ATTR_RO(local_spanno),
|
||||
__ATTR_RO(alarms),
|
||||
__ATTR_RO(lbo),
|
||||
__ATTR_RO(syncsrc),
|
||||
__ATTR_RO(is_digital),
|
||||
__ATTR_RO(is_sync_master),
|
||||
__ATTR_RO(basechan),
|
||||
__ATTR_RO(channels),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct driver_attribute dahdi_attrs[] = {
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct bus_type spans_bus_type = {
|
||||
.name = "dahdi_spans",
|
||||
.match = span_match,
|
||||
#ifdef OLD_HOTPLUG_SUPPORT
|
||||
.hotplug = span_hotplug,
|
||||
#else
|
||||
.uevent = span_uevent,
|
||||
#endif
|
||||
.dev_attrs = span_dev_attrs,
|
||||
.drv_attrs = dahdi_attrs,
|
||||
};
|
||||
|
||||
static int span_probe(struct device *dev)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
span_dbg(DEVICES, span, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int span_remove(struct device *dev)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
span_dbg(DEVICES, span, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver dahdi_driver = {
|
||||
.name = "generic_lowlevel",
|
||||
.bus = &spans_bus_type,
|
||||
.probe = span_probe,
|
||||
.remove = span_remove,
|
||||
#ifndef OLD_HOTPLUG_SUPPORT
|
||||
.owner = THIS_MODULE
|
||||
#endif
|
||||
};
|
||||
|
||||
static void span_uevent_send(struct dahdi_span *span, enum kobject_action act)
|
||||
{
|
||||
struct kobject *kobj;
|
||||
|
||||
kobj = &span->span_device->kobj;
|
||||
span_dbg(DEVICES, span, "SYFS dev_name=%s action=%d\n",
|
||||
dev_name(span->span_device), act);
|
||||
|
||||
#if defined(OLD_HOTPLUG_SUPPORT_269)
|
||||
{
|
||||
/* Copy from new kernels lib/kobject_uevent.c */
|
||||
static const char *const str[] = {
|
||||
[KOBJ_ADD] "add",
|
||||
[KOBJ_REMOVE] "remove",
|
||||
[KOBJ_CHANGE] "change",
|
||||
[KOBJ_MOUNT] "mount",
|
||||
[KOBJ_UMOUNT] "umount",
|
||||
[KOBJ_OFFLINE] "offline",
|
||||
[KOBJ_ONLINE] "online"
|
||||
};
|
||||
kobject_hotplug(str[act], kobj);
|
||||
}
|
||||
#elif defined(OLD_HOTPLUG_SUPPORT)
|
||||
kobject_hotplug(kobj, act);
|
||||
#else
|
||||
kobject_uevent(kobj, act);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void span_release(struct device *dev)
|
||||
{
|
||||
dahdi_dbg(DEVICES, "%s: %s\n", __func__, dev_name(dev));
|
||||
}
|
||||
|
||||
int dahdi_register_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
@@ -78,7 +377,15 @@ EXPORT_SYMBOL(dahdi_unregister_chardev);
|
||||
|
||||
void span_sysfs_remove(struct dahdi_span *span)
|
||||
{
|
||||
struct device *span_device;
|
||||
int x;
|
||||
|
||||
span_dbg(DEVICES, span, "\n");
|
||||
span_device = span->span_device;
|
||||
|
||||
if (!span_device)
|
||||
return;
|
||||
|
||||
for (x = 0; x < span->channels; x++) {
|
||||
struct dahdi_chan *chan = span->chans[x];
|
||||
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
@@ -88,13 +395,55 @@ void span_sysfs_remove(struct dahdi_span *span)
|
||||
MKDEV(DAHDI_MAJOR, chan->channo));
|
||||
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
}
|
||||
if (!dev_get_drvdata(span_device))
|
||||
return;
|
||||
|
||||
/* Grab an extra reference to the device since we'll still want it
|
||||
* after we've unregistered it */
|
||||
|
||||
get_device(span_device);
|
||||
span_uevent_send(span, KOBJ_OFFLINE);
|
||||
device_unregister(span->span_device);
|
||||
dev_set_drvdata(span_device, NULL);
|
||||
span_device->parent = NULL;
|
||||
put_device(span_device);
|
||||
memset(&span->span_device, 0, sizeof(span->span_device));
|
||||
kfree(span->span_device);
|
||||
span->span_device = NULL;
|
||||
}
|
||||
|
||||
int span_sysfs_create(struct dahdi_span *span)
|
||||
{
|
||||
struct device *span_device;
|
||||
int res = 0;
|
||||
int x;
|
||||
|
||||
if (span->span_device) {
|
||||
WARN_ON(1);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
span->span_device = kzalloc(sizeof(*span->span_device), GFP_KERNEL);
|
||||
if (!span->span_device)
|
||||
return -ENOMEM;
|
||||
|
||||
span_device = span->span_device;
|
||||
span_dbg(DEVICES, span, "\n");
|
||||
|
||||
span_device->bus = &spans_bus_type;
|
||||
span_device->parent = &span->parent->dev;
|
||||
dev_set_name(span_device, "span-%d", span->spanno);
|
||||
dev_set_drvdata(span_device, span);
|
||||
span_device->release = span_release;
|
||||
res = device_register(span_device);
|
||||
if (res) {
|
||||
span_err(span, "%s: device_register failed: %d\n", __func__,
|
||||
res);
|
||||
kfree(span->span_device);
|
||||
span->span_device = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (x = 0; x < span->channels; x++) {
|
||||
struct dahdi_chan *chan = span->chans[x];
|
||||
char chan_name[32];
|
||||
@@ -137,10 +486,248 @@ static struct {
|
||||
unsigned int timer:1;
|
||||
unsigned int channel:1;
|
||||
unsigned int pseudo:1;
|
||||
unsigned int sysfs_driver_registered:1;
|
||||
unsigned int sysfs_spans_bus_type:1;
|
||||
unsigned int dahdi_device_bus_registered:1;
|
||||
} dummy_dev;
|
||||
|
||||
static inline struct dahdi_device *to_ddev(struct device *dev)
|
||||
{
|
||||
return container_of(dev, struct dahdi_device, dev);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t dahdi_device_manufacturer_show(struct device *dev, char *buf)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_manufacturer_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
return sprintf(buf, "%s\n", ddev->manufacturer);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t dahdi_device_type_show(struct device *dev, char *buf)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
return sprintf(buf, "%s\n", ddev->devicetype);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t dahdi_device_span_count_show(struct device *dev, char *buf)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_span_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
unsigned int count = 0;
|
||||
struct list_head *pos;
|
||||
|
||||
list_for_each(pos, &ddev->spans)
|
||||
++count;
|
||||
|
||||
return sprintf(buf, "%d\n", count);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t dahdi_device_hardware_id_show(struct device *dev, char *buf)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_hardware_id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
(ddev->hardware_id) ? ddev->hardware_id : "");
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t
|
||||
dahdi_device_auto_assign(struct device *dev, const char *buf, size_t count)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
dahdi_assign_device_spans(ddev);
|
||||
return count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t
|
||||
dahdi_device_assign_span(struct device *dev, const char *buf, size_t count)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
struct dahdi_span *span;
|
||||
unsigned int local_span_number;
|
||||
unsigned int desired_spanno;
|
||||
unsigned int desired_basechanno;
|
||||
struct dahdi_device *const ddev = to_ddev(dev);
|
||||
|
||||
ret = sscanf(buf, "%u:%u:%u", &local_span_number, &desired_spanno,
|
||||
&desired_basechanno);
|
||||
if (ret != 3) {
|
||||
dev_notice(dev, "badly formatted input (should be <num>:<num>:<num>)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (desired_spanno && !desired_basechanno) {
|
||||
dev_notice(dev, "Must set span number AND base chan number\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(span, &ddev->spans, device_node) {
|
||||
if (local_span_number == local_spanno(span)) {
|
||||
ret = dahdi_assign_span(span, desired_spanno,
|
||||
desired_basechanno, 1);
|
||||
return (ret) ? ret : count;
|
||||
}
|
||||
}
|
||||
dev_notice(dev, "no match for local span number %d\n", local_span_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t
|
||||
dahdi_device_unassign_span(struct device *dev, const char *buf, size_t count)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
unsigned int local_span_number;
|
||||
struct dahdi_span *span;
|
||||
struct dahdi_device *const ddev = to_ddev(dev);
|
||||
|
||||
ret = sscanf(buf, "%u", &local_span_number);
|
||||
if (ret != 1)
|
||||
return -EINVAL;
|
||||
|
||||
ret = -ENODEV;
|
||||
list_for_each_entry(span, &ddev->spans, device_node) {
|
||||
if (local_span_number == local_spanno(span))
|
||||
ret = dahdi_unassign_span(span);
|
||||
}
|
||||
if (-ENODEV == ret) {
|
||||
if (printk_ratelimit()) {
|
||||
dev_info(dev, "'%d' is an invalid local span number.\n",
|
||||
local_span_number);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
return (ret < 0) ? ret : count;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t dahdi_spantype_show(struct device *dev, char *buf)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_spantype_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
int count = 0;
|
||||
ssize_t total = 0;
|
||||
struct dahdi_span *span;
|
||||
|
||||
/* TODO: Make sure this doesn't overflow the page. */
|
||||
list_for_each_entry(span, &ddev->spans, device_node) {
|
||||
count = sprintf(buf, "%d:%s\n", local_spanno(span), span->spantype);
|
||||
buf += count;
|
||||
total += count;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
|
||||
static ssize_t
|
||||
dahdi_spantype_store(struct device *dev, const char *buf, size_t count)
|
||||
#else
|
||||
static ssize_t
|
||||
dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_device *const ddev = to_ddev(dev);
|
||||
int ret;
|
||||
struct dahdi_span *span;
|
||||
unsigned int local_span_number;
|
||||
char desired_spantype[80];
|
||||
|
||||
ret = sscanf(buf, "%u:%70s", &local_span_number, desired_spantype);
|
||||
if (ret != 2)
|
||||
return -EINVAL;
|
||||
|
||||
list_for_each_entry(span, &ddev->spans, device_node) {
|
||||
if (local_spanno(span) == local_span_number)
|
||||
break;
|
||||
}
|
||||
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
|
||||
module_printk(KERN_WARNING, "Span %s is already assigned.\n",
|
||||
span->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (local_spanno(span) != local_span_number) {
|
||||
module_printk(KERN_WARNING, "%d is not a valid local span number "
|
||||
"for this device.\n", local_span_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!span->ops->set_spantype) {
|
||||
module_printk(KERN_WARNING, "Span %s does not support "
|
||||
"setting type.\n", span->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = span->ops->set_spantype(span, &desired_spantype[0]);
|
||||
return (ret < 0) ? ret : count;
|
||||
}
|
||||
|
||||
static struct device_attribute dahdi_device_attrs[] = {
|
||||
__ATTR(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
|
||||
__ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
|
||||
__ATTR(span_count, S_IRUGO, dahdi_device_span_count_show, NULL),
|
||||
__ATTR(hardware_id, S_IRUGO, dahdi_device_hardware_id_show, NULL),
|
||||
__ATTR(auto_assign, S_IWUSR, NULL, dahdi_device_auto_assign),
|
||||
__ATTR(assign_span, S_IWUSR, NULL, dahdi_device_assign_span),
|
||||
__ATTR(unassign_span, S_IWUSR, NULL, dahdi_device_unassign_span),
|
||||
__ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
|
||||
dahdi_spantype_store),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct bus_type dahdi_device_bus = {
|
||||
.name = "dahdi_devices",
|
||||
.dev_attrs = dahdi_device_attrs,
|
||||
};
|
||||
|
||||
void dahdi_sysfs_exit(void)
|
||||
{
|
||||
dahdi_dbg(DEVICES, "SYSFS\n");
|
||||
if (dummy_dev.pseudo) {
|
||||
dahdi_dbg(DEVICES, "Removing /dev/dahdi/pseudo:\n");
|
||||
DEL_DAHDI_DEV(DAHDI_PSEUDO);
|
||||
@@ -166,7 +753,67 @@ void dahdi_sysfs_exit(void)
|
||||
class_destroy(dahdi_class);
|
||||
dahdi_class = NULL;
|
||||
}
|
||||
if (dummy_dev.sysfs_driver_registered) {
|
||||
dahdi_dbg(DEVICES, "Unregister driver\n");
|
||||
driver_unregister(&dahdi_driver);
|
||||
dummy_dev.sysfs_driver_registered = 0;
|
||||
}
|
||||
if (dummy_dev.sysfs_spans_bus_type) {
|
||||
dahdi_dbg(DEVICES, "Unregister span bus type\n");
|
||||
bus_unregister(&spans_bus_type);
|
||||
dummy_dev.sysfs_spans_bus_type = 0;
|
||||
}
|
||||
unregister_chrdev(DAHDI_MAJOR, "dahdi");
|
||||
|
||||
if (dummy_dev.dahdi_device_bus_registered) {
|
||||
bus_unregister(&dahdi_device_bus);
|
||||
dummy_dev.dahdi_device_bus_registered = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dahdi_device_release(struct device *dev)
|
||||
{
|
||||
struct dahdi_device *ddev = container_of(dev, struct dahdi_device, dev);
|
||||
kfree(ddev);
|
||||
}
|
||||
|
||||
/**
|
||||
* dahdi_sysfs_add_device - Add the dahdi_device into the sysfs hierarchy.
|
||||
* @ddev: The device to add.
|
||||
* @parent: The physical device that is implementing this device.
|
||||
*
|
||||
* By adding the dahdi_device to the sysfs hierarchy user space can control
|
||||
* how spans are numbered.
|
||||
*
|
||||
*/
|
||||
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent)
|
||||
{
|
||||
int ret;
|
||||
struct device *const dev = &ddev->dev;
|
||||
const char *dn;
|
||||
|
||||
dev->parent = parent;
|
||||
dev->bus = &dahdi_device_bus;
|
||||
dn = dev_name(dev);
|
||||
if (!dn || !*dn) {
|
||||
/* Invent default name based on parent */
|
||||
if (!parent)
|
||||
return -EINVAL;
|
||||
dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent));
|
||||
}
|
||||
ret = device_add(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_init_device(struct dahdi_device *ddev)
|
||||
{
|
||||
device_initialize(&ddev->dev);
|
||||
ddev->dev.release = dahdi_device_release;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev)
|
||||
{
|
||||
device_del(&ddev->dev);
|
||||
}
|
||||
|
||||
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
|
||||
@@ -174,6 +821,12 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
|
||||
int res = 0;
|
||||
void *dev;
|
||||
|
||||
res = bus_register(&dahdi_device_bus);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
dummy_dev.dahdi_device_bus_registered = 1;
|
||||
|
||||
res = register_chrdev(DAHDI_MAJOR, "dahdi", dahdi_fops);
|
||||
if (res) {
|
||||
module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR);
|
||||
@@ -220,6 +873,20 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.ctl = 1;
|
||||
res = bus_register(&spans_bus_type);
|
||||
if (res != 0) {
|
||||
dahdi_err("%s: bus_register(%s) failed. Error number %d",
|
||||
__func__, spans_bus_type.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.sysfs_spans_bus_type = 1;
|
||||
res = driver_register(&dahdi_driver);
|
||||
if (res < 0) {
|
||||
dahdi_err("%s: driver_register(%s) failed. Error number %d",
|
||||
__func__, dahdi_driver.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.sysfs_driver_registered = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -34,4 +34,28 @@ void span_sysfs_remove(struct dahdi_span *span);
|
||||
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops);
|
||||
void dahdi_sysfs_exit(void);
|
||||
|
||||
void dahdi_sysfs_init_device(struct dahdi_device *ddev);
|
||||
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent);
|
||||
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev);
|
||||
|
||||
int dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
|
||||
unsigned int basechan, int prefmaster);
|
||||
int dahdi_unassign_span(struct dahdi_span *span);
|
||||
int dahdi_assign_device_spans(struct dahdi_device *ddev);
|
||||
|
||||
static inline int get_span(struct dahdi_span *span)
|
||||
{
|
||||
return try_module_get(span->ops->owner);
|
||||
}
|
||||
|
||||
static inline void put_span(struct dahdi_span *span)
|
||||
{
|
||||
module_put(span->ops->owner);
|
||||
}
|
||||
|
||||
static inline int local_spanno(struct dahdi_span *span)
|
||||
{
|
||||
return span->offset + 1;
|
||||
}
|
||||
|
||||
#endif /* _DAHDI_H */
|
||||
|
||||
@@ -75,6 +75,7 @@ static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
|
||||
#endif
|
||||
|
||||
struct dahdi_dummy {
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan _chan;
|
||||
struct dahdi_chan *chan;
|
||||
@@ -205,37 +206,44 @@ static const struct dahdi_span_ops dummy_ops = {
|
||||
|
||||
static int dahdi_dummy_initialize(struct dahdi_dummy *ztd)
|
||||
{
|
||||
int res = 0;
|
||||
/* DAHDI stuff */
|
||||
ztd->ddev = dahdi_create_device();
|
||||
if (!ztd->ddev)
|
||||
return -ENOMEM;
|
||||
dev_set_name(&ztd->ddev->dev, "dahdi_dummy");
|
||||
ztd->chan = &ztd->_chan;
|
||||
sprintf(ztd->span.name, "DAHDI_DUMMY/1");
|
||||
snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1);
|
||||
sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0);
|
||||
strlcpy(ztd->span.devicetype, "DAHDI Dummy Timing",
|
||||
sizeof(ztd->span.devicetype));
|
||||
ztd->ddev->devicetype = "DAHDI Dummy Timing";
|
||||
ztd->chan->chanpos = 1;
|
||||
ztd->span.chans = &ztd->chan;
|
||||
ztd->span.channels = 0; /* no channels on our span */
|
||||
ztd->span.deflaw = DAHDI_LAW_MULAW;
|
||||
ztd->chan->pvt = ztd;
|
||||
ztd->span.ops = &dummy_ops;
|
||||
if (dahdi_register(&ztd->span, 0)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
list_add_tail(&ztd->span.device_node, &ztd->ddev->spans);
|
||||
res = dahdi_register_device(ztd->ddev, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int res;
|
||||
ztd = kzalloc(sizeof(*ztd), GFP_KERNEL);
|
||||
if (ztd == NULL) {
|
||||
printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (dahdi_dummy_initialize(ztd)) {
|
||||
printk(KERN_ERR "dahdi_dummy: Unable to intialize DAHDI driver\n");
|
||||
res = dahdi_dummy_initialize(ztd);
|
||||
if (res) {
|
||||
printk(KERN_ERR
|
||||
"dahdi_dummy: Unable to intialize DAHDI driver (%d)\n",
|
||||
res);
|
||||
kfree(ztd);
|
||||
return -ENODEV;
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(USE_HIGHRESTIMER)
|
||||
@@ -273,7 +281,8 @@ void cleanup_module(void)
|
||||
atomic_set(&shutdown, 1);
|
||||
del_timer_sync(&timer);
|
||||
#endif
|
||||
dahdi_unregister(&ztd->span);
|
||||
dahdi_unregister_device(ztd->ddev);
|
||||
dahdi_free_device(ztd->ddev);
|
||||
kfree(ztd);
|
||||
if (debug)
|
||||
printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n");
|
||||
|
||||
@@ -385,21 +385,12 @@ static void dahdi_dynamic_release(struct kref *kref)
|
||||
|
||||
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
|
||||
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
__module_get(d->driver->owner);
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(d->msgbuf);
|
||||
|
||||
for (x = 0; x < d->span.channels; x++)
|
||||
kfree(d->chans[x]);
|
||||
|
||||
dahdi_free_device(d->ddev);
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
@@ -469,7 +460,25 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dahdi_unregister(&d->span);
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
if (!try_module_get(d->driver->owner)) {
|
||||
/* The driver for this device is in the
|
||||
* process of unloading. Leave this dynamic on
|
||||
* the list so it's cleaned up when the driver
|
||||
* unregisters. */
|
||||
dynamic_put(d);
|
||||
return -ENXIO;
|
||||
}
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
d->pvt = NULL;
|
||||
}
|
||||
|
||||
dahdi_unregister_device(d->ddev);
|
||||
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
@@ -578,8 +587,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
kref_init(&d->kref);
|
||||
d->ddev = dahdi_create_device();
|
||||
|
||||
for (x = 0; x < dds->numchans; x++) {
|
||||
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
||||
@@ -604,9 +613,10 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
strlcpy(d->dname, dds->driver, sizeof(d->dname));
|
||||
strlcpy(d->addr, dds->addr, sizeof(d->addr));
|
||||
d->timing = dds->timing;
|
||||
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
|
||||
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
|
||||
dds->driver, dds->addr);
|
||||
snprintf(d->span.name, sizeof(d->span.name), "DYN/%s/%s",
|
||||
dds->driver, dds->addr);
|
||||
snprintf(d->span.desc, sizeof(d->span.desc),
|
||||
"Dynamic '%s' span at '%s'", dds->driver, dds->addr);
|
||||
d->span.deflaw = DAHDI_LAW_MULAW;
|
||||
d->span.flags |= DAHDI_FLAG_RBS;
|
||||
d->span.chans = d->chans;
|
||||
@@ -657,8 +667,12 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return res;
|
||||
}
|
||||
|
||||
d->ddev->devicetype = d->span.name;
|
||||
d->ddev->hardware_id = d->span.name;
|
||||
dev_set_name(&d->ddev->dev, "dynamic:%s:%d", dds->driver, dtd->id++);
|
||||
list_add_tail(&d->span.device_node, &d->ddev->spans);
|
||||
/* Whee! We're created. Now register the span */
|
||||
if (dahdi_register(&d->span, 0)) {
|
||||
if (dahdi_register_device(d->ddev, d->dev)) {
|
||||
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
||||
d->span.name);
|
||||
dynamic_put(d);
|
||||
@@ -761,19 +775,17 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
|
||||
list_for_each_entry_safe(d, n, &dspan_list, list) {
|
||||
if (d->driver == dri) {
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
__module_get(d->driver->owner);
|
||||
if (d->driver && d->driver->destroy)
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
else
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
dahdi_unregister(&d->span);
|
||||
dahdi_unregister_device(d->ddev);
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||
synchronize_rcu();
|
||||
d->driver = NULL;
|
||||
dynamic_put(d);
|
||||
}
|
||||
}
|
||||
@@ -817,10 +829,13 @@ static void check_for_red_alarm(unsigned long ignored)
|
||||
mod_timer(&alarmcheck, jiffies + 1 * HZ);
|
||||
}
|
||||
|
||||
static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = dahdi_dynamic_ioctl,
|
||||
};
|
||||
|
||||
static int dahdi_dynamic_init(void)
|
||||
{
|
||||
dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl);
|
||||
|
||||
/* Start process to check for RED ALARM */
|
||||
init_timer(&alarmcheck);
|
||||
alarmcheck.expires = 0;
|
||||
@@ -831,19 +846,25 @@ static int dahdi_dynamic_init(void)
|
||||
#ifdef ENABLE_TASKLETS
|
||||
tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
|
||||
#endif
|
||||
dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
|
||||
|
||||
printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dahdi_dynamic_cleanup(void)
|
||||
{
|
||||
dahdi_set_dynamic_ops(NULL);
|
||||
|
||||
#ifdef ENABLE_TASKLETS
|
||||
if (taskletpending) {
|
||||
tasklet_disable(&dahdi_dynamic_tlet);
|
||||
tasklet_kill(&dahdi_dynamic_tlet);
|
||||
}
|
||||
#endif
|
||||
dahdi_set_dynamic_ioctl(NULL);
|
||||
del_timer_sync(&alarmcheck);
|
||||
/* Must call again in case it was running before and rescheduled
|
||||
* itself. */
|
||||
del_timer(&alarmcheck);
|
||||
printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n");
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short sub
|
||||
if (z)
|
||||
span = z->span;
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
|
||||
return NULL;
|
||||
return span;
|
||||
}
|
||||
|
||||
@@ -152,7 +154,7 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
|
||||
spin_lock_irqsave(&zlock, flags);
|
||||
z = dyn->pvt;
|
||||
if (z->dev) {
|
||||
if (z && z->dev) {
|
||||
/* Copy fields to local variables to remove spinlock ASAP */
|
||||
dev = z->dev;
|
||||
memcpy(addr, z->addr, sizeof(z->addr));
|
||||
@@ -191,15 +193,44 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
|
||||
static int ztdeth_flush(void)
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static int ztdeth_flush(void)
|
||||
{
|
||||
schedule_work(&dahdi_dynamic_eth_flush_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -284,11 +315,12 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
if (cur == z) { /* Successfully removed */
|
||||
dyn->pvt = NULL;
|
||||
printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
|
||||
kfree(z);
|
||||
}
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
|
||||
@@ -411,20 +443,27 @@ static struct notifier_block ztdeth_nblock = {
|
||||
|
||||
static int __init ztdeth_init(void)
|
||||
{
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
dev_add_pack(&ztdeth_ptype);
|
||||
register_netdevice_notifier(&ztdeth_nblock);
|
||||
dahdi_dynamic_register_driver(&ztd_eth);
|
||||
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ztdeth_exit(void)
|
||||
{
|
||||
dev_remove_pack(&ztdeth_ptype);
|
||||
unregister_netdevice_notifier(&ztdeth_nblock);
|
||||
#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);
|
||||
|
||||
skb_queue_purge(&skbs);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support");
|
||||
|
||||
@@ -78,10 +78,11 @@ static LIST_HEAD(dynamic_local_list);
|
||||
static void
|
||||
dahdi_dynamic_local_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
{
|
||||
struct dahdi_dynamic_local *const d = dyn->pvt;
|
||||
struct dahdi_dynamic_local *d;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&local_lock, flags);
|
||||
d = dyn->pvt;
|
||||
if (d && d->peer && d->peer->span) {
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->peer->span->flags))
|
||||
dahdi_dynamic_receive(d->peer->span, msg, msglen);
|
||||
@@ -130,11 +131,12 @@ static int digit2int(char d)
|
||||
|
||||
static void dahdi_dynamic_local_destroy(struct dahdi_dynamic *dyn)
|
||||
{
|
||||
struct dahdi_dynamic_local *d = dyn->pvt;
|
||||
struct dahdi_dynamic_local *d;
|
||||
unsigned long flags;
|
||||
struct dahdi_dynamic_local *cur;
|
||||
|
||||
spin_lock_irqsave(&local_lock, flags);
|
||||
d = dyn->pvt;
|
||||
list_for_each_entry(cur, &dynamic_local_list, node) {
|
||||
if (cur->peer == d)
|
||||
cur->peer = NULL;
|
||||
|
||||
@@ -24,14 +24,16 @@
|
||||
|
||||
OCT6114_064_VERSION:=1.05.01
|
||||
OCT6114_128_VERSION:=1.05.01
|
||||
OCT6114_256_VERSION:=1.05.01
|
||||
TC400M_VERSION:=MR6.12
|
||||
VPMADT032_VERSION:=1.25.0
|
||||
HX8_VERSION:=2.06
|
||||
VPMOCT032_VERSION:=1.11.0
|
||||
VPMOCT032_VERSION:=1.12.0
|
||||
WCT820_VERSION:=1.76
|
||||
|
||||
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
|
||||
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820
|
||||
|
||||
# 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,15 +44,18 @@ ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-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:=$(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)
|
||||
|
||||
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-064=dahdi-fw-oct6114-064.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-HX8=dahdi-fw-hx8.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
|
||||
@@ -124,6 +129,17 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-12
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-128.bin is already installed with required version $(OCT6114_128_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-oct6114-256.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
|
||||
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-oct6114-256.bin is already installed with required version $(OCT6114_256_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-tc400m.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@@ -157,6 +173,17 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-
|
||||
else
|
||||
@echo "Firmware dahdi-fw-vpmoct032.bin is already installed with required version $(VPMOCT032_VERSION)"
|
||||
endif
|
||||
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
|
||||
@echo "Installing dahdi-fw-te820.bin to hotplug firmware directories"
|
||||
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/usr/lib/hotplug/firmware
|
||||
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-*
|
||||
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
|
||||
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/lib/firmware
|
||||
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te820-*
|
||||
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
|
||||
else
|
||||
@echo "Firmware dahdi-fw-te820.bin is already installed with required version $(WCT820_VERSION)"
|
||||
endif
|
||||
|
||||
# Uninstall any installed dahdi firmware images from hotplug firmware directories
|
||||
hotplug-uninstall:
|
||||
@@ -185,6 +212,11 @@ dahdi-fw-oct6114-128.o: dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz dahdi
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-128.bin
|
||||
./make_firmware_object dahdi-fw-oct6114-128.bin $@
|
||||
|
||||
# Build object file of an oct6114 256 firmware image for linking
|
||||
dahdi-fw-oct6114-256.o: dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz dahdi-fw-oct6114-256.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-oct6114-256.bin
|
||||
./make_firmware_object dahdi-fw-oct6114-256.bin $@
|
||||
|
||||
# Build object file of a TC400M firmware image for linking
|
||||
dahdi-fw-tc400m.o: dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz dahdi-fw-tc400m.bin make_firmware_object
|
||||
@echo Making firmware object file for dahdi-fw-tc400m.bin
|
||||
|
||||
@@ -397,7 +397,7 @@ $Octasic_Revision: 171 $
|
||||
|
||||
/* Max defines.*/
|
||||
#ifndef cOCT6100_MAX_ECHO_CHANNELS
|
||||
#define cOCT6100_MAX_ECHO_CHANNELS 128
|
||||
#define cOCT6100_MAX_ECHO_CHANNELS 256
|
||||
#endif
|
||||
#define cOCT6100_MAX_TSI_CNCTS 1530
|
||||
#define cOCT6100_MAX_CALLER_ID_PLAYOUT_BUFFERS ( 3328 + 6 )
|
||||
|
||||
@@ -146,6 +146,7 @@ struct encdec
|
||||
|
||||
struct pciradio {
|
||||
struct pci_dev *dev;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
unsigned char ios;
|
||||
int usecount;
|
||||
@@ -1488,7 +1489,7 @@ static int pciradio_initialize(struct pciradio *rad)
|
||||
rad->span.flags = DAHDI_FLAG_RBS;
|
||||
rad->span.ops = &pciradio_span_ops;
|
||||
|
||||
if (dahdi_register(&rad->span, 0)) {
|
||||
if (dahdi_register_device(rad->ddev, &rad->dev->dev)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1777,7 +1778,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
|
||||
release_region(rad->ioaddr, 0xff);
|
||||
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
dahdi_unregister(&rad->span);
|
||||
dahdi_free_device(rad->ddev);
|
||||
kfree(rad);
|
||||
return -EIO;
|
||||
|
||||
@@ -1810,7 +1811,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
|
||||
|
||||
static void pciradio_release(struct pciradio *rad)
|
||||
{
|
||||
dahdi_unregister(&rad->span);
|
||||
dahdi_unregister_device(rad->ddev);
|
||||
if (rad->freeregion)
|
||||
release_region(rad->ioaddr, 0xff);
|
||||
kfree(rad);
|
||||
|
||||
@@ -97,6 +97,7 @@ struct tor2 {
|
||||
unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */
|
||||
unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */
|
||||
__iomem volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */
|
||||
struct dahdi_device *ddev;
|
||||
struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */
|
||||
struct dahdi_chan **chans[SPANS_PER_CARD]; /* Pointers to card channels */
|
||||
struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */
|
||||
@@ -285,10 +286,6 @@ static void init_spans(struct tor2 *tor)
|
||||
snprintf(s->desc, sizeof(s->desc) - 1,
|
||||
"Tormenta 2 (PCI) Quad %s Card %d Span %d",
|
||||
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
|
||||
s->manufacturer = "Digium";
|
||||
strlcpy(s->devicetype, tor->type, sizeof(s->devicetype));
|
||||
snprintf(s->location, sizeof(s->location) - 1,
|
||||
"PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1);
|
||||
if (tor->cardtype == TYPE_T1) {
|
||||
s->channels = 24;
|
||||
s->deflaw = DAHDI_LAW_MULAW;
|
||||
@@ -322,19 +319,31 @@ static void init_spans(struct tor2 *tor)
|
||||
|
||||
static int __devinit tor2_launch(struct tor2 *tor)
|
||||
{
|
||||
int res;
|
||||
struct dahdi_span *s;
|
||||
int i;
|
||||
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->tspans[0].dahdi_span.flags))
|
||||
return 0;
|
||||
|
||||
tor->ddev = dahdi_create_device();
|
||||
tor->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||
tor->pci->bus->number,
|
||||
PCI_SLOT(tor->pci->devfn) + 1);
|
||||
|
||||
if (!tor->ddev->location)
|
||||
return -ENOMEM;
|
||||
|
||||
printk(KERN_INFO "Tor2: Launching card: %d\n", tor->order);
|
||||
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
||||
s = &tor->tspans[i].dahdi_span;
|
||||
if (dahdi_register(s, 0)) {
|
||||
printk(KERN_ERR "Unable to register span %s\n", s->name);
|
||||
goto error_exit;
|
||||
}
|
||||
list_add_tail(&s->device_node, &tor->ddev->spans);
|
||||
}
|
||||
|
||||
res = dahdi_register_device(tor->ddev, &tor->pci->dev);
|
||||
if (res) {
|
||||
dev_err(&tor->pci->dev, "Unable to register with DAHDI.\n");
|
||||
return res;
|
||||
}
|
||||
writew(PLX_INTENA, &tor->plx[INTCSR]); /* enable PLX interrupt */
|
||||
|
||||
@@ -342,14 +351,6 @@ static int __devinit tor2_launch(struct tor2 *tor)
|
||||
tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
error_exit:
|
||||
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
||||
s = &tor->tspans[i].dahdi_span;
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
|
||||
dahdi_unregister(s);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void free_tor(struct tor2 *tor)
|
||||
@@ -365,6 +366,8 @@ static void free_tor(struct tor2 *tor)
|
||||
if (tor->chans[x])
|
||||
kfree(tor->chans[x]);
|
||||
}
|
||||
kfree(tor->ddev->location);
|
||||
dahdi_free_device(tor->ddev);
|
||||
kfree(tor);
|
||||
}
|
||||
|
||||
@@ -631,7 +634,6 @@ static struct pci_driver tor2_driver;
|
||||
static void __devexit tor2_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct tor2 *tor;
|
||||
int i;
|
||||
|
||||
tor = pci_get_drvdata(pdev);
|
||||
if (!tor)
|
||||
@@ -641,11 +643,7 @@ static void __devexit tor2_remove(struct pci_dev *pdev)
|
||||
writeb(0, &tor->mem8[LEDREG]);
|
||||
writew(0, &tor->plx[INTCSR]);
|
||||
free_irq(tor->irq, tor);
|
||||
for (i = 0; i < SPANS_PER_CARD; ++i) {
|
||||
struct dahdi_span *s = &tor->tspans[i].dahdi_span;
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
|
||||
dahdi_unregister(s);
|
||||
}
|
||||
dahdi_unregister_device(tor->ddev);
|
||||
release_mem_region(tor->plx_region, tor->plx_len);
|
||||
release_mem_region(tor->xilinx32_region, tor->xilinx32_len);
|
||||
release_mem_region(tor->xilinx8_region, tor->xilinx8_len);
|
||||
|
||||
@@ -126,8 +126,8 @@ static int vpmadt032_getreg_full_return(struct vpmadt032 *vpm, int pagechange,
|
||||
unsigned long ret;
|
||||
BUG_ON(!cmd);
|
||||
|
||||
/* We'll wait for 200ms */
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ/5);
|
||||
/* We'll wait for 2s */
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ*2);
|
||||
if (unlikely(!ret)) {
|
||||
spin_lock_irqsave(&vpm->list_lock, flags);
|
||||
list_del(&cmd->node);
|
||||
|
||||
@@ -2030,7 +2030,7 @@ static int __init voicebus_module_init(void)
|
||||
* defined, but it will make sure that this module is a dependency of
|
||||
* dahdi.ko, so that when it is being unloded, this module will be
|
||||
* unloaded as well. */
|
||||
dahdi_register(NULL, 0);
|
||||
dahdi_register_device(NULL, NULL);
|
||||
spin_lock_init(&loader_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,15 @@
|
||||
* (and not tasklet). */
|
||||
#define CONFIG_VOICEBUS_INTERRUPT
|
||||
|
||||
/*
|
||||
* Enable the following definition in order to disable Active-State Power
|
||||
* Management on the PCIe bridge for PCIe cards. This has been known to work
|
||||
* around issues where the BIOS enables it on the cards even though the
|
||||
* platform does not support it.
|
||||
*
|
||||
*/
|
||||
#undef CONFIG_VOICEBUS_DISABLE_ASPM
|
||||
|
||||
/* Define this to use a FIFO for the software echocan reference.
|
||||
* (experimental) */
|
||||
#undef CONFIG_VOICEBUS_ECREFERENCE
|
||||
|
||||
@@ -72,7 +72,7 @@ static int _vpmoct_read(struct vpmoct *vpm, u8 address,
|
||||
list_del(&cmd->node);
|
||||
spin_unlock_irqrestore(&vpm->list_lock, flags);
|
||||
kfree(cmd);
|
||||
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out :O(\n");
|
||||
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1249,7 +1249,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;
|
||||
}
|
||||
@@ -2474,7 +2475,6 @@ static void init_spans(struct b4xxp *b4)
|
||||
bspan = &b4->spans[i];
|
||||
bspan->parent = b4;
|
||||
|
||||
bspan->span.irq = b4->pdev->irq;
|
||||
bspan->span.spantype = (bspan->te_mode) ? "TE" : "NT";
|
||||
bspan->span.offset = i;
|
||||
bspan->span.channels = WCB4XXP_CHANNELS_PER_SPAN;
|
||||
@@ -2493,11 +2493,6 @@ static void init_spans(struct b4xxp *b4)
|
||||
|
||||
sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1);
|
||||
sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1);
|
||||
bspan->span.manufacturer = "Digium";
|
||||
strlcpy(bspan->span.devicetype, b4->variety,
|
||||
sizeof(bspan->span.devicetype));
|
||||
sprintf(bspan->span.location, "PCI Bus %02d Slot %02d",
|
||||
b4->pdev->bus->number, PCI_SLOT(b4->pdev->devfn) + 1);
|
||||
|
||||
bspan->span.ops = &b4xxp_span_ops;
|
||||
/* HDLC stuff */
|
||||
@@ -2929,14 +2924,27 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
|
||||
hfc_init_all_st(b4);
|
||||
|
||||
/* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */
|
||||
b4->ddev = dahdi_create_device();
|
||||
init_spans(b4);
|
||||
|
||||
for (x=0; x < b4->numspans; x++) {
|
||||
if (dahdi_register(&b4->spans[x].span, 0)) {
|
||||
dev_err(&b4->pdev->dev,
|
||||
"Unable to register span %s\n",
|
||||
b4->spans[x].span.name);
|
||||
goto err_out_unreg_spans;
|
||||
}
|
||||
struct dahdi_span *const s = &b4->spans[x].span;
|
||||
list_add_tail(&s->device_node, &b4->ddev->spans);
|
||||
}
|
||||
|
||||
b4->ddev->manufacturer = "Digium";
|
||||
b4->ddev->devicetype = b4->variety;
|
||||
b4->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||
b4->pdev->bus->number,
|
||||
PCI_SLOT(b4->pdev->devfn) + 1);
|
||||
if (!b4->ddev->location) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out_del_from_card_array;
|
||||
}
|
||||
|
||||
if (dahdi_register_device(b4->ddev, &b4->pdev->dev)) {
|
||||
dev_err(&b4->pdev->dev, "Unable to register device.\n");
|
||||
goto err_out_unreg_spans;
|
||||
}
|
||||
|
||||
|
||||
@@ -2972,10 +2980,7 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
|
||||
|
||||
/* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */
|
||||
err_out_unreg_spans:
|
||||
while (x) {
|
||||
dahdi_unregister(&b4->spans[x].span);
|
||||
x--;
|
||||
};
|
||||
dahdi_unregister_device(b4->ddev);
|
||||
|
||||
b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */
|
||||
free_irq(pdev->irq, b4);
|
||||
@@ -2996,6 +3001,8 @@ err_out_free_mem:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_iounmap(pdev, b4->ioaddr);
|
||||
pci_iounmap(pdev, b4->addr);
|
||||
kfree(b4->ddev->location);
|
||||
dahdi_free_device(b4->ddev);
|
||||
kfree(b4);
|
||||
|
||||
err_out_release_regions:
|
||||
@@ -3010,14 +3017,11 @@ err_out_disable_pdev:
|
||||
static void __devexit b4xxp_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct b4xxp *b4 = pci_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
if (b4) {
|
||||
b4->shutdown = 1;
|
||||
|
||||
for (i=b4->numspans - 1; i >= 0; i--) {
|
||||
dahdi_unregister(&b4->spans[i].span);
|
||||
}
|
||||
dahdi_unregister_device(b4->ddev);
|
||||
|
||||
b4xxp_init_stage1(b4);
|
||||
remove_sysfs_files(b4);
|
||||
@@ -3032,6 +3036,8 @@ static void __devexit b4xxp_remove(struct pci_dev *pdev)
|
||||
|
||||
tasklet_kill(&b4->b4xxp_tlet);
|
||||
|
||||
kfree(b4->ddev->location);
|
||||
dahdi_free_device(b4->ddev);
|
||||
kfree(b4);
|
||||
}
|
||||
|
||||
|
||||
@@ -474,6 +474,7 @@ struct b4xxp {
|
||||
/* Flags for our bottom half */
|
||||
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
|
||||
struct tasklet_struct b4xxp_tlet;
|
||||
struct dahdi_device *ddev;
|
||||
};
|
||||
|
||||
/* CPLD access bits */
|
||||
|
||||
@@ -135,6 +135,7 @@ static int wecareregs[] =
|
||||
struct wcfxo {
|
||||
struct pci_dev *dev;
|
||||
char *variety;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan _chan;
|
||||
struct dahdi_chan *chan;
|
||||
@@ -647,19 +648,24 @@ static const struct dahdi_span_ops wcfxo_span_ops = {
|
||||
|
||||
static int wcfxo_initialize(struct wcfxo *wc)
|
||||
{
|
||||
wc->ddev = dahdi_create_device();
|
||||
|
||||
/* DAHDI stuff */
|
||||
sprintf(wc->span.name, "WCFXO/%d", wc->pos);
|
||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
|
||||
sprintf(wc->chan->name, "WCFXO/%d/%d", wc->pos, 0);
|
||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
||||
wc->span.manufacturer = "Digium";
|
||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
||||
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||
wc->dev->bus->number,
|
||||
PCI_SLOT(wc->dev->devfn) + 1);
|
||||
if (!wc->ddev->location)
|
||||
return -ENOMEM;
|
||||
|
||||
wc->ddev->manufacturer = "Digium";
|
||||
wc->ddev->devicetype = wc->variety;
|
||||
wc->chan->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF;
|
||||
wc->chan->chanpos = 1;
|
||||
wc->span.chans = &wc->chan;
|
||||
wc->span.channels = 1;
|
||||
wc->span.irq = wc->dev->irq;
|
||||
wc->span.flags = DAHDI_FLAG_RBS;
|
||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||
#ifdef ENABLE_TASKLETS
|
||||
@@ -668,7 +674,8 @@ static int wcfxo_initialize(struct wcfxo *wc)
|
||||
|
||||
wc->chan->pvt = wc;
|
||||
wc->span.ops = &wcfxo_span_ops;
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -976,7 +983,7 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
printk(KERN_NOTICE "Failed to initailize DAA, giving up...\n");
|
||||
wcfxo_stop_dma(wc);
|
||||
wcfxo_disable_interrupts(wc);
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
free_irq(pdev->irq, wc);
|
||||
|
||||
/* Reset PCI chip and registers */
|
||||
@@ -984,6 +991,8 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
|
||||
if (wc->freeregion)
|
||||
release_region(wc->ioaddr, 0xff);
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
return -EIO;
|
||||
}
|
||||
@@ -995,9 +1004,11 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
|
||||
static void wcfxo_release(struct wcfxo *wc)
|
||||
{
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
if (wc->freeregion)
|
||||
release_region(wc->ioaddr, 0xff);
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
printk(KERN_INFO "Freed a Wildcard\n");
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ struct t1xxp {
|
||||
unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE];
|
||||
unsigned char tempo[32];
|
||||
struct dahdi_span span; /* Span */
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_chan *chans[31]; /* Channels */
|
||||
};
|
||||
|
||||
@@ -272,10 +273,11 @@ static void t1xxp_release(struct t1xxp *wc)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
for (x = 0; x < (wc->ise1 ? 31 : 24); x++) {
|
||||
kfree(wc->chans[x]);
|
||||
}
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
printk(KERN_INFO "Freed a Wildcard\n");
|
||||
}
|
||||
@@ -770,14 +772,20 @@ static int t1xxp_software_init(struct t1xxp *wc)
|
||||
}
|
||||
if (x >= WC_MAX_CARDS)
|
||||
return -1;
|
||||
|
||||
wc->ddev = dahdi_create_device();
|
||||
|
||||
wc->num = x;
|
||||
sprintf(wc->span.name, "WCT1/%d", wc->num);
|
||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
|
||||
wc->span.manufacturer = "Digium";
|
||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
||||
wc->span.irq = wc->dev->irq;
|
||||
wc->ddev->manufacturer = "Digium";
|
||||
wc->ddev->devicetype = wc->variety;
|
||||
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||
wc->dev->bus->number,
|
||||
PCI_SLOT(wc->dev->devfn) + 1);
|
||||
if (!wc->ddev->location)
|
||||
return -ENOMEM;
|
||||
|
||||
wc->span.chans = wc->chans;
|
||||
wc->span.flags = DAHDI_FLAG_RBS;
|
||||
if (wc->ise1) {
|
||||
@@ -801,7 +809,8 @@ static int t1xxp_software_init(struct t1xxp *wc)
|
||||
wc->chans[x]->chanpos = x + 1;
|
||||
}
|
||||
wc->span.ops = &t1xxp_span_ops;
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -908,10 +917,10 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
|
||||
if (((oldcan & 0xffff0000) >> 16) != CANARY) {
|
||||
/* Check top part */
|
||||
if (debug) printk(KERN_DEBUG "Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16);
|
||||
wc->span.irqmisses++;
|
||||
wc->ddev->irqmisses++;
|
||||
} else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) {
|
||||
if (debug) printk(KERN_DEBUG "Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff);
|
||||
wc->span.irqmisses++;
|
||||
wc->ddev->irqmisses++;
|
||||
}
|
||||
for (y=0;y<DAHDI_CHUNKSIZE;y++) {
|
||||
for (x=0;x<wc->span.channels;x++) {
|
||||
|
||||
@@ -17,7 +17,7 @@ endif
|
||||
wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x)
|
||||
|
||||
ifneq ($(HOTPLUG_FIRMWARE),yes)
|
||||
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o
|
||||
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o
|
||||
$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
|
||||
endif
|
||||
|
||||
@@ -26,3 +26,6 @@ $(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -172,9 +172,9 @@ UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
|
||||
|
||||
struct vpm450m {
|
||||
tPOCT6100_INSTANCE_API pApiInstance;
|
||||
UINT32 aulEchoChanHndl[128];
|
||||
int chanflags[128];
|
||||
int ecmode[128];
|
||||
UINT32 aulEchoChanHndl[256];
|
||||
int chanflags[256];
|
||||
int ecmode[256];
|
||||
int numchans;
|
||||
};
|
||||
|
||||
@@ -422,6 +422,8 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
|
||||
tOCT6100_CHANNEL_OPEN *ChannelOpen;
|
||||
UINT32 ulResult;
|
||||
const unsigned int mask = (8 == numspans) ? 0x7 : 0x3;
|
||||
unsigned int sout_stream, rout_stream;
|
||||
struct vpm450m *vpm450m;
|
||||
int x,y,law;
|
||||
|
||||
@@ -467,15 +469,22 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
|
||||
ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB;
|
||||
ChipOpen->ulNumMemoryChips = 1;
|
||||
ChipOpen->ulMaxTdmStreams = 4;
|
||||
ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ;
|
||||
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
|
||||
ChipOpen->ulMaxFlexibleConfParticipants = 0;
|
||||
ChipOpen->ulMaxConfBridges = 0;
|
||||
ChipOpen->ulMaxRemoteDebugSessions = 0;
|
||||
ChipOpen->fEnableChannelRecording = FALSE;
|
||||
ChipOpen->ulSoftToneEventsBufSize = 64;
|
||||
|
||||
if (vpm450m->numchans <= 128) {
|
||||
ChipOpen->ulMaxTdmStreams = 4;
|
||||
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
|
||||
} else {
|
||||
ChipOpen->ulMaxTdmStreams = 32;
|
||||
ChipOpen->fEnableFastH100Mode = TRUE;
|
||||
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_RISING_EDGE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ChipOpen->fEnableAcousticEcho = TRUE;
|
||||
#endif
|
||||
@@ -507,7 +516,11 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
kfree(ChannelOpen);
|
||||
return NULL;
|
||||
}
|
||||
for (x = 0; x < ARRAY_SIZE(vpm450m->aulEchoChanHndl); x++) {
|
||||
|
||||
sout_stream = (8 == numspans) ? 29 : 2;
|
||||
rout_stream = (8 == numspans) ? 24 : 3;
|
||||
|
||||
for (x = 0; x < ((8 == numspans) ? 256 : 128); x++) {
|
||||
/* execute this loop always on 4 span cards but
|
||||
* on 2 span cards only execute for the channels related to our spans */
|
||||
if (( numspans > 2) || ((x & 0x03) <2)) {
|
||||
@@ -515,7 +528,7 @@ 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 & 0x03])
|
||||
if (isalaw[x & mask])
|
||||
law = cOCT6100_PCM_A_LAW;
|
||||
else
|
||||
law = cOCT6100_PCM_U_LAW;
|
||||
@@ -529,11 +542,13 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
ChannelOpen->TdmConfig.ulSinStream = 1;
|
||||
ChannelOpen->TdmConfig.ulSinTimeslot = x;
|
||||
ChannelOpen->TdmConfig.ulSoutPcmLaw = law;
|
||||
ChannelOpen->TdmConfig.ulSoutStream = 2;
|
||||
ChannelOpen->TdmConfig.ulSoutStream = sout_stream;
|
||||
ChannelOpen->TdmConfig.ulSoutTimeslot = x;
|
||||
#if 1
|
||||
ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
|
||||
ChannelOpen->TdmConfig.ulRoutStream = 3;
|
||||
ChannelOpen->TdmConfig.ulRoutStream = rout_stream;
|
||||
ChannelOpen->TdmConfig.ulRoutTimeslot = x;
|
||||
#endif
|
||||
ChannelOpen->VqeConfig.fEnableNlp = TRUE;
|
||||
ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
|
||||
ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
|
||||
@@ -543,7 +558,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
|
||||
ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen);
|
||||
if (ulResult != GENERIC_OK) {
|
||||
printk(KERN_NOTICE "Failed to open channel %d!\n", x);
|
||||
printk(KERN_NOTICE "Failed to open channel %d %x!\n", x, ulResult);
|
||||
continue;
|
||||
}
|
||||
for (y = 0; y < ARRAY_SIZE(tones); y++) {
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
#define FRMR_SIC3 0x40
|
||||
#define FRMR_CMR1 0x44
|
||||
#define FRMR_CMR2 0x45
|
||||
/* OctalFALC Only */
|
||||
#define FRMR_CMR4 0x41
|
||||
#define FRMR_CMR5 0x42
|
||||
#define FRMR_CMR6 0x43
|
||||
#define FRMR_GPC2 0x8a
|
||||
/* End Octal */
|
||||
#define FRMR_GCR 0x46
|
||||
#define FRMR_ISR0 0x68
|
||||
#define FRMR_ISR0_RME 0x80
|
||||
@@ -76,6 +82,13 @@
|
||||
#define FRMR_CIS_GIS2 0x02
|
||||
#define FRMR_CIS_GIS3 0x04
|
||||
#define FRMR_CIS_GIS4 0x08
|
||||
|
||||
/* CIS - Octal falc bits */
|
||||
#define FRMR_CIS_GIS5 0x10
|
||||
#define FRMR_CIS_GIS6 0x20
|
||||
#define FRMR_CIS_GIS7 0x40
|
||||
#define FRMR_CIS_GIS8 0x80
|
||||
|
||||
#define FRMR_CMDR 0x02
|
||||
#define FRMR_CMDR_SRES 0x01
|
||||
#define FRMR_CMDR_XRES 0x10
|
||||
@@ -113,6 +126,11 @@ struct t4_regs {
|
||||
unsigned char regs[NUM_REGS];
|
||||
};
|
||||
|
||||
struct t4_reg {
|
||||
unsigned int reg;
|
||||
unsigned int val;
|
||||
};
|
||||
|
||||
#define T4_CHECK_VPM 0
|
||||
#define T4_LOADING_FW 1
|
||||
#define T4_STOP_DMA 2
|
||||
@@ -120,5 +138,7 @@ struct t4_regs {
|
||||
#define T4_CHANGE_LATENCY 4
|
||||
#define T4_IGNORE_LATENCY 5
|
||||
|
||||
#define WCT4_GET_REGS _IOW (DAHDI_CODE, 60, struct t4_regs)
|
||||
#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
|
||||
#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
|
||||
#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ struct wctdm {
|
||||
struct pci_dev *dev;
|
||||
char *variety;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_device *ddev;
|
||||
unsigned char ios;
|
||||
int usecount;
|
||||
unsigned int intcount;
|
||||
@@ -2362,13 +2363,26 @@ static int wctdm_initialize(struct wctdm *wc)
|
||||
{
|
||||
int x;
|
||||
|
||||
wc->ddev = dahdi_create_device();
|
||||
if (!wc->ddev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* DAHDI stuff */
|
||||
sprintf(wc->span.name, "WCTDM/%d", wc->pos);
|
||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
|
||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
||||
wc->span.manufacturer = "Digium";
|
||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
||||
wc->ddev->location = kasprintf(GFP_KERNEL,
|
||||
"PCI Bus %02d Slot %02d",
|
||||
wc->dev->bus->number,
|
||||
PCI_SLOT(wc->dev->devfn) + 1);
|
||||
if (!wc->ddev->location) {
|
||||
dahdi_free_device(wc->ddev);
|
||||
wc->ddev = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
wc->ddev->manufacturer = "Digium";
|
||||
wc->ddev->devicetype = wc->variety;
|
||||
|
||||
if (alawoverride) {
|
||||
printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
|
||||
wc->span.deflaw = DAHDI_LAW_ALAW;
|
||||
@@ -2384,12 +2398,15 @@ static int wctdm_initialize(struct wctdm *wc)
|
||||
}
|
||||
wc->span.chans = wc->chans;
|
||||
wc->span.channels = NUM_CARDS;
|
||||
wc->span.irq = wc->dev->irq;
|
||||
wc->span.flags = DAHDI_FLAG_RBS;
|
||||
wc->span.ops = &wctdm_span_ops;
|
||||
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
wc->ddev = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -2677,7 +2694,9 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
release_region(wc->ioaddr, 0xff);
|
||||
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
return -EIO;
|
||||
|
||||
@@ -2708,10 +2727,14 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
|
||||
static void wctdm_release(struct wctdm *wc)
|
||||
{
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
if (wc->freeregion)
|
||||
release_region(wc->ioaddr, 0xff);
|
||||
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
|
||||
printk(KERN_INFO "Freed a Wildcard\n");
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,7 +45,6 @@
|
||||
* \brief Default ringer debounce (in ms)
|
||||
*/
|
||||
#define DEFAULT_RING_DEBOUNCE 1024
|
||||
|
||||
#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */
|
||||
|
||||
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
|
||||
@@ -85,7 +84,6 @@
|
||||
|
||||
#define NUM_CAL_REGS 12
|
||||
|
||||
#define ISR_COMMANDS 2
|
||||
#define QRV_DEBOUNCETIME 20
|
||||
|
||||
#define VPM150M_HPI_CONTROL 0x00
|
||||
@@ -107,10 +105,30 @@ struct calregs {
|
||||
|
||||
enum battery_state {
|
||||
BATTERY_UNKNOWN = 0,
|
||||
BATTERY_DEBOUNCING_PRESENT,
|
||||
BATTERY_DEBOUNCING_PRESENT_ALARM,
|
||||
BATTERY_PRESENT,
|
||||
BATTERY_DEBOUNCING_LOST,
|
||||
BATTERY_DEBOUNCING_LOST_ALARM,
|
||||
BATTERY_LOST,
|
||||
};
|
||||
|
||||
enum ring_detector_state {
|
||||
RINGOFF = 0,
|
||||
DEBOUNCING_RINGING_POSITIVE,
|
||||
DEBOUNCING_RINGING_NEGATIVE,
|
||||
RINGING,
|
||||
DEBOUNCING_RINGOFF,
|
||||
};
|
||||
|
||||
enum polarity_state {
|
||||
UNKNOWN_POLARITY = 0,
|
||||
POLARITY_DEBOUNCE_POSITIVE,
|
||||
POLARITY_POSITIVE,
|
||||
POLARITY_DEBOUNCE_NEGATIVE,
|
||||
POLARITY_NEGATIVE,
|
||||
};
|
||||
|
||||
struct wctdm_cmd {
|
||||
struct list_head node;
|
||||
struct completion *complete;
|
||||
@@ -146,29 +164,26 @@ struct wctdm_chan {
|
||||
};
|
||||
|
||||
struct fxo {
|
||||
int wasringing;
|
||||
int lastrdtx;
|
||||
int lastrdtx_count;
|
||||
int ringdebounce;
|
||||
enum ring_detector_state ring_state:4;
|
||||
enum battery_state battery_state:4;
|
||||
enum polarity_state polarity_state:4;
|
||||
u8 ring_polarity_change_count:4;
|
||||
u8 hook_ring_shadow;
|
||||
s8 line_voltage_status;
|
||||
int offhook;
|
||||
int battdebounce;
|
||||
int battalarm;
|
||||
enum battery_state battery;
|
||||
int lastpol;
|
||||
int polarity;
|
||||
int polaritydebounce;
|
||||
int neonmwi_state;
|
||||
int neonmwi_last_voltage;
|
||||
unsigned int neonmwi_debounce;
|
||||
unsigned int neonmwi_offcounter;
|
||||
unsigned long display_fxovoltage;
|
||||
unsigned long ringdebounce_timer;
|
||||
unsigned long battdebounce_timer;
|
||||
unsigned long poldebounce_timer;
|
||||
};
|
||||
|
||||
struct fxs {
|
||||
int oldrxhook;
|
||||
int debouncehook;
|
||||
int lastrxhook;
|
||||
int debounce;
|
||||
int ohttimer;
|
||||
u8 oht_active:1;
|
||||
u8 off_hook:1;
|
||||
int idletxhookstate; /* IDLE changing hook state */
|
||||
/* lasttxhook reflects the last value written to the proslic's reg
|
||||
* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last
|
||||
@@ -180,13 +195,18 @@ struct fxs {
|
||||
* voicebus ISR.
|
||||
*/
|
||||
int lasttxhook;
|
||||
int oppending_ms;
|
||||
u8 linefeed_control_shadow;
|
||||
u8 hook_state_shadow;
|
||||
int palarms;
|
||||
struct dahdi_vmwi_info vmwisetting;
|
||||
int vmwi_active_messages;
|
||||
int vmwi_linereverse;
|
||||
int reversepolarity; /* polarity reversal */
|
||||
struct calregs calregs;
|
||||
unsigned long check_alarm;
|
||||
unsigned long check_proslic;
|
||||
unsigned long oppending_timeout;
|
||||
unsigned long ohttimer;
|
||||
};
|
||||
|
||||
struct qrv {
|
||||
@@ -203,6 +223,7 @@ struct qrv {
|
||||
int radmode;
|
||||
signed short rxgain;
|
||||
signed short txgain;
|
||||
u8 isrshadow[3];
|
||||
};
|
||||
|
||||
enum module_type {
|
||||
@@ -215,7 +236,7 @@ enum module_type {
|
||||
};
|
||||
|
||||
struct wctdm_module {
|
||||
union {
|
||||
union modtypes {
|
||||
struct fxo fxo;
|
||||
struct fxs fxs;
|
||||
struct qrv qrv;
|
||||
@@ -227,7 +248,6 @@ struct wctdm_module {
|
||||
struct list_head active_cmds;
|
||||
u8 offsets[3];
|
||||
u8 subaddr;
|
||||
u8 isrshadow[ISR_COMMANDS];
|
||||
u8 card;
|
||||
|
||||
enum module_type type;
|
||||
@@ -242,7 +262,7 @@ struct wctdm {
|
||||
spinlock_t frame_list_lock;
|
||||
struct list_head frame_list;
|
||||
|
||||
unsigned int intcount;
|
||||
unsigned long framecount;
|
||||
unsigned char txident;
|
||||
unsigned char rxident;
|
||||
|
||||
@@ -277,6 +297,7 @@ struct wctdm {
|
||||
int not_ready; /* 0 when the entire card is ready to go */
|
||||
unsigned long checkflag; /* Internal state flags and task bits */
|
||||
int companding;
|
||||
struct dahdi_device *ddev;
|
||||
};
|
||||
|
||||
static inline bool is_initialized(struct wctdm *wc)
|
||||
|
||||
@@ -174,6 +174,7 @@ struct t1 {
|
||||
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
|
||||
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
|
||||
unsigned char tempo[33];
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span; /* Span */
|
||||
struct dahdi_chan *chans[32]; /* Channels */
|
||||
};
|
||||
@@ -340,10 +341,12 @@ static void t1xxp_release(struct t1 *wc)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
||||
kfree(wc->chans[x]);
|
||||
}
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
printk(KERN_INFO "Freed a Wildcard\n");
|
||||
}
|
||||
@@ -976,15 +979,21 @@ static int t1xxp_software_init(struct t1 *wc)
|
||||
}
|
||||
if (x >= WC_MAX_CARDS)
|
||||
return -1;
|
||||
|
||||
wc->ddev = dahdi_create_device();
|
||||
|
||||
t4_serial_setup(wc);
|
||||
wc->num = x;
|
||||
sprintf(wc->span.name, "WCT1/%d", wc->num);
|
||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
|
||||
wc->span.manufacturer = "Digium";
|
||||
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
|
||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
||||
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
|
||||
wc->span.irq = wc->dev->irq;
|
||||
wc->ddev->manufacturer = "Digium";
|
||||
wc->ddev->devicetype = wc->variety;
|
||||
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||
wc->dev->bus->number,
|
||||
PCI_SLOT(wc->dev->devfn) + 1);
|
||||
if (!wc->ddev->location)
|
||||
return -ENOMEM;
|
||||
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (unchannelized)
|
||||
wc->span.channels = 32;
|
||||
@@ -1011,7 +1020,8 @@ static int t1xxp_software_init(struct t1 *wc)
|
||||
wc->chans[x]->chanpos = x + 1;
|
||||
}
|
||||
wc->span.ops = &t1xxp_span_ops;
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1118,10 +1128,10 @@ static void t1xxp_receiveprep(struct t1 *wc, int ints)
|
||||
if (((oldcan & 0xffff0000) >> 16) != CANARY) {
|
||||
/* Check top part */
|
||||
if (debug) printk(KERN_DEBUG "Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16);
|
||||
wc->span.irqmisses++;
|
||||
wc->ddev->irqmisses++;
|
||||
} else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) {
|
||||
if (debug) printk(KERN_DEBUG "Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff);
|
||||
wc->span.irqmisses++;
|
||||
wc->ddev->irqmisses++;
|
||||
}
|
||||
for (y=0;y<DAHDI_CHUNKSIZE;y++) {
|
||||
for (x=0;x<wc->span.channels;x++) {
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
@@ -56,12 +58,13 @@
|
||||
#endif
|
||||
|
||||
static int debug;
|
||||
static int j1mode = 0;
|
||||
static int j1mode = -1;
|
||||
static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/
|
||||
static int losalarmdebounce = 2500; /* LOS def to 2.5s AT&T TR54016*/
|
||||
static int aisalarmdebounce = 2500; /* AIS(blue) def to 2.5s AT&T TR54016*/
|
||||
static int yelalarmdebounce = 500; /* RAI(yellow) def to 0.5s AT&T devguide */
|
||||
static int t1e1override = -1;
|
||||
static int t1e1override = -1; /* deprecated */
|
||||
static char *default_linemode = "auto"; /* 'auto', 'e1', 't1', or 'j1' */
|
||||
static int latency = VOICEBUS_DEFAULT_LATENCY;
|
||||
static unsigned int max_latency = VOICEBUS_DEFAULT_MAXLATENCY;
|
||||
static int vpmsupport = 1;
|
||||
@@ -94,6 +97,11 @@ static const struct t1_desc te120p = {"Wildcard TE120P"};
|
||||
static const struct t1_desc te122 = {"Wildcard TE122"};
|
||||
static const struct t1_desc te121 = {"Wildcard TE121"};
|
||||
|
||||
static inline bool is_pcie(const struct t1 *t1)
|
||||
{
|
||||
return (0 == strcmp(t1->variety, te121.name));
|
||||
}
|
||||
|
||||
/* names of HWEC modules */
|
||||
static const char *vpmadt032_name = "VPMADT032";
|
||||
static const char *vpmoct_name = "VPMOCT032";
|
||||
@@ -635,21 +643,21 @@ static inline int t1_setreg(struct t1 *wc, int addr, int val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t1_getreg(struct t1 *wc, int addr)
|
||||
static void __t1_getreg(struct t1 *wc, int addr, struct command *cmd)
|
||||
{
|
||||
struct command *cmd = NULL;
|
||||
unsigned long ret;
|
||||
unsigned long flags;
|
||||
|
||||
might_sleep();
|
||||
|
||||
cmd = get_free_cmd(wc);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
cmd->address = addr;
|
||||
cmd->data = 0x00;
|
||||
cmd->flags = __CMD_RD;
|
||||
submit_cmd(wc, cmd);
|
||||
}
|
||||
|
||||
static int __t1_getresult(struct t1 *wc, struct command *cmd)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
might_sleep();
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(&cmd->complete, HZ*10);
|
||||
if (unlikely(!ret)) {
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
@@ -680,10 +688,22 @@ static int t1_getreg(struct t1 *wc, int addr)
|
||||
}
|
||||
}
|
||||
ret = cmd->data;
|
||||
free_cmd(wc, cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int t1_getreg(struct t1 *wc, int addr)
|
||||
{
|
||||
int res;
|
||||
struct command *cmd = NULL;
|
||||
cmd = get_free_cmd(wc);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
__t1_getreg(wc, addr, cmd);
|
||||
res = __t1_getresult(wc, cmd);
|
||||
free_cmd(wc, cmd);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void t1_setleds(struct t1 *wc, int leds)
|
||||
{
|
||||
struct command *cmd;
|
||||
@@ -750,7 +770,7 @@ static void __t1xxp_set_clear(struct t1 *wc)
|
||||
/* Calculate all states on all 24 channels using the channel
|
||||
flags, then write all 3 clear channel registers at once */
|
||||
|
||||
for (i = 0; i < 24; i++) {
|
||||
for (i = 0; i < wc->span.channels; i++) {
|
||||
offset = i/8;
|
||||
if (wc->span.chans[i]->flags & DAHDI_FLAG_CLEAR)
|
||||
reg[offset] |= 1 << (7 - (i % 8));
|
||||
@@ -771,19 +791,31 @@ static void __t1xxp_set_clear(struct t1 *wc)
|
||||
t1_info(wc, "Unable to set clear/rbs mode!\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* _t1_free_channels - Free the memory allocated for the channels.
|
||||
*
|
||||
* Must be called with wc->reglock held.
|
||||
*
|
||||
*/
|
||||
static void _t1_free_channels(struct t1 *wc)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < ARRAY_SIZE(wc->chans); x++) {
|
||||
kfree(wc->chans[x]);
|
||||
kfree(wc->ec[x]);
|
||||
wc->chans[x] = NULL;
|
||||
wc->ec[x] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_wc(struct t1 *wc)
|
||||
{
|
||||
unsigned int x;
|
||||
unsigned long flags;
|
||||
struct command *cmd;
|
||||
LIST_HEAD(list);
|
||||
|
||||
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
||||
kfree(wc->chans[x]);
|
||||
kfree(wc->ec[x]);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
_t1_free_channels(wc);
|
||||
list_splice_init(&wc->active_cmds, &list);
|
||||
list_splice_init(&wc->pending_cmds, &list);
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
@@ -803,14 +835,14 @@ static void free_wc(struct t1 *wc)
|
||||
}
|
||||
#endif
|
||||
|
||||
kfree(wc->ddev->location);
|
||||
kfree(wc->ddev->devicetype);
|
||||
dahdi_free_device(wc->ddev);
|
||||
kfree(wc);
|
||||
}
|
||||
|
||||
static void t4_serial_setup(struct t1 *wc)
|
||||
{
|
||||
t1_info(wc, "Setting up global serial parameters for %s\n",
|
||||
((wc->spantype == TYPE_E1) ? "E1" : "T1"));
|
||||
|
||||
t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
|
||||
t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */
|
||||
|
||||
@@ -861,7 +893,8 @@ static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel)
|
||||
fmr1 = 0x9e; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */
|
||||
fmr2 = 0x20; /* FMR2: no payload loopback, don't auto yellow alarm */
|
||||
|
||||
if (j1mode)
|
||||
|
||||
if (!strcasecmp("j1", wc->span.spantype))
|
||||
fmr4 = 0x1c;
|
||||
else
|
||||
fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */
|
||||
@@ -901,7 +934,7 @@ static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel)
|
||||
t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */
|
||||
t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */
|
||||
|
||||
if (j1mode)
|
||||
if (!strcasecmp("j1", wc->span.spantype))
|
||||
t1_setreg(wc, 0x24, 0x80); /* J1 overide */
|
||||
|
||||
/* Generate pulse mask for T1 */
|
||||
@@ -1004,12 +1037,12 @@ static void t1_configure_e1(struct t1 *wc, int lineconfig)
|
||||
t1_info(wc, "Span configured for %s/%s%s\n", framing, line, crc4);
|
||||
}
|
||||
|
||||
static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
|
||||
static void t1xxp_framer_start(struct t1 *wc)
|
||||
{
|
||||
if (wc->spantype == TYPE_E1) { /* if this is an E1 card */
|
||||
t1_configure_e1(wc, span->lineconfig);
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
t1_configure_e1(wc, wc->span.lineconfig);
|
||||
} else { /* is a T1 card */
|
||||
t1_configure_t1(wc, span->lineconfig, span->txlevel);
|
||||
t1_configure_t1(wc, wc->span.lineconfig, wc->span.txlevel);
|
||||
__t1xxp_set_clear(wc);
|
||||
}
|
||||
|
||||
@@ -1018,18 +1051,28 @@ static void t1xxp_framer_start(struct t1 *wc, struct dahdi_span *span)
|
||||
|
||||
static void set_span_devicetype(struct t1 *wc)
|
||||
{
|
||||
strncpy(wc->span.devicetype, wc->variety,
|
||||
sizeof(wc->span.devicetype) - 1);
|
||||
const char *olddevicetype;
|
||||
olddevicetype = wc->ddev->devicetype;
|
||||
|
||||
#if defined(VPM_SUPPORT)
|
||||
if (wc->vpmadt032) {
|
||||
strncat(wc->span.devicetype, " (VPMADT032)",
|
||||
sizeof(wc->span.devicetype) - 1);
|
||||
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
|
||||
"%s (VPMADT032)", wc->variety);
|
||||
} else if (wc->vpmoct) {
|
||||
strncat(wc->span.devicetype, " (VPMOCT032)",
|
||||
sizeof(wc->span.devicetype) - 1);
|
||||
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
|
||||
"%s (VPMOCT032)", wc->variety);
|
||||
} else {
|
||||
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->variety);
|
||||
}
|
||||
#else
|
||||
wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s", wc->variety);
|
||||
#endif
|
||||
|
||||
/* On the off chance that we were able to allocate it previously. */
|
||||
if (!wc->ddev->devicetype)
|
||||
wc->ddev->devicetype = olddevicetype;
|
||||
else
|
||||
kfree(olddevicetype);
|
||||
}
|
||||
|
||||
static int t1xxp_startup(struct file *file, struct dahdi_span *span)
|
||||
@@ -1050,7 +1093,7 @@ static int t1xxp_startup(struct file *file, struct dahdi_span *span)
|
||||
#endif
|
||||
|
||||
/* Reset framer with proper parameters and start */
|
||||
t1xxp_framer_start(wc, span);
|
||||
t1xxp_framer_start(wc);
|
||||
debug_printk(wc, 1, "Calling startup (flags is %lu)\n", span->flags);
|
||||
|
||||
return 0;
|
||||
@@ -1090,7 +1133,7 @@ static int t1xxp_chanconfig(struct file *file,
|
||||
}
|
||||
|
||||
if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) &&
|
||||
(wc->spantype != TYPE_E1)) {
|
||||
dahdi_is_t1_span(&wc->span)) {
|
||||
__t1xxp_set_clear(wc);
|
||||
}
|
||||
return 0;
|
||||
@@ -1105,7 +1148,7 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits)
|
||||
|
||||
debug_printk(wc, 2, "Setting bits to %d on channel %s\n",
|
||||
bits, chan->name);
|
||||
if (wc->spantype == TYPE_E1) { /* do it E1 way */
|
||||
if (dahdi_is_e1_span(&wc->span)) { /* do it E1 way */
|
||||
if (chan->chanpos == 16)
|
||||
return 0;
|
||||
|
||||
@@ -1152,15 +1195,47 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void t1_check_sigbits(struct t1 *wc)
|
||||
static void t1_check_sigbits(struct t1 *wc)
|
||||
{
|
||||
struct command_container {
|
||||
struct command *cmd;
|
||||
struct list_head node;
|
||||
unsigned int index;
|
||||
};
|
||||
struct command_container *cont;
|
||||
LIST_HEAD(commands);
|
||||
int a,i,rxs;
|
||||
|
||||
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
|
||||
return;
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
/* Send out all the commands first. */
|
||||
for (i = 0; i < 15; i++) {
|
||||
a = t1_getreg(wc, 0x71 + i);
|
||||
if (!(wc->span.chans[i+16]->sig & DAHDI_SIG_CLEAR) ||
|
||||
!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
|
||||
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
|
||||
if (!cont) {
|
||||
WARN_ON_ONCE(1);
|
||||
goto done;
|
||||
}
|
||||
cont->cmd = get_free_cmd(wc);
|
||||
if (!cont->cmd) {
|
||||
WARN_ON_ONCE(1);
|
||||
goto done;
|
||||
}
|
||||
cont->index = i;
|
||||
list_add_tail(&cont->node, &commands);
|
||||
__t1_getreg(wc, 0x71 + i, cont->cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check the results */
|
||||
list_for_each_entry_reverse(cont, &commands, node) {
|
||||
i = cont->index;
|
||||
a = __t1_getresult(wc, cont->cmd);
|
||||
free_cmd(wc, cont->cmd);
|
||||
cont->cmd = NULL;
|
||||
if (a > -1) {
|
||||
/* Get high channel in low bits */
|
||||
rxs = (a & 0xf);
|
||||
@@ -1178,8 +1253,29 @@ static inline void t1_check_sigbits(struct t1 *wc)
|
||||
}
|
||||
}
|
||||
} else if (wc->span.lineconfig & DAHDI_CONFIG_D4) {
|
||||
for (i = 0; i < 24; i+=4) {
|
||||
a = t1_getreg(wc, 0x70 + (i>>2));
|
||||
/* First we'll send out the commands */
|
||||
for (i = 0; i < 24; i += 4) {
|
||||
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
|
||||
if (!cont) {
|
||||
WARN_ON_ONCE(1);
|
||||
goto done;
|
||||
}
|
||||
cont->cmd = get_free_cmd(wc);
|
||||
if (!cont->cmd) {
|
||||
WARN_ON_ONCE(1);
|
||||
goto done;
|
||||
}
|
||||
cont->index = i;
|
||||
list_add_tail(&cont->node, &commands);
|
||||
__t1_getreg(wc, 0x70 + (i>>2), cont->cmd);
|
||||
}
|
||||
|
||||
/* Now we'll check the results */
|
||||
list_for_each_entry_reverse(cont, &commands, node) {
|
||||
i = cont->index;
|
||||
a = __t1_getresult(wc, cont->cmd);
|
||||
free_cmd(wc, cont->cmd);
|
||||
cont->cmd = NULL;
|
||||
if (a > -1) {
|
||||
/* Get high channel in low bits */
|
||||
rxs = (a & 0x3) << 2;
|
||||
@@ -1209,8 +1305,28 @@ static inline void t1_check_sigbits(struct t1 *wc)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 24; i+=2) {
|
||||
a = t1_getreg(wc, 0x70 + (i>>1));
|
||||
/* First send out the commands. */
|
||||
for (i = 0; i < 24; i += 2) {
|
||||
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
|
||||
if (!cont) {
|
||||
WARN_ON_ONCE(1);
|
||||
goto done;
|
||||
}
|
||||
cont->cmd = get_free_cmd(wc);
|
||||
if (!cont->cmd) {
|
||||
WARN_ON_ONCE(1);
|
||||
goto done;
|
||||
}
|
||||
cont->index = i;
|
||||
list_add_tail(&cont->node, &commands);
|
||||
__t1_getreg(wc, 0x70 + (i>>1), cont->cmd);
|
||||
}
|
||||
|
||||
list_for_each_entry_reverse(cont, &commands, node) {
|
||||
i = cont->index;
|
||||
a = __t1_getresult(wc, cont->cmd);
|
||||
free_cmd(wc, cont->cmd);
|
||||
cont->cmd = NULL;
|
||||
if (a > -1) {
|
||||
/* Get high channel in low bits */
|
||||
rxs = (a & 0xf);
|
||||
@@ -1228,6 +1344,21 @@ static inline void t1_check_sigbits(struct t1 *wc)
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
while (!list_empty(&commands)) {
|
||||
cont = container_of(commands.next,
|
||||
struct command_container, node);
|
||||
if (unlikely(cont->cmd)) {
|
||||
/* We do not care about the result, let's just wait for
|
||||
* the rest of the system to finish with it. */
|
||||
__t1_getresult(wc, cont->cmd);
|
||||
free_cmd(wc, cont->cmd);
|
||||
cont->cmd = NULL;
|
||||
}
|
||||
list_del(&cont->node);
|
||||
kfree(cont);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct maint_work_struct {
|
||||
@@ -1253,7 +1384,7 @@ static void t1xxp_maint_work(struct work_struct *work)
|
||||
int reg = 0;
|
||||
int cmd = w->cmd;
|
||||
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
switch (cmd) {
|
||||
case DAHDI_MAINT_NONE:
|
||||
t1_info(wc, "Clearing all maint modes\n");
|
||||
@@ -1325,7 +1456,7 @@ static int t1xxp_maint(struct dahdi_span *span, int cmd)
|
||||
struct maint_work_struct *work;
|
||||
struct t1 *wc = container_of(span, struct t1, span);
|
||||
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
switch (cmd) {
|
||||
case DAHDI_MAINT_NONE:
|
||||
case DAHDI_MAINT_LOCALLOOP:
|
||||
@@ -1574,6 +1705,7 @@ static int vpm_start_load(struct t1 *wc)
|
||||
work->wc = wc;
|
||||
|
||||
queue_work(wc->wq, &work->work);
|
||||
wc->not_ready++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1620,12 +1752,23 @@ static void check_and_load_vpm(struct t1 *wc)
|
||||
options.vpmnlptype = vpmnlptype;
|
||||
options.vpmnlpthresh = vpmnlpthresh;
|
||||
options.vpmnlpmaxsupp = vpmnlpmaxsupp;
|
||||
options.channels = (TYPE_T1 == wc->spantype) ? 24 : 32;
|
||||
options.channels = dahdi_is_t1_span(&wc->span) ? 24 : 32;
|
||||
|
||||
/* We do not want to check that the VPM is alive until after we're
|
||||
* done setting it up here, an hour should cover it... */
|
||||
wc->vpm_check = jiffies + HZ*3600;
|
||||
|
||||
/* If there was one already allocated, let's free it. */
|
||||
if (wc->vpmadt032) {
|
||||
vpmadt = wc->vpmadt032;
|
||||
clear_bit(VPM150M_ACTIVE, &vpmadt->control);
|
||||
flush_workqueue(vpmadt->wq);
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
wc->vpmadt032 = NULL;
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
vpmadt032_free(vpmadt);
|
||||
}
|
||||
|
||||
vpmadt = vpmadt032_alloc(&options);
|
||||
if (!vpmadt)
|
||||
return;
|
||||
@@ -1680,7 +1823,7 @@ static void t1_chan_set_sigcap(struct dahdi_span *span, int x)
|
||||
struct dahdi_chan *chan = wc->chans[x];
|
||||
chan->sigcap = DAHDI_SIG_CLEAR;
|
||||
/* E&M variant supported depends on span type */
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
/* E1 sigcap setup */
|
||||
if (span->lineconfig & DAHDI_CONFIG_CCS) {
|
||||
/* CCS setup */
|
||||
@@ -1763,84 +1906,162 @@ static void t1xxp_disable_hw_preechocan(struct dahdi_chan *chan)
|
||||
vpmoct_preecho_disable(wc->vpmoct, chan->chanpos - 1);
|
||||
}
|
||||
|
||||
static const struct dahdi_span_ops t1_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.spanconfig = t1xxp_spanconfig,
|
||||
.chanconfig = t1xxp_chanconfig,
|
||||
.startup = t1xxp_startup,
|
||||
.rbsbits = t1xxp_rbsbits,
|
||||
.maint = t1xxp_maint,
|
||||
.ioctl = t1xxp_ioctl,
|
||||
#ifdef VPM_SUPPORT
|
||||
.enable_hw_preechocan = t1xxp_enable_hw_preechocan,
|
||||
.disable_hw_preechocan = t1xxp_disable_hw_preechocan,
|
||||
.echocan_create = t1xxp_echocan_create,
|
||||
.echocan_name = t1xxp_echocan_name,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int t1_software_init(struct t1 *wc)
|
||||
/**
|
||||
* t1_software_init - Initialize the board for the given type.
|
||||
* @wc: The board to initialize.
|
||||
* @type: The type of board we are, T1 / E1
|
||||
*
|
||||
* This function is called at startup and when the type of the span is changed
|
||||
* via the dahdi_device before the span is assigned a number.
|
||||
*
|
||||
*/
|
||||
static int t1_software_init(struct t1 *wc, enum linemode type)
|
||||
{
|
||||
int x;
|
||||
int num;
|
||||
struct pci_dev *pdev = wc->vb.pdev;
|
||||
struct dahdi_chan *chans[32] = {NULL,};
|
||||
struct dahdi_echocan_state *ec[32] = {NULL,};
|
||||
unsigned long flags;
|
||||
int res = 0;
|
||||
|
||||
/* Find position */
|
||||
for (x = 0; x < ARRAY_SIZE(ifaces); ++x) {
|
||||
if (ifaces[x] == wc) {
|
||||
debug_printk(wc, 1, "software init for card %d\n", x);
|
||||
break;
|
||||
}
|
||||
/* We may already be setup properly. */
|
||||
if (wc->span.channels == ((E1 == type) ? 31 : 24))
|
||||
return 0;
|
||||
|
||||
for (x = 0; x < ((E1 == type) ? 31 : 24); x++) {
|
||||
chans[x] = kzalloc(sizeof(*chans[x]), GFP_KERNEL);
|
||||
ec[x] = kzalloc(sizeof(*ec[x]), GFP_KERNEL);
|
||||
if (!chans[x] || !ec[x])
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (x == ARRAY_SIZE(ifaces))
|
||||
return -1;
|
||||
|
||||
t4_serial_setup(wc);
|
||||
|
||||
num = x;
|
||||
sprintf(wc->span.name, "WCT1/%d", num);
|
||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, num);
|
||||
wc->span.manufacturer = "Digium";
|
||||
set_span_devicetype(wc);
|
||||
|
||||
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
|
||||
"PCI Bus %02d Slot %02d", pdev->bus->number,
|
||||
PCI_SLOT(pdev->devfn) + 1);
|
||||
/* Because the interrupt handler is running, we need to atomically
|
||||
* swap the channel arrays. */
|
||||
spin_lock_irqsave(&wc->reglock, flags);
|
||||
_t1_free_channels(wc);
|
||||
memcpy(wc->chans, chans, sizeof(wc->chans));
|
||||
memcpy(wc->ec, ec, sizeof(wc->ec));
|
||||
memset(chans, 0, sizeof(chans));
|
||||
memset(ec, 0, sizeof(ec));
|
||||
|
||||
wc->span.irq = pdev->irq;
|
||||
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
switch (type) {
|
||||
case E1:
|
||||
wc->span.channels = 31;
|
||||
wc->span.spantype = "E1";
|
||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 |
|
||||
DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
|
||||
wc->span.deflaw = DAHDI_LAW_ALAW;
|
||||
} else {
|
||||
break;
|
||||
case T1:
|
||||
wc->span.channels = 24;
|
||||
wc->span.spantype = "T1";
|
||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS |
|
||||
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||
break;
|
||||
case J1:
|
||||
wc->span.channels = 24;
|
||||
wc->span.spantype = "J1";
|
||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS |
|
||||
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||
break;
|
||||
default:
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
res = -EINVAL;
|
||||
goto error_exit;
|
||||
}
|
||||
wc->span.chans = wc->chans;
|
||||
|
||||
spin_unlock_irqrestore(&wc->reglock, flags);
|
||||
|
||||
if (!wc->ddev->location)
|
||||
return -ENOMEM;
|
||||
|
||||
t1_info(wc, "Setting up global serial parameters for %s\n",
|
||||
wc->span.spantype);
|
||||
|
||||
t4_serial_setup(wc);
|
||||
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
|
||||
for (x = 0; x < wc->span.channels; x++) {
|
||||
sprintf(wc->chans[x]->name, "WCT1/%d/%d", num, x + 1);
|
||||
sprintf(wc->chans[x]->name, "%s/%d", wc->span.name, x + 1);
|
||||
t1_chan_set_sigcap(&wc->span, x);
|
||||
wc->chans[x]->pvt = wc;
|
||||
wc->chans[x]->chanpos = x + 1;
|
||||
}
|
||||
|
||||
check_and_load_vpm(wc);
|
||||
|
||||
wc->span.ops = &t1_span_ops;
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
t1_info(wc, "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
set_span_devicetype(wc);
|
||||
|
||||
return 0;
|
||||
|
||||
error_exit:
|
||||
for (x = 0; x < ARRAY_SIZE(chans); ++x) {
|
||||
kfree(chans[x]);
|
||||
kfree(ec[x]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* t1xx_set_linemode - Change the type of span before assignment.
|
||||
* @span: The span to change.
|
||||
* @linemode: Text string for the line mode.
|
||||
*
|
||||
* This function may be called after the dahdi_device is registered but
|
||||
* before the spans are assigned numbers (and are visible to the rest of
|
||||
* DAHDI).
|
||||
*
|
||||
*/
|
||||
static int t1xxp_set_linemode(struct dahdi_span *span, const char *linemode)
|
||||
{
|
||||
int res;
|
||||
struct t1 *wc = container_of(span, struct t1, span);
|
||||
|
||||
/* We may already be set to the requested type. */
|
||||
if (!strcasecmp(span->spantype, linemode))
|
||||
return 0;
|
||||
|
||||
res = t1_wait_for_ready(wc);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
/* Stop the processing of the channels since we're going to change
|
||||
* them. */
|
||||
clear_bit(INITIALIZED, &wc->bit_flags);
|
||||
smp_mb__after_clear_bit();
|
||||
del_timer_sync(&wc->timer);
|
||||
flush_workqueue(wc->wq);
|
||||
|
||||
if (!strcasecmp(linemode, "t1")) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
"Changing from %s to T1 line mode.\n",
|
||||
wc->span.spantype);
|
||||
res = t1_software_init(wc, T1);
|
||||
} else if (!strcasecmp(linemode, "e1")) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
"Changing from %s to E1 line mode.\n",
|
||||
wc->span.spantype);
|
||||
res = t1_software_init(wc, E1);
|
||||
} else if (!strcasecmp(linemode, "j1")) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
"Changing from %s to E1 line mode.\n",
|
||||
wc->span.spantype);
|
||||
res = t1_software_init(wc, J1);
|
||||
} else {
|
||||
dev_err(&wc->vb.pdev->dev,
|
||||
"'%s' is an unknown linemode.\n", linemode);
|
||||
res = -EINVAL;
|
||||
}
|
||||
|
||||
/* Since we probably reallocated the channels we need to make
|
||||
* sure they are configured before setting INITIALIZED again. */
|
||||
if (!res) {
|
||||
dahdi_init_span(span);
|
||||
set_bit(INITIALIZED, &wc->bit_flags);
|
||||
mod_timer(&wc->timer, jiffies + HZ/5);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -1859,39 +2080,55 @@ static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned i
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int t1_hardware_post_init(struct t1 *wc)
|
||||
static int t1_hardware_post_init(struct t1 *wc, enum linemode *type)
|
||||
{
|
||||
int res;
|
||||
unsigned int reg;
|
||||
int reg;
|
||||
int x;
|
||||
|
||||
/* T1 or E1 */
|
||||
if (t1e1override > -1) {
|
||||
if (t1e1override)
|
||||
wc->spantype = TYPE_E1;
|
||||
else
|
||||
wc->spantype = TYPE_T1;
|
||||
if ((-1 != t1e1override) || (-1 != j1mode)) {
|
||||
*type = (t1e1override) ? E1 : (j1mode) ? J1 : T1;
|
||||
} else {
|
||||
u8 pins;
|
||||
res = t1_getpins(wc, &pins);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
wc->spantype = (pins & 0x01) ? TYPE_T1 : TYPE_E1;
|
||||
if (!strcasecmp(default_linemode, "e1")) {
|
||||
*type = E1;
|
||||
} else if (!strcasecmp(default_linemode, "t1")) {
|
||||
*type = T1;
|
||||
} else if (!strcasecmp(default_linemode, "j1")) {
|
||||
*type = J1;
|
||||
} else {
|
||||
u8 pins;
|
||||
res = t1_getpins(wc, &pins);
|
||||
if (res)
|
||||
return res;
|
||||
*type = (pins & 0x01) ? T1 : E1;
|
||||
}
|
||||
}
|
||||
debug_printk(wc, 1, "spantype: %s\n", 1 == wc->spantype ? "T1" : "E1");
|
||||
debug_printk(wc, 1, "linemode: %s\n", (*type == T1) ? "T1" :
|
||||
(J1 == *type) ? "J1" : "E1");
|
||||
|
||||
/* what version of the FALC are we using? */
|
||||
reg = t1_setreg(wc, 0x4a, 0xaa);
|
||||
reg = t1_getreg(wc, 0x4a);
|
||||
if (reg < 0) {
|
||||
t1_info(wc, "Failed to read FALC version (%d)\n", reg);
|
||||
return -EIO;
|
||||
}
|
||||
debug_printk(wc, 1, "FALC version: %08x\n", reg);
|
||||
|
||||
/* make sure reads and writes work */
|
||||
for (x = 0; x < 256; x++) {
|
||||
t1_setreg(wc, 0x14, x);
|
||||
reg = t1_getreg(wc, 0x14);
|
||||
if (reg != x)
|
||||
t1_info(wc, "Wrote '%x' but read '%x'\n", x, reg);
|
||||
if (reg < 0) {
|
||||
t1_info(wc, "Failed register read (%d)\n", reg);
|
||||
return -EIO;
|
||||
}
|
||||
if (reg != x) {
|
||||
t1_info(wc, "Register test failed. "
|
||||
"Wrote '%x' but read '%x'\n", x, reg);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
t1_setleds(wc, wc->ledstate);
|
||||
@@ -1899,19 +2136,41 @@ static int t1_hardware_post_init(struct t1 *wc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void t1_check_alarms(struct t1 *wc)
|
||||
static void t1_check_alarms(struct t1 *wc)
|
||||
{
|
||||
unsigned char c,d;
|
||||
int alarms;
|
||||
int x,j;
|
||||
unsigned char fmr4; /* must read this always */
|
||||
struct command *cmds[3];
|
||||
|
||||
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
|
||||
return;
|
||||
|
||||
c = t1_getreg(wc, 0x4c);
|
||||
fmr4 = t1_getreg(wc, 0x20); /* must read this even if we don't use it */
|
||||
d = t1_getreg(wc, 0x4d);
|
||||
for (x = 0; x < ARRAY_SIZE(cmds); ++x) {
|
||||
cmds[x] = get_free_cmd(wc);
|
||||
if (!cmds[x]) {
|
||||
WARN_ON(1);
|
||||
for (x = 0; x < ARRAY_SIZE(cmds); ++x)
|
||||
free_cmd(wc, cmds[x]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Since this is voicebus, if we issue all the reads initially and then
|
||||
* check the results we can save ourselves some time. Otherwise, each
|
||||
* read will take a minimum of 3ms to go through the complete pipeline.
|
||||
*/
|
||||
__t1_getreg(wc, 0x4c, cmds[0]);
|
||||
__t1_getreg(wc, 0x20, cmds[1]); /* must read this even if not used */
|
||||
__t1_getreg(wc, 0x4d, cmds[2]);
|
||||
|
||||
d = __t1_getresult(wc, cmds[2]);
|
||||
fmr4 = __t1_getresult(wc, cmds[1]);
|
||||
c = __t1_getresult(wc, cmds[0]);
|
||||
|
||||
for (x=0; x < ARRAY_SIZE(cmds); ++x)
|
||||
free_cmd(wc, cmds[x]);
|
||||
|
||||
/* Assume no alarms */
|
||||
alarms = 0;
|
||||
@@ -1919,7 +2178,7 @@ static inline void t1_check_alarms(struct t1 *wc)
|
||||
/* And consider only carrier alarms */
|
||||
wc->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN);
|
||||
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
if (c & 0x04) {
|
||||
/* No multiframe found, force RAI high after 400ms only if
|
||||
we haven't found a multiframe since last loss
|
||||
@@ -2245,7 +2504,7 @@ static inline void t1_receiveprep(struct t1 *wc, const u8* sframe)
|
||||
wc->rxident = eframe[EFRAME_SIZE + 1];
|
||||
wc->statreg = eframe[EFRAME_SIZE + 2];
|
||||
if (wc->rxident != expected) {
|
||||
wc->span.irqmisses++;
|
||||
wc->ddev->irqmisses++;
|
||||
_resend_cmds(wc);
|
||||
if (unlikely(debug)) {
|
||||
t1_info(wc, "oops: rxident=%d "
|
||||
@@ -2327,11 +2586,11 @@ static void timer_work_func(struct work_struct *work)
|
||||
{
|
||||
struct t1 *wc = container_of(work, struct t1, timer_work);
|
||||
#endif
|
||||
if (test_bit(INITIALIZED, &wc->bit_flags))
|
||||
mod_timer(&wc->timer, jiffies + HZ/30);
|
||||
t1_do_counters(wc);
|
||||
t1_check_alarms(wc);
|
||||
t1_check_sigbits(wc);
|
||||
if (test_bit(INITIALIZED, &wc->bit_flags))
|
||||
mod_timer(&wc->timer, jiffies + HZ/10);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
@@ -2528,14 +2787,31 @@ static inline void remove_sysfs_files(struct t1 *wc) { return; }
|
||||
|
||||
#endif /* CONFIG_VOICEBUS_SYSFS */
|
||||
|
||||
static const struct dahdi_span_ops t1_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.spanconfig = t1xxp_spanconfig,
|
||||
.chanconfig = t1xxp_chanconfig,
|
||||
.startup = t1xxp_startup,
|
||||
.rbsbits = t1xxp_rbsbits,
|
||||
.maint = t1xxp_maint,
|
||||
.ioctl = t1xxp_ioctl,
|
||||
.set_spantype = t1xxp_set_linemode,
|
||||
#ifdef VPM_SUPPORT
|
||||
.enable_hw_preechocan = t1xxp_enable_hw_preechocan,
|
||||
.disable_hw_preechocan = t1xxp_disable_hw_preechocan,
|
||||
.echocan_create = t1xxp_echocan_create,
|
||||
.echocan_name = t1xxp_echocan_name,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct t1 *wc;
|
||||
struct t1_desc *d = (struct t1_desc *) ent->driver_data;
|
||||
const struct t1_desc *d = (struct t1_desc *) ent->driver_data;
|
||||
unsigned int x;
|
||||
int res;
|
||||
unsigned int index = -1;
|
||||
enum linemode type;
|
||||
|
||||
for (x = 0; x < ARRAY_SIZE(ifaces); x++) {
|
||||
if (!ifaces[x]) {
|
||||
@@ -2554,18 +2830,22 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
||||
if (!wc)
|
||||
return -ENOMEM;
|
||||
|
||||
wc->not_ready = 1;
|
||||
/* Set the performance counters to -1 since this card currently does
|
||||
* not support collecting them. */
|
||||
memset(&wc->span.count, -1, sizeof(wc->span.count));
|
||||
|
||||
ifaces[index] = wc;
|
||||
|
||||
sprintf(wc->span.name, "WCT1/%d", index);
|
||||
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d",
|
||||
d->name, index);
|
||||
wc->not_ready = 1;
|
||||
wc->ledstate = -1;
|
||||
wc->variety = d->name;
|
||||
wc->txident = 1;
|
||||
spin_lock_init(&wc->reglock);
|
||||
INIT_LIST_HEAD(&wc->active_cmds);
|
||||
INIT_LIST_HEAD(&wc->pending_cmds);
|
||||
|
||||
wc->variety = d->name;
|
||||
wc->txident = 1;
|
||||
|
||||
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
wc->timer.function = te12xp_timer;
|
||||
wc->timer.data = (unsigned long)wc;
|
||||
@@ -2586,6 +2866,22 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
||||
INIT_WORK(&wc->vpm_check_work, vpm_check_func);
|
||||
# endif
|
||||
|
||||
wc->ddev = dahdi_create_device();
|
||||
if (!wc->ddev) {
|
||||
ifaces[index] = NULL;
|
||||
kfree(wc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
wc->ddev->manufacturer = "Digium";
|
||||
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
|
||||
pdev->bus->number,
|
||||
PCI_SLOT(pdev->devfn) + 1);
|
||||
if (!wc->ddev->location) {
|
||||
ifaces[index] = NULL;
|
||||
kfree(wc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VOICEBUS_ECREFERENCE
|
||||
for (x = 0; x < ARRAY_SIZE(wc->ec_reference); ++x) {
|
||||
/* 256 is used here since it is the largest power of two that
|
||||
@@ -2602,6 +2898,13 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
||||
}
|
||||
#endif /* CONFIG_VOICEBUS_ECREFERENCE */
|
||||
|
||||
#ifdef CONFIG_VOICEBUS_DISABLE_ASPM
|
||||
if (is_pcie(wc)) {
|
||||
pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S |
|
||||
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
|
||||
};
|
||||
#endif
|
||||
|
||||
snprintf(wc->name, sizeof(wc->name)-1, "wcte12xp%d", index);
|
||||
pci_set_drvdata(pdev, wc);
|
||||
wc->vb.ops = &voicebus_operations;
|
||||
@@ -2617,6 +2920,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
||||
wc->wq = create_singlethread_workqueue(wc->name);
|
||||
if (!wc->wq) {
|
||||
kfree(wc);
|
||||
ifaces[index] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -2630,36 +2934,33 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
||||
if (voicebus_start(&wc->vb)) {
|
||||
voicebus_release(&wc->vb);
|
||||
free_wc(wc);
|
||||
ifaces[index] = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
res = t1_hardware_post_init(wc);
|
||||
res = t1_hardware_post_init(wc, &type);
|
||||
if (res) {
|
||||
voicebus_release(&wc->vb);
|
||||
free_wc(wc);
|
||||
ifaces[index] = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
|
||||
wc->chans[x] = kzalloc(sizeof(*wc->chans[x]), GFP_KERNEL);
|
||||
if (!wc->chans[x]) {
|
||||
free_wc(wc);
|
||||
ifaces[index] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
wc->span.chans = wc->chans;
|
||||
|
||||
wc->ec[x] = kzalloc(sizeof(*wc->ec[x]), GFP_KERNEL);
|
||||
if (!wc->ec[x]) {
|
||||
free_wc(wc);
|
||||
ifaces[index] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
res = t1_software_init(wc);
|
||||
res = t1_software_init(wc, type);
|
||||
if (res) {
|
||||
voicebus_release(&wc->vb);
|
||||
free_wc(wc);
|
||||
ifaces[index] = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
wc->span.ops = &t1_span_ops;
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
res = dahdi_register_device(wc->ddev, &wc->vb.pdev->dev);
|
||||
if (res) {
|
||||
t1_info(wc, "Unable to register with DAHDI\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2669,10 +2970,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
|
||||
t1_info(wc, "Found a %s\n", wc->variety);
|
||||
voicebus_unlock_latency(&wc->vb);
|
||||
|
||||
/* If there is VPMADT032 module attached to this device, it will
|
||||
* signal ready after the channels are configured and ready for use. */
|
||||
if (!wc->vpmadt032)
|
||||
wc->not_ready--;
|
||||
wc->not_ready--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2687,7 +2985,7 @@ static void __devexit te12xp_remove_one(struct pci_dev *pdev)
|
||||
if (!wc)
|
||||
return;
|
||||
|
||||
dahdi_unregister(&wc->span);
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
|
||||
remove_sysfs_files(wc);
|
||||
|
||||
@@ -2778,6 +3076,22 @@ static int __init te12xp_init(void)
|
||||
if (!cmd_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
if ((-1 != t1e1override) || (-1 != j1mode)) {
|
||||
pr_info("'t1e1override' and 'j1mode' are deprecated. "
|
||||
"Please use 'default_linemode' instead.\n");
|
||||
/* If someone is setting j1mode, then, t1e1override most likely
|
||||
* needs to be forced to t1 mode */
|
||||
if (j1mode > 0)
|
||||
t1e1override = 0;
|
||||
} else if (strcasecmp(default_linemode, "auto") &&
|
||||
strcasecmp(default_linemode, "t1") &&
|
||||
strcasecmp(default_linemode, "j1") &&
|
||||
strcasecmp(default_linemode, "e1")) {
|
||||
pr_err("'%s' is an unknown span type.\n", default_linemode);
|
||||
default_linemode = "auto";
|
||||
kmem_cache_destroy(cmd_cache);
|
||||
return -EINVAL;
|
||||
}
|
||||
res = dahdi_pci_module(&te12xp_driver);
|
||||
if (res) {
|
||||
kmem_cache_destroy(cmd_cache);
|
||||
@@ -2796,6 +3110,9 @@ static void __exit te12xp_cleanup(void)
|
||||
|
||||
module_param(debug, int, S_IRUGO | S_IWUSR);
|
||||
module_param(t1e1override, int, S_IRUGO | S_IWUSR);
|
||||
module_param(default_linemode, charp, S_IRUGO);
|
||||
MODULE_PARM_DESC(default_linemode, "\"auto\"(default), \"e1\", or \"t1\". "
|
||||
"\"auto\" will use the value from the hardware jumpers.");
|
||||
module_param(j1mode, int, S_IRUGO | S_IWUSR);
|
||||
module_param(alarmdebounce, int, S_IRUGO | S_IWUSR);
|
||||
module_param(losalarmdebounce, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
@@ -74,8 +74,11 @@
|
||||
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
|
||||
//TODO: make a separate macro
|
||||
|
||||
#define TYPE_T1 1
|
||||
#define TYPE_E1 2
|
||||
enum linemode {
|
||||
T1 = 1,
|
||||
E1,
|
||||
J1,
|
||||
};
|
||||
|
||||
struct command {
|
||||
struct list_head node;
|
||||
@@ -94,7 +97,6 @@ struct t1 {
|
||||
unsigned char txident;
|
||||
unsigned char rxident;
|
||||
unsigned char statreg; /* bit 0 = vpmadt032 int */
|
||||
int spantype;
|
||||
struct {
|
||||
unsigned int nmf:1;
|
||||
unsigned int sendingyellow:1;
|
||||
@@ -116,6 +118,7 @@ struct t1 {
|
||||
unsigned long alarmtimer;
|
||||
unsigned char ledstate;
|
||||
unsigned char vpm_check_count;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span; /* Span */
|
||||
struct dahdi_chan *chans[32]; /* Channels */
|
||||
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
|
||||
|
||||
@@ -733,6 +733,7 @@ static const struct dahdi_span_ops BRI_span_ops = {
|
||||
.maint = xpp_maint,
|
||||
.echocan_create = xpp_echocan_create,
|
||||
.echocan_name = xpp_echocan_name,
|
||||
.assigned = xpp_span_assigned,
|
||||
#ifdef DAHDI_SYNC_TICK
|
||||
.sync_tick = dahdi_sync_tick,
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,6 @@ enum fxo_opcodes {
|
||||
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
|
||||
/**/
|
||||
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, XPD_STATE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
||||
};
|
||||
|
||||
@@ -1351,7 +1351,8 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
|
||||
#endif
|
||||
|
||||
static const char dtmf_digits[] = {
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#', 'A', 'B', 'C', 'D'
|
||||
'D', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#',
|
||||
'A', 'B', 'C'
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1373,12 +1374,6 @@ static void process_dtmf(xpd_t *xpd, uint portnum, byte val)
|
||||
return;
|
||||
priv = xpd->priv;
|
||||
val &= 0xF;
|
||||
if(val <= 0) {
|
||||
if(key_down)
|
||||
XPD_NOTICE(xpd, "Bad DTMF value %d. Ignored\n", val);
|
||||
return;
|
||||
}
|
||||
val--;
|
||||
digit = dtmf_digits[val];
|
||||
want_mute = IS_SET(priv->want_dtmf_mute, portnum);
|
||||
want_event = IS_SET(priv->want_dtmf_events, portnum);
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
enum fxs_opcodes {
|
||||
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
||||
/**/
|
||||
XPROTO_NAME(FXS, XPD_STATE) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kmod.h>
|
||||
#include "xdefs.h"
|
||||
#include "xpd.h"
|
||||
#include "xpp_dahdi.h"
|
||||
@@ -655,6 +656,15 @@ static void global_packet_dump(const char *msg, xpacket_t *pack)
|
||||
|
||||
#define MAX_PATH_STR 128
|
||||
|
||||
#ifndef UMH_WAIT_PROC
|
||||
/*
|
||||
* - UMH_WAIT_PROC was introduced as enum in 2.6.23
|
||||
* with a value of 1
|
||||
* - It was changed to a macro (and it's value was modified) in 3.3.0
|
||||
*/
|
||||
#define UMH_WAIT_PROC 1
|
||||
#endif
|
||||
|
||||
int run_initialize_registers(xpd_t *xpd)
|
||||
{
|
||||
int ret;
|
||||
@@ -737,7 +747,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
|
||||
init_card, xpd->type, xbus->revision);
|
||||
ret = call_usermodehelper(init_card, argv, envp, 1);
|
||||
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
|
||||
/*
|
||||
* Carefully report results
|
||||
*/
|
||||
|
||||
@@ -80,6 +80,7 @@ static int pri_shutdown(struct dahdi_span *span);
|
||||
static int pri_rbsbits(struct dahdi_chan *chan, int bits);
|
||||
static int pri_lineconfig(xpd_t *xpd, int lineconfig);
|
||||
static void send_idlebits(xpd_t *xpd, bool saveold);
|
||||
static int apply_pri_protocol(xpd_t *xpd);
|
||||
|
||||
#define PROC_REGISTER_FNAME "slics"
|
||||
|
||||
@@ -90,17 +91,29 @@ enum pri_protocol {
|
||||
PRI_PROTO_J1 = 3
|
||||
};
|
||||
|
||||
static const char *protocol_names[] = {
|
||||
[PRI_PROTO_0] = "??", /* unknown */
|
||||
[PRI_PROTO_E1] = "E1",
|
||||
[PRI_PROTO_T1] = "T1",
|
||||
[PRI_PROTO_J1] = "J1"
|
||||
};
|
||||
|
||||
static const char *pri_protocol_name(enum pri_protocol pri_protocol)
|
||||
{
|
||||
static const char *protocol_names[] = {
|
||||
[PRI_PROTO_0] = "??", /* unknown */
|
||||
[PRI_PROTO_E1] = "E1",
|
||||
[PRI_PROTO_T1] = "T1",
|
||||
[PRI_PROTO_J1] = "J1"
|
||||
};
|
||||
return protocol_names[pri_protocol];
|
||||
}
|
||||
|
||||
static enum pri_protocol pri_protocol_bystr(const char *spantype)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(protocol_names); i++) {
|
||||
if (strcasecmp(protocol_names[i], spantype) == 0)
|
||||
return i;
|
||||
}
|
||||
return PRI_PROTO_0;
|
||||
}
|
||||
|
||||
static int pri_num_channels(enum pri_protocol pri_protocol)
|
||||
{
|
||||
static int num_channels[] = {
|
||||
@@ -551,12 +564,14 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
unsigned int dchan_num;
|
||||
int default_lineconfig = 0;
|
||||
int ret;
|
||||
struct phonedev *phonedev;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
XPD_NOTICE(xpd, "Registered as span %d. Cannot do setup pri protocol (%s)\n",
|
||||
PHONEDEV(xpd).span.spanno, __FUNCTION__);
|
||||
phonedev = &PHONEDEV(xpd);
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &phonedev->span.flags)) {
|
||||
XPD_NOTICE(xpd, "%s: %s already assigned as span %d\n",
|
||||
__func__, phonedev->span.name, phonedev->span.spanno);
|
||||
return -EBUSY;
|
||||
}
|
||||
if(priv->pri_protocol != PRI_PROTO_0) {
|
||||
@@ -596,8 +611,8 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
}
|
||||
priv->pri_protocol = set_proto;
|
||||
priv->is_cas = -1;
|
||||
PHONEDEV(xpd).channels = pri_num_channels(set_proto);
|
||||
PHONEDEV(xpd).offhook_state = BITMASK(PHONEDEV(xpd).channels);
|
||||
phonedev->channels = pri_num_channels(set_proto);
|
||||
phonedev->offhook_state = BITMASK(phonedev->channels);
|
||||
CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
|
||||
priv->deflaw = deflaw;
|
||||
priv->dchan_num = dchan_num;
|
||||
@@ -605,7 +620,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
xpd->type_name = type_name(priv->pri_protocol);
|
||||
XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n",
|
||||
pri_protocol_name(set_proto),
|
||||
PHONEDEV(xpd).channels,
|
||||
phonedev->channels,
|
||||
priv->dchan_num,
|
||||
priv->deflaw
|
||||
);
|
||||
@@ -618,7 +633,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
XPD_NOTICE(xpd, "Failed setting PRI default line config\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
return apply_pri_protocol(xpd);
|
||||
}
|
||||
|
||||
static void dahdi_update_syncsrc(xpd_t *xpd)
|
||||
@@ -1040,6 +1055,17 @@ bad_lineconfig:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int pri_set_spantype(struct dahdi_span *span, const char *spantype)
|
||||
{
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
enum pri_protocol set_proto = PRI_PROTO_0;
|
||||
|
||||
XPD_INFO(xpd, "%s: %s\n", __func__, spantype);
|
||||
set_proto = pri_protocol_bystr(spantype);
|
||||
return set_pri_proto(xpd, set_proto);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called only for 'span' keyword in /etc/dahdi/system.conf
|
||||
*/
|
||||
@@ -1215,6 +1241,7 @@ static int pri_audio_notify(struct dahdi_chan *chan, int on)
|
||||
|
||||
static const struct dahdi_span_ops PRI_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_spantype = pri_set_spantype,
|
||||
.spanconfig = pri_spanconfig,
|
||||
.chanconfig = pri_chanconfig,
|
||||
.startup = pri_startup,
|
||||
@@ -1226,6 +1253,7 @@ static const struct dahdi_span_ops PRI_span_ops = {
|
||||
.maint = xpp_maint,
|
||||
.echocan_create = xpp_echocan_create,
|
||||
.echocan_name = xpp_echocan_name,
|
||||
.assigned = xpp_span_assigned,
|
||||
#ifdef DAHDI_SYNC_TICK
|
||||
.sync_tick = dahdi_sync_tick,
|
||||
#endif
|
||||
@@ -1238,7 +1266,7 @@ static const struct dahdi_span_ops PRI_span_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
static int apply_pri_protocol(xpd_t *xpd)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
struct PRI_priv_data *priv;
|
||||
@@ -1248,15 +1276,7 @@ static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
xbus = xpd->xbus;
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!xbus);
|
||||
XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n",
|
||||
(on)?"on":"off",
|
||||
pri_protocol_name(priv->pri_protocol),
|
||||
PHONEDEV(xpd).channels,
|
||||
priv->deflaw);
|
||||
if(!on) {
|
||||
/* Nothing to do yet */
|
||||
return 0;
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "\n");
|
||||
PHONEDEV(xpd).span.spantype = pri_protocol_name(priv->pri_protocol);
|
||||
PHONEDEV(xpd).span.linecompat = pri_linecompat(priv->pri_protocol);
|
||||
PHONEDEV(xpd).span.deflaw = priv->deflaw;
|
||||
@@ -1279,9 +1299,32 @@ static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
}
|
||||
PHONEDEV(xpd).offhook_state = PHONEDEV(xpd).wanted_pcm_mask;
|
||||
PHONEDEV(xpd).span.ops = &PRI_span_ops;
|
||||
PHONEDEV(xpd).span.channels = PHONEDEV(xpd).channels;
|
||||
xpd_set_spanname(xpd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
struct PRI_priv_data *priv;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
xbus = xpd->xbus;
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!xbus);
|
||||
XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n",
|
||||
(on)?"on":"off",
|
||||
pri_protocol_name(priv->pri_protocol),
|
||||
PHONEDEV(xpd).channels,
|
||||
priv->deflaw);
|
||||
if(!on) {
|
||||
/* Nothing to do yet */
|
||||
return 0;
|
||||
}
|
||||
return apply_pri_protocol(xpd);
|
||||
}
|
||||
|
||||
static int PRI_card_dahdi_postregistration(xpd_t *xpd, bool on)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
@@ -2228,19 +2271,20 @@ static DEVICE_ATTR_WRITER(pri_protocol_store, dev, buf, count)
|
||||
BUG_ON(!dev);
|
||||
xpd = dev_to_xpd(dev);
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", buf);
|
||||
if(!xpd)
|
||||
if (!xpd)
|
||||
return -ENODEV;
|
||||
if((i = strcspn(buf, " \r\n")) != 2) {
|
||||
i = strcspn(buf, " \r\n");
|
||||
if (i != 2) {
|
||||
XPD_NOTICE(xpd,
|
||||
"Protocol name '%s' has %d characters (should be 2). Ignored.\n",
|
||||
buf, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if(strnicmp(buf, "E1", 2) == 0)
|
||||
if (strnicmp(buf, "E1", 2) == 0)
|
||||
new_protocol = PRI_PROTO_E1;
|
||||
else if(strnicmp(buf, "T1", 2) == 0)
|
||||
else if (strnicmp(buf, "T1", 2) == 0)
|
||||
new_protocol = PRI_PROTO_T1;
|
||||
else if(strnicmp(buf, "J1", 2) == 0)
|
||||
else if (strnicmp(buf, "J1", 2) == 0)
|
||||
new_protocol = PRI_PROTO_J1;
|
||||
else {
|
||||
XPD_NOTICE(xpd,
|
||||
@@ -2252,7 +2296,8 @@ static DEVICE_ATTR_WRITER(pri_protocol_store, dev, buf, count)
|
||||
return (ret < 0) ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(pri_protocol, S_IRUGO | S_IWUSR, pri_protocol_show, pri_protocol_store);
|
||||
static DEVICE_ATTR(pri_protocol, S_IRUGO | S_IWUSR, pri_protocol_show,
|
||||
pri_protocol_store);
|
||||
|
||||
static DEVICE_ATTR_READER(pri_localloop_show, dev, buf)
|
||||
{
|
||||
|
||||
@@ -61,6 +61,8 @@ extern int debug;
|
||||
static DEF_PARM(uint, command_queue_length, 1500, 0444, "Maximal command queue length");
|
||||
static DEF_PARM(uint, poll_timeout, 1000, 0644, "Timeout (in jiffies) waiting for units to reply");
|
||||
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
|
||||
static DEF_PARM_BOOL(dahdi_autoreg, 0, 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);
|
||||
@@ -776,7 +778,6 @@ static int xpd_initialize(xpd_t *xpd)
|
||||
goto out;
|
||||
}
|
||||
XPD_INFO(xpd, "Initialized: %s\n", xpd->type_name);
|
||||
xpd_post_init(xpd);
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
@@ -810,6 +811,29 @@ static int xbus_echocancel(xbus_t *xbus, int on)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xbus_deactivate_xpds(xbus_t *xbus)
|
||||
{
|
||||
unsigned long flags;
|
||||
int unit;
|
||||
int subunit;
|
||||
xpd_t *xpd;
|
||||
|
||||
for (unit = 0; unit < MAX_UNIT; unit++) {
|
||||
xpd = xpd_byaddr(xbus, unit, 0);
|
||||
if (!xpd)
|
||||
continue;
|
||||
for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) {
|
||||
xpd = xpd_byaddr(xbus, unit, subunit);
|
||||
if (!xpd)
|
||||
continue;
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
xpd->card_present = 0;
|
||||
xpd_setstate(xpd, XPD_STATE_NOHW);
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int xbus_initialize(xbus_t *xbus)
|
||||
{
|
||||
int unit;
|
||||
@@ -871,6 +895,120 @@ err:
|
||||
goto out;
|
||||
}
|
||||
|
||||
int xbus_is_registered(xbus_t *xbus)
|
||||
{
|
||||
return xbus->ddev && xbus->ddev->dev.parent;
|
||||
}
|
||||
|
||||
static void xbus_free_ddev(xbus_t *xbus)
|
||||
{
|
||||
if (!xbus->ddev)
|
||||
return;
|
||||
if (xbus->ddev->devicetype)
|
||||
kfree(xbus->ddev->devicetype);
|
||||
xbus->ddev->devicetype = NULL;
|
||||
xbus->ddev->location = NULL;
|
||||
xbus->ddev->hardware_id = NULL;
|
||||
dahdi_free_device(xbus->ddev);
|
||||
xbus->ddev = NULL;
|
||||
}
|
||||
|
||||
int xbus_register_dahdi_device(xbus_t *xbus)
|
||||
{
|
||||
int i;
|
||||
int offset = 0;
|
||||
int ret;
|
||||
|
||||
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
||||
if (xbus_is_registered(xbus)) {
|
||||
XBUS_ERR(xbus, "Already registered to DAHDI\n");
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
xbus->ddev = dahdi_create_device();
|
||||
if (!xbus->ddev) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* This actually describe the dahdi_spaninfo version 3
|
||||
* A bunch of unrelated data exported via a modified ioctl()
|
||||
* What a bummer...
|
||||
*/
|
||||
xbus->ddev->manufacturer = "Xorcom Inc."; /* OK, that's obvious */
|
||||
/* span->spantype = "...."; set in card_dahdi_preregistration() */
|
||||
/*
|
||||
* Yes, this basically duplicates information available
|
||||
* from the description field. If some more is needed
|
||||
* why not add it there?
|
||||
* OK, let's add to the kernel more useless info.
|
||||
*/
|
||||
xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2");
|
||||
if (!xbus->ddev->devicetype) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* location is the only usefull new data item.
|
||||
* For our devices it was available for ages via:
|
||||
* - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...)
|
||||
* - The same info in "/proc/xpp/xbuses"
|
||||
* - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute
|
||||
* So let's also export it via the newfangled "location" field.
|
||||
*/
|
||||
xbus->ddev->location = xbus->connector;
|
||||
xbus->ddev->hardware_id = xbus->label;
|
||||
|
||||
/*
|
||||
* Prepare the span list
|
||||
*/
|
||||
for (i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
if (xpd && IS_PHONEDEV(xpd)) {
|
||||
XPD_DBG(DEVICES, xpd, "offset=%d\n", offset);
|
||||
xpd_dahdi_preregister(xpd, offset++);
|
||||
}
|
||||
}
|
||||
if (dahdi_register_device(xbus->ddev, &xbus->astribank)) {
|
||||
XBUS_ERR(xbus, "Failed to dahdi_register_device()\n");
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
if (xpd && IS_PHONEDEV(xpd)) {
|
||||
XPD_DBG(DEVICES, xpd, "\n");
|
||||
xpd_dahdi_postregister(xpd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
xbus_free_ddev(xbus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void xbus_unregister_dahdi_device(xbus_t *xbus)
|
||||
{
|
||||
int i;
|
||||
|
||||
XBUS_NOTICE(xbus, "%s\n", __func__);
|
||||
for(i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
xpd_dahdi_preunregister(xpd);
|
||||
}
|
||||
if (xbus->ddev) {
|
||||
dahdi_unregister_device(xbus->ddev);
|
||||
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
|
||||
xbus_free_ddev(xbus);
|
||||
}
|
||||
for(i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
xpd_dahdi_postunregister(xpd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This must be called from synchronous (non-interrupt) context
|
||||
* it returns only when all XPD's on the bus are detected and
|
||||
@@ -934,6 +1072,8 @@ void xbus_populate(void *data)
|
||||
*/
|
||||
xbus_request_sync(xbus, SYNC_MODE_PLL);
|
||||
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
|
||||
if (dahdi_autoreg)
|
||||
xbus_register_dahdi_device(xbus);
|
||||
out:
|
||||
XBUS_DBG(DEVICES, xbus, "Leaving\n");
|
||||
wake_up_interruptible_all(&worker->wait_for_xpd_initialization);
|
||||
@@ -1206,12 +1346,13 @@ void xbus_deactivate(xbus_t *xbus)
|
||||
xbus_request_sync(xbus, SYNC_MODE_NONE); /* no more ticks */
|
||||
elect_syncer("deactivate");
|
||||
xbus_echocancel(xbus, 0);
|
||||
xbus_request_removal(xbus);
|
||||
xbus_deactivate_xpds(xbus);
|
||||
XBUS_DBG(DEVICES, xbus, "[%s] Waiting for queues\n", xbus->label);
|
||||
xbus_command_queue_clean(xbus);
|
||||
xbus_command_queue_waitempty(xbus);
|
||||
xbus_setstate(xbus, XBUS_STATE_DEACTIVATED);
|
||||
worker_reset(xbus);
|
||||
xbus_unregister_dahdi_device(xbus);
|
||||
xbus_release_xpds(xbus); /* taken in xpd_alloc() [kref_init] */
|
||||
}
|
||||
|
||||
@@ -1787,10 +1928,6 @@ err:
|
||||
|
||||
void xbus_core_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_BUSES; i++)
|
||||
BUG_ON(xbus_num(i));
|
||||
xbus_core_cleanup();
|
||||
xpp_driver_exit();
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ struct xbus {
|
||||
char label[LABEL_SIZE];
|
||||
byte revision; /* Protocol revision */
|
||||
struct xbus_transport transport;
|
||||
struct dahdi_device *ddev;
|
||||
|
||||
int num;
|
||||
struct xpd *xpds[MAX_XPDS];
|
||||
@@ -342,6 +343,10 @@ int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
|
||||
void xpd_device_unregister(xpd_t *xpd);
|
||||
int echocancel_xpd(xpd_t *xpd, int on);
|
||||
|
||||
int xbus_is_registered(xbus_t *xbus);
|
||||
int xbus_register_dahdi_device(xbus_t *xbus);
|
||||
void xbus_unregister_dahdi_device(xbus_t *xbus);
|
||||
|
||||
int xpp_driver_init(void);
|
||||
void xpp_driver_exit(void);
|
||||
int xbus_sysfs_transport_create(xbus_t *xbus);
|
||||
|
||||
@@ -438,16 +438,6 @@ static void astribank_release(struct device *dev)
|
||||
xbus_free(xbus);
|
||||
}
|
||||
|
||||
static void toplevel_release(struct device *dev)
|
||||
{
|
||||
NOTICE("%s\n", __func__);
|
||||
}
|
||||
|
||||
static struct device toplevel_device = {
|
||||
.release = toplevel_release,
|
||||
/* No Parent */
|
||||
};
|
||||
|
||||
static struct bus_type toplevel_bus_type = {
|
||||
.name = "astribanks",
|
||||
.match = astribank_match,
|
||||
@@ -623,6 +613,10 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* For backward compatibility with old dahdi-tools
|
||||
* Remove after dahdi_registration is upgraded
|
||||
*/
|
||||
static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
@@ -631,19 +625,34 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
||||
|
||||
BUG_ON(!dev);
|
||||
xpd = dev_to_xpd(dev);
|
||||
if(!xpd)
|
||||
if (!xpd)
|
||||
return -ENODEV;
|
||||
ret = sscanf(buf, "%d", &dahdi_reg);
|
||||
if(ret != 1)
|
||||
if (ret != 1)
|
||||
return -EINVAL;
|
||||
if(!XBUS_IS(xpd->xbus, READY))
|
||||
if (!XBUS_IS(xpd->xbus, READY))
|
||||
return -ENODEV;
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", (dahdi_reg) ? "register" : "unregister");
|
||||
if(dahdi_reg)
|
||||
ret = dahdi_register_xpd(xpd);
|
||||
else
|
||||
ret = dahdi_unregister_xpd(xpd);
|
||||
return (ret < 0) ? ret : count;
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"%s -- deprecated (should use pinned-spans)\n",
|
||||
(dahdi_reg) ? "register" : "unregister");
|
||||
if (xbus_is_registered(xpd->xbus)) {
|
||||
if (dahdi_reg) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"already registered %s. Ignored.\n",
|
||||
xpd->xbus->busname);
|
||||
} else {
|
||||
xbus_unregister_dahdi_device(xpd->xbus);
|
||||
}
|
||||
} else {
|
||||
if (!dahdi_reg) {
|
||||
XPD_DBG(DEVICES, xpd,
|
||||
"already unregistered %s. Ignored.\n",
|
||||
xpd->xbus->busname);
|
||||
} else {
|
||||
xbus_register_dahdi_device(xpd->xbus);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_READER(type_show, dev, buf)
|
||||
@@ -964,7 +973,7 @@ int xbus_sysfs_create(xbus_t *xbus)
|
||||
astribank = &xbus->astribank;
|
||||
XBUS_DBG(DEVICES, xbus, "\n");
|
||||
astribank->bus = &toplevel_bus_type;
|
||||
astribank->parent = &toplevel_device;
|
||||
astribank->parent = xbus->transport.transport_device;
|
||||
dev_set_name(astribank, "xbus-%02d", xbus->num);
|
||||
dev_set_drvdata(astribank, xbus);
|
||||
astribank->release = astribank_release;
|
||||
@@ -981,16 +990,10 @@ int __init xpp_driver_init(void)
|
||||
int ret;
|
||||
|
||||
DBG(DEVICES, "SYSFS\n");
|
||||
dev_set_name(&toplevel_device, "astribanks");
|
||||
ret = device_register(&toplevel_device);
|
||||
if (ret) {
|
||||
ERR("%s: toplevel device_register failed: %d\n", __func__, ret);
|
||||
goto failed_toplevel;
|
||||
}
|
||||
if((ret = bus_register(&toplevel_bus_type)) < 0) {
|
||||
ERR("%s: bus_register(%s) failed. Error number %d",
|
||||
__FUNCTION__, toplevel_bus_type.name, ret);
|
||||
goto failed_bus;
|
||||
goto failed_toplevel;
|
||||
}
|
||||
if((ret = driver_register(&xpp_driver)) < 0) {
|
||||
ERR("%s: driver_register(%s) failed. Error number %d",
|
||||
@@ -1007,8 +1010,6 @@ failed_xpd_bus:
|
||||
driver_unregister(&xpp_driver);
|
||||
failed_xpp_driver:
|
||||
bus_unregister(&toplevel_bus_type);
|
||||
failed_bus:
|
||||
device_unregister(&toplevel_device);
|
||||
failed_toplevel:
|
||||
return ret;
|
||||
}
|
||||
@@ -1019,7 +1020,6 @@ void xpp_driver_exit(void)
|
||||
bus_unregister(&xpd_type);
|
||||
driver_unregister(&xpp_driver);
|
||||
bus_unregister(&toplevel_bus_type);
|
||||
device_unregister(&toplevel_device);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xpd_driver_register);
|
||||
|
||||
@@ -144,12 +144,14 @@ typedef unsigned char byte;
|
||||
#define SET_PROC_DIRENTRY_OWNER(p) do { } while(0);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
/* Also don't define this for later RHEL >= 5.2 . 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)
|
||||
typedef int bool;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
/* Also don't define this for later RHEL >= 5.2. */
|
||||
#if defined(RHEL_RELEASE_CODE) && defined(RHEL_RELEASE_VERSION)
|
||||
#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 3)
|
||||
typedef int bool;
|
||||
#endif
|
||||
#else
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
|
||||
@@ -57,7 +57,6 @@ struct proc_dir_entry *xpp_proc_toplevel = NULL;
|
||||
#define DELAY_UNTIL_DIALTONE 3000
|
||||
|
||||
DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644, "Register spans automatically (1) or not (0)");
|
||||
static DEF_PARM_BOOL(prefmaster, 0, 0644, "Do we want to be dahdi preferred sync master");
|
||||
// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit");
|
||||
|
||||
@@ -253,13 +252,6 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xpd_post_init(xpd_t *xpd)
|
||||
{
|
||||
XPD_DBG(DEVICES, xpd, "\n");
|
||||
if(dahdi_autoreg)
|
||||
dahdi_register_xpd(xpd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
/**
|
||||
@@ -568,46 +560,6 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try our best to make asterisk close all channels related to
|
||||
* this Astribank:
|
||||
* - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
|
||||
* - Notify dahdi afterwards about spans (so it can see all changes at once).
|
||||
* - Also send DAHDI_EVENT_REMOVED on all channels.
|
||||
*/
|
||||
void xbus_request_removal(xbus_t *xbus)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
if(xpd) {
|
||||
XPD_DBG(DEVICES, xpd, "\n");
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
xpd->card_present = 0;
|
||||
xpd_setstate(xpd, XPD_STATE_NOHW);
|
||||
PHONEDEV(xpd).span.alarms = DAHDI_ALARM_NOTOPEN;
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
}
|
||||
}
|
||||
/* Now notify dahdi */
|
||||
for(i = 0; i < MAX_XPDS; i++) {
|
||||
xpd_t *xpd = xpd_of(xbus, i);
|
||||
if(xpd) {
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
int j;
|
||||
|
||||
dahdi_alarm_notify(&PHONEDEV(xpd).span);
|
||||
XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
||||
for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
|
||||
dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The xpd isn't open by anyone, we can unregister it and free it
|
||||
*/
|
||||
@@ -615,7 +567,6 @@ void xpd_remove(xpd_t *xpd)
|
||||
{
|
||||
BUG_ON(!xpd);
|
||||
XPD_INFO(xpd, "Remove\n");
|
||||
dahdi_unregister_xpd(xpd);
|
||||
CALL_XMETHOD(card_remove, xpd);
|
||||
xpd_free(xpd);
|
||||
}
|
||||
@@ -734,7 +685,6 @@ int xpp_open(struct dahdi_chan *chan)
|
||||
return -EINVAL;
|
||||
}
|
||||
xpd = chan->pvt;
|
||||
xpd = get_xpd(__FUNCTION__, xpd); /* Returned in xpp_close() */
|
||||
if (!xpd) {
|
||||
NOTICE("open called on a chan with no pvt (xpd)\n");
|
||||
BUG();
|
||||
@@ -775,7 +725,6 @@ int xpp_close(struct dahdi_chan *chan)
|
||||
current->comm, current->pid,
|
||||
atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
atomic_dec(&PHONEDEV(xpd).open_counter); /* from xpp_open() */
|
||||
put_xpd(__FUNCTION__, xpd); /* from xpp_open() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -996,53 +945,18 @@ int xpp_echocan_create(struct dahdi_chan *chan,
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_echocan_create);
|
||||
|
||||
|
||||
/**
|
||||
* Unregister an xpd from dahdi and release related resources
|
||||
* @xpd The xpd to be unregistered
|
||||
* @returns 0 on success, errno otherwise
|
||||
*
|
||||
* Checks that nobody holds an open channel.
|
||||
*
|
||||
* Called by:
|
||||
* - User action through /proc
|
||||
* - During xpd_remove()
|
||||
*/
|
||||
int dahdi_unregister_xpd(xpd_t *xpd)
|
||||
void xpp_span_assigned(struct dahdi_span *span)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
|
||||
BUG_ON(!xpd);
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
|
||||
if (!IS_PHONEDEV(xpd)) {
|
||||
XPD_ERR(xpd, "Not a telephony device\n");
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return -EBADF;
|
||||
XPD_INFO(xpd, "Span assigned: %d\n", span->spanno);
|
||||
if (xpd->card_present) {
|
||||
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
|
||||
dahdi_alarm_notify(&phonedev->span);
|
||||
}
|
||||
if(!SPAN_REGISTERED(xpd)) {
|
||||
XPD_NOTICE(xpd, "Already unregistered\n");
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return -EIDRM;
|
||||
}
|
||||
update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
|
||||
/* We should now have only a ref from the xbus (from create_xpd()) */
|
||||
if(atomic_read(&PHONEDEV(xpd).open_counter)) {
|
||||
XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish.
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if(xpd->card_present)
|
||||
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
|
||||
atomic_dec(&PHONEDEV(xpd).dahdi_registered);
|
||||
atomic_dec(&num_registered_spans);
|
||||
dahdi_unregister(&PHONEDEV(xpd).span);
|
||||
if(xpd->card_present)
|
||||
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_span_assigned);
|
||||
|
||||
static const struct dahdi_span_ops xpp_span_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1052,6 +966,7 @@ static const struct dahdi_span_ops xpp_span_ops = {
|
||||
.maint = xpp_maint,
|
||||
.echocan_create = xpp_echocan_create,
|
||||
.echocan_name = xpp_echocan_name,
|
||||
.assigned = xpp_span_assigned,
|
||||
};
|
||||
|
||||
static const struct dahdi_span_ops xpp_rbs_span_ops = {
|
||||
@@ -1063,14 +978,54 @@ static const struct dahdi_span_ops xpp_rbs_span_ops = {
|
||||
.maint = xpp_maint,
|
||||
.echocan_create = xpp_echocan_create,
|
||||
.echocan_name = xpp_echocan_name,
|
||||
.assigned = xpp_span_assigned,
|
||||
};
|
||||
|
||||
int dahdi_register_xpd(xpd_t *xpd)
|
||||
void xpd_set_spanname(xpd_t *xpd)
|
||||
{
|
||||
struct dahdi_span *span = &PHONEDEV(xpd).span;
|
||||
|
||||
snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname, xpd->xpdname);
|
||||
/*
|
||||
* The "Xorcom XPD" is a prefix in one of the regexes we
|
||||
* use in our dahdi_genconf to match for PRI cards.
|
||||
* FIXME: After moving completely to sysfs, we can remove
|
||||
* this horseshit.
|
||||
*/
|
||||
snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD [%s].%d: %s",
|
||||
xpd->xbus->label, span->offset + 1, xpd->type_name);
|
||||
}
|
||||
EXPORT_SYMBOL(xpd_set_spanname);
|
||||
|
||||
static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int i;
|
||||
|
||||
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
||||
for (i = 0; i < cn; i++)
|
||||
memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
|
||||
|
||||
span = &PHONEDEV(xpd).span;
|
||||
span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
|
||||
span->channels = cn;
|
||||
span->chans = PHONEDEV(xpd).chans;
|
||||
|
||||
span->flags = DAHDI_FLAG_RBS;
|
||||
span->offset = offset;
|
||||
if (PHONEDEV(xpd).phoneops->card_hooksig)
|
||||
span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
|
||||
else
|
||||
span->ops = &xpp_span_ops;
|
||||
xpd_set_spanname(xpd);
|
||||
list_add_tail(&span->device_node, &xpd->xbus->ddev->spans);
|
||||
}
|
||||
|
||||
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int cn;
|
||||
int i;
|
||||
struct phonedev *phonedev;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
|
||||
@@ -1080,70 +1035,26 @@ int dahdi_register_xpd(xpd_t *xpd)
|
||||
XPD_ERR(xpd, "Not a telephony device\n");
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
phonedev = &PHONEDEV(xpd);
|
||||
|
||||
if (SPAN_REGISTERED(xpd)) {
|
||||
XPD_ERR(xpd, "Already registered\n");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
cn = PHONEDEV(xpd).channels;
|
||||
XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn);
|
||||
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
||||
for(i = 0; i < cn; i++) {
|
||||
memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
|
||||
}
|
||||
|
||||
span = &PHONEDEV(xpd).span;
|
||||
snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname);
|
||||
span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
|
||||
span->channels = cn;
|
||||
span->chans = PHONEDEV(xpd).chans;
|
||||
|
||||
span->flags = DAHDI_FLAG_RBS;
|
||||
if(PHONEDEV(xpd).phoneops->card_hooksig)
|
||||
span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
|
||||
else
|
||||
span->ops = &xpp_span_ops;
|
||||
|
||||
/*
|
||||
* This actually describe the dahdi_spaninfo version 3
|
||||
* A bunch of unrelated data exported via a modified ioctl()
|
||||
* What a bummer...
|
||||
*/
|
||||
span->manufacturer = "Xorcom Inc."; /* OK, that's obvious */
|
||||
/* span->spantype = "...."; set in card_dahdi_preregistration() */
|
||||
/*
|
||||
* Yes, this basically duplicates information available
|
||||
* from the description field. If some more is needed
|
||||
* why not add it there?
|
||||
* OK, let's add to the kernel more useless info.
|
||||
*/
|
||||
snprintf(span->devicetype, sizeof(span->devicetype) - 1,
|
||||
"Astribank: Unit %x Subunit %x: %s",
|
||||
XBUS_UNIT(xpd->xbus_idx), XBUS_SUBUNIT(xpd->xbus_idx),
|
||||
xpd->type_name);
|
||||
/*
|
||||
* location is the only usefull new data item.
|
||||
* For our devices it was available for ages via:
|
||||
* - The legacy "/proc/xpp/XBUS-??/summary" (CONNECTOR=...)
|
||||
* - The same info in "/proc/xpp/xbuses"
|
||||
* - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute
|
||||
* So let's also export it via the newfangled "location" field.
|
||||
*/
|
||||
snprintf(span->location, sizeof(span->location) - 1, "%s", xbus->connector);
|
||||
/*
|
||||
* Who said a span and irq have 1-1 relationship?
|
||||
* Also exporting this low-level detail isn't too wise.
|
||||
* No irq's for you today!
|
||||
*/
|
||||
span->irq = 0;
|
||||
|
||||
snprintf(PHONEDEV(xpd).span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
|
||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
|
||||
XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", PHONEDEV(xpd).span.desc);
|
||||
xpd_init_span(xpd, offset, cn);
|
||||
XPD_DBG(DEVICES, xpd, "Preregister local span %d: %d channels.\n",
|
||||
offset + 1, cn);
|
||||
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 1);
|
||||
if(dahdi_register(&PHONEDEV(xpd).span, prefmaster)) {
|
||||
XPD_ERR(xpd, "Failed to dahdi_register span\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xpd_dahdi_postregister(xpd_t *xpd)
|
||||
{
|
||||
int cn;
|
||||
|
||||
atomic_inc(&num_registered_spans);
|
||||
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
|
||||
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 1);
|
||||
@@ -1163,6 +1074,43 @@ int dahdi_register_xpd(xpd_t *xpd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try our best to make asterisk close all channels related to
|
||||
* this Astribank:
|
||||
* - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
|
||||
* - Notify dahdi afterwards about spans (so it can see all changes at once).
|
||||
* - Also send DAHDI_EVENT_REMOVED on all channels.
|
||||
*/
|
||||
void xpd_dahdi_preunregister(xpd_t *xpd)
|
||||
{
|
||||
if (!xpd || !IS_PHONEDEV(xpd))
|
||||
return;
|
||||
XPD_DBG(DEVICES, xpd, "\n");
|
||||
update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
|
||||
if(xpd->card_present)
|
||||
CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
|
||||
/* Now notify dahdi */
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
int j;
|
||||
|
||||
dahdi_alarm_notify(&PHONEDEV(xpd).span);
|
||||
XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
||||
for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
|
||||
dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void xpd_dahdi_postunregister(xpd_t *xpd)
|
||||
{
|
||||
if (!xpd || !IS_PHONEDEV(xpd))
|
||||
return;
|
||||
atomic_dec(&PHONEDEV(xpd).dahdi_registered);
|
||||
atomic_dec(&num_registered_spans);
|
||||
if(xpd->card_present)
|
||||
CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
|
||||
}
|
||||
|
||||
/*------------------------- Initialization -------------------------*/
|
||||
|
||||
static void do_cleanup(void)
|
||||
@@ -1217,12 +1165,10 @@ static void __exit xpp_dahdi_cleanup(void)
|
||||
|
||||
EXPORT_SYMBOL(debug);
|
||||
EXPORT_SYMBOL(create_xpd);
|
||||
EXPORT_SYMBOL(xpd_post_init);
|
||||
EXPORT_SYMBOL(get_xpd);
|
||||
EXPORT_SYMBOL(put_xpd);
|
||||
EXPORT_SYMBOL(xpd_alloc);
|
||||
EXPORT_SYMBOL(xpd_free);
|
||||
EXPORT_SYMBOL(xbus_request_removal);
|
||||
EXPORT_SYMBOL(update_xpd_status);
|
||||
EXPORT_SYMBOL(oht_pcm);
|
||||
EXPORT_SYMBOL(mark_offhook);
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
#include "xpd.h"
|
||||
#include "xproto.h"
|
||||
|
||||
int dahdi_register_xpd(xpd_t *xpd);
|
||||
int dahdi_unregister_xpd(xpd_t *xpd);
|
||||
void xbus_request_removal(xbus_t *xbus);
|
||||
void xpd_set_spanname(xpd_t *xpd);
|
||||
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
|
||||
int xpd_dahdi_postregister(xpd_t *xpd);
|
||||
void xpd_dahdi_preunregister(xpd_t *xpd);
|
||||
void xpd_dahdi_postunregister(xpd_t *xpd);
|
||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
||||
int unit, int subunit, byte type, byte subtype, int subunits, int subunit_ports, byte port_dir);
|
||||
void xpd_post_init(xpd_t *xpd);
|
||||
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits, size_t privsize, const xproto_table_t *proto_table, int channels);
|
||||
void xpd_free(xpd_t *xpd);
|
||||
void xpd_remove(xpd_t *xpd);
|
||||
@@ -47,6 +48,7 @@ int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg);
|
||||
int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig);
|
||||
int xpp_maint(struct dahdi_span *span, int cmd);
|
||||
int xpp_watchdog(struct dahdi_span *span, int cause);
|
||||
void xpp_span_assigned(struct dahdi_span *span);
|
||||
void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd);
|
||||
int total_registered_spans(void);
|
||||
void oht_pcm(xpd_t *xpd, int pos, bool pass);
|
||||
|
||||
@@ -43,11 +43,10 @@ show_debug() {
|
||||
list=''
|
||||
for n in $dbg_names
|
||||
do
|
||||
if (( val & (1 << j) ))
|
||||
then
|
||||
if [ $(( val & (1 << j) )) -ne 0 ]; then
|
||||
list="$list $n"
|
||||
fi
|
||||
let j++
|
||||
j=$((j+1))
|
||||
done
|
||||
if [ "$list" = "" ]; then
|
||||
list=' NONE'
|
||||
@@ -67,19 +66,19 @@ calc_debug() {
|
||||
for n in $dbg_names
|
||||
do
|
||||
if [ "$wanted" = "$n" ]; then
|
||||
(( val |= (1 << j) ))
|
||||
: $(( val |= (1 << j) ))
|
||||
found=1
|
||||
elif [ "$wanted" = -"$n" ]; then
|
||||
(( val &= ~(1 << j) ))
|
||||
: $(( val &= ~(1 << j) ))
|
||||
found=1
|
||||
elif [ "$wanted" = "ANY" ]; then
|
||||
(( val = ~0 ))
|
||||
: $(( val = ~0 ))
|
||||
found=1
|
||||
elif [ "$wanted" = -"ANY" -o "$wanted" = "NONE" ]; then
|
||||
(( val = 0 ))
|
||||
val=0
|
||||
found=1
|
||||
fi
|
||||
let j++
|
||||
j=$((j+1))
|
||||
done
|
||||
if [ "$found" -eq 0 ]; then
|
||||
echo >&2 "$0: Unknown debug flag '$wanted'"
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/interrupt.h>
|
||||
#endif
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include <linux/poll.h>
|
||||
|
||||
@@ -70,6 +72,12 @@
|
||||
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#ifdef CONFIG_PCI
|
||||
#include <linux/pci-aspm.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
|
||||
#define HAVE_NET_DEVICE_OPS
|
||||
#endif
|
||||
@@ -91,16 +99,33 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
|
||||
# ifdef RHEL_RELEASE_VERSION
|
||||
# if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 6)
|
||||
#define dev_name(dev) ((dev)->bus_id)
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
|
||||
# else
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
do { \
|
||||
kobject_set_name(&(dev)->kobj, format, ## __VA_ARGS__); \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, \
|
||||
kobject_name(&(dev)->kobj)); \
|
||||
} while (0)
|
||||
# endif
|
||||
# else
|
||||
#define dev_name(dev) ((dev)->bus_id)
|
||||
# endif
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
|
||||
# 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
|
||||
@@ -886,6 +911,38 @@ struct dahdi_span_ops {
|
||||
|
||||
/*! Opt: Provide the name of the echo canceller on a channel */
|
||||
const char *(*echocan_name)(const struct dahdi_chan *chan);
|
||||
|
||||
/*! When using "pinned_spans", this function is called back when this
|
||||
* span has been assigned with the system. */
|
||||
void (*assigned)(struct dahdi_span *span);
|
||||
|
||||
/*! Called when the spantype / linemode is changed before the span is
|
||||
* assigned a number. */
|
||||
int (*set_spantype)(struct dahdi_span *span, const char *spantype);
|
||||
};
|
||||
|
||||
/**
|
||||
* dahdi_device - Represents a device that can contain one or more spans.
|
||||
*
|
||||
* @spans: List of child spans.
|
||||
* @manufacturer: Device manufacturer.
|
||||
* @location: The location of this device. This should not change if
|
||||
* the device is replaced (e.g: in the same PCI slot)
|
||||
* @hardware_id: The hardware_id of this device (NULL for devices without
|
||||
* a hardware_id). This should not change if the device is
|
||||
* relocated to a different location (e.g: different PCI slot)
|
||||
* @devicetype: What type of device this is.
|
||||
* @irqmisses: Count of "interrupt misses" for this device.
|
||||
*
|
||||
*/
|
||||
struct dahdi_device {
|
||||
struct list_head spans;
|
||||
const char *manufacturer;
|
||||
const char *location;
|
||||
const char *hardware_id;
|
||||
const char *devicetype;
|
||||
struct device dev;
|
||||
unsigned int irqmisses;
|
||||
};
|
||||
|
||||
struct dahdi_span {
|
||||
@@ -893,14 +950,10 @@ struct dahdi_span {
|
||||
char name[40]; /*!< Span name */
|
||||
char desc[80]; /*!< Span description */
|
||||
const char *spantype; /*!< span type in text form */
|
||||
const char *manufacturer; /*!< span's device manufacturer */
|
||||
char devicetype[80]; /*!< span's device type */
|
||||
char location[40]; /*!< span device's location in system */
|
||||
int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
|
||||
int alarms; /*!< Pending alarms on span */
|
||||
unsigned long flags;
|
||||
u8 cannot_provide_timing:1;
|
||||
int irq; /*!< IRQ for this span's hardware */
|
||||
int lbo; /*!< Span Line-Buildout */
|
||||
int lineconfig; /*!< Span line configuration */
|
||||
int linecompat; /*!< Span line compatibility (0 for
|
||||
@@ -914,7 +967,6 @@ struct dahdi_span {
|
||||
int maintstat; /*!< Maintenance state */
|
||||
int mainttimer; /*!< Maintenance timer */
|
||||
|
||||
int irqmisses; /*!< Interrupt misses */
|
||||
int timingslips; /*!< Clock slips */
|
||||
|
||||
struct dahdi_chan **chans; /*!< Member channel structures */
|
||||
@@ -934,7 +986,11 @@ struct dahdi_span {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_entry;
|
||||
#endif
|
||||
struct list_head node;
|
||||
struct list_head spans_node;
|
||||
|
||||
struct dahdi_device *parent;
|
||||
struct list_head device_node;
|
||||
struct device *span_device;
|
||||
};
|
||||
|
||||
struct dahdi_transcoder_channel {
|
||||
@@ -951,6 +1007,8 @@ struct dahdi_transcoder_channel {
|
||||
u32 srcfmt;
|
||||
};
|
||||
|
||||
int dahdi_is_sync_master(const struct dahdi_span *span);
|
||||
|
||||
static inline int
|
||||
dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) {
|
||||
return test_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags);
|
||||
@@ -1032,6 +1090,7 @@ struct dahdi_dynamic {
|
||||
long rxjif;
|
||||
unsigned short txcnt;
|
||||
unsigned short rxcnt;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan *chans[256];
|
||||
struct dahdi_dynamic_driver *driver;
|
||||
@@ -1039,6 +1098,7 @@ struct dahdi_dynamic {
|
||||
int timing;
|
||||
int master;
|
||||
unsigned char *msgbuf;
|
||||
struct device *dev;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
@@ -1064,6 +1124,9 @@ struct dahdi_dynamic_driver {
|
||||
|
||||
struct list_head list;
|
||||
struct module *owner;
|
||||
|
||||
/*! Numberic id of next device created by this driver. */
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
/*! \brief Receive a dynamic span message */
|
||||
@@ -1102,6 +1165,22 @@ static inline int dahdi_transmit(struct dahdi_span *span)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int dahdi_is_digital_span(const struct dahdi_span *s)
|
||||
{
|
||||
return (s->linecompat > 0);
|
||||
}
|
||||
|
||||
static inline int dahdi_is_t1_span(const struct dahdi_span *s)
|
||||
{
|
||||
return (s->linecompat & (DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
|
||||
DAHDI_CONFIG_B8ZS)) > 0;
|
||||
}
|
||||
|
||||
static inline int dahdi_is_e1_span(const struct dahdi_span *s)
|
||||
{
|
||||
return dahdi_is_digital_span(s) && !dahdi_is_t1_span(s);
|
||||
}
|
||||
|
||||
/*! Abort the buffer currently being receive with event "event" */
|
||||
void dahdi_hdlc_abort(struct dahdi_chan *ss, int event);
|
||||
|
||||
@@ -1116,10 +1195,12 @@ void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes);
|
||||
* and 1 if the currently transmitted message is now done */
|
||||
int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size);
|
||||
|
||||
|
||||
/*! Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if
|
||||
we should have preference in being the master device */
|
||||
int dahdi_register(struct dahdi_span *span, int prefmaster);
|
||||
/*! Register a device. Returns 0 on success, -1 on failure. */
|
||||
struct dahdi_device *dahdi_create_device(void);
|
||||
int dahdi_register_device(struct dahdi_device *ddev, struct device *parent);
|
||||
void dahdi_unregister_device(struct dahdi_device *ddev);
|
||||
void dahdi_free_device(struct dahdi_device *ddev);
|
||||
void dahdi_init_span(struct dahdi_span *span);
|
||||
|
||||
/*! Allocate / free memory for a transcoder */
|
||||
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
|
||||
@@ -1134,9 +1215,6 @@ int dahdi_transcoder_unregister(struct dahdi_transcoder *tc);
|
||||
/*! \brief Alert a transcoder */
|
||||
int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc);
|
||||
|
||||
/*! \brief Unregister a span */
|
||||
int dahdi_unregister(struct dahdi_span *span);
|
||||
|
||||
/*! \brief Gives a name to an LBO */
|
||||
const char *dahdi_lboname(int lbo);
|
||||
|
||||
@@ -1210,8 +1288,13 @@ extern u_char __dahdi_lin2mu[16384];
|
||||
extern u_char __dahdi_lin2a[16384];
|
||||
#endif
|
||||
|
||||
struct dahdi_dynamic_ops {
|
||||
struct module *owner;
|
||||
int (*ioctl)(unsigned int cmd, unsigned long data);
|
||||
};
|
||||
|
||||
/*! \brief Used by dynamic DAHDI -- don't use directly */
|
||||
void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));
|
||||
void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops);
|
||||
|
||||
/*! \brief Used by DAHDI HPEC module -- don't use directly */
|
||||
void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data));
|
||||
@@ -1330,6 +1413,16 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
|
||||
#define fatal_signal_pending(p) \
|
||||
(signal_pending((p)) && sigismember(&(p)->pending.signal, SIGKILL))
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#ifndef PCIE_LINK_STATE_L0S
|
||||
#define PCIE_LINK_STATE_L0S 1
|
||||
#define PCIE_LINK_STATE_L1 2
|
||||
#define PCIE_LINK_STATE_CLKPM 4
|
||||
#endif
|
||||
#define pci_disable_link_state dahdi_pci_disable_link_state
|
||||
void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
|
||||
#ifndef __packed
|
||||
@@ -1357,59 +1450,15 @@ static inline int strcasecmp(const char *s1, const char *s2)
|
||||
return c1 - c2;
|
||||
}
|
||||
#endif /* clamp_val */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
static inline void list_replace(struct list_head *old, struct list_head *new)
|
||||
{
|
||||
new->next = old->next;
|
||||
new->next->prev = new;
|
||||
new->prev = old->prev;
|
||||
new->prev->next = new;
|
||||
}
|
||||
|
||||
#ifndef WARN_ON_ONCE
|
||||
#define WARN_ON_ONCE(__condition) do { \
|
||||
static int __once = 1; \
|
||||
if (unlikely(__condition)) { \
|
||||
if (__once) { \
|
||||
__once = 0; \
|
||||
WARN_ON(0); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
|
||||
#define kzalloc(a, b) kcalloc(1, a, b)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
|
||||
#define synchronize_rcu() synchronize_kernel()
|
||||
#define kasprintf dahdi_kasprintf
|
||||
char *dahdi_kasprintf(gfp_t gfp, const char *fmt, ...);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
|
||||
#if !defined(HAVE_WAIT_FOR_COMPLETION_TIMEOUT)
|
||||
static inline unsigned long
|
||||
wait_for_completion_interruptible_timeout(struct completion *x,
|
||||
unsigned long timeout)
|
||||
{
|
||||
/* There is a race condition here. If x->done is reset to 0
|
||||
* before the call to wait_for_completion after this thread wakes.
|
||||
*/
|
||||
timeout = wait_event_interruptible_timeout(x->wait, x->done, timeout);
|
||||
if (timeout)
|
||||
wait_for_completion(x);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
#endif
|
||||
typedef u32 __bitwise pm_message_t;
|
||||
#endif /* 2.6.11 */
|
||||
#endif /* 2.6.12 */
|
||||
#endif /* 2.6.14 */
|
||||
#endif /* 2.6.18 */
|
||||
#endif /* 2.6.22 */
|
||||
#endif /* 2.6.25 */
|
||||
#endif /* 2.6.26 */
|
||||
#endif /* 2.6.31 */
|
||||
|
||||
#ifndef CONFIG_TRACING
|
||||
#define trace_printk printk
|
||||
#endif
|
||||
|
||||
#ifndef DEFINE_SPINLOCK
|
||||
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
|
||||
#endif
|
||||
@@ -1475,6 +1524,26 @@ struct mutex {
|
||||
#define chan_err(chan, fmt, ...) chan_printk(ERR, "", chan, fmt, \
|
||||
## __VA_ARGS__)
|
||||
|
||||
#ifndef pr_err
|
||||
#define pr_err(fmt, ...) \
|
||||
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef pr_warning
|
||||
#define pr_warning(fmt, ...) \
|
||||
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef pr_warn
|
||||
#define pr_warn pr_warning
|
||||
#endif
|
||||
#ifndef pr_notice
|
||||
#define pr_notice(fmt, ...) \
|
||||
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef pr_info
|
||||
#define pr_info(fmt, ...) \
|
||||
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* The dbg_* ones use a magical variable 'debug' and the user should be
|
||||
* aware of that.
|
||||
*/
|
||||
@@ -1486,6 +1555,7 @@ struct mutex {
|
||||
* be of the form DAHDI_DBG_*
|
||||
*/
|
||||
#define DAHDI_DBG_GENERAL BIT(0)
|
||||
#define DAHDI_DBG_ASSIGN BIT(1)
|
||||
#define DAHDI_DBG_DEVICES BIT(7) /* instantiation/destruction etc. */
|
||||
#define dahdi_dbg(bits, fmt, ...) \
|
||||
((void)((debug & (DAHDI_DBG_ ## bits)) && DAHDI_PRINTK(DEBUG, \
|
||||
@@ -1498,6 +1568,10 @@ struct mutex {
|
||||
((void)((debug & (DAHDI_DBG_ ## bits)) && \
|
||||
chan_printk(DEBUG, "-" #bits, chan, \
|
||||
"%s: " fmt, __func__, ## __VA_ARGS__)))
|
||||
#define dahdi_dev_dbg(bits, dev, fmt, ...) \
|
||||
((void)((debug & (DAHDI_DBG_ ## bits)) && \
|
||||
dev_printk(KERN_DEBUG, dev, \
|
||||
"DBG-%s(%s): " fmt, #bits, __func__, ## __VA_ARGS__)))
|
||||
#endif /* DAHDI_PRINK_MACROS_USE_debug */
|
||||
|
||||
#endif /* _DAHDI_KERNEL_H */
|
||||
|
||||
Reference in New Issue
Block a user