Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a58eef031 | ||
|
|
07a8698f77 | ||
|
|
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 |
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
|
||||
@@ -538,6 +539,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.
|
||||
@@ -557,6 +559,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.
|
||||
@@ -644,6 +721,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
|
||||
@@ -721,7 +895,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
|
||||
|
||||
@@ -6,6 +6,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH) += dahdi_dynamic_eth.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF) += dahdi_dynamic_ethmf.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o
|
||||
|
||||
ifdef CONFIG_PCI
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
|
||||
@@ -20,6 +21,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o
|
||||
endif
|
||||
|
||||
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -49,6 +49,311 @@ 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)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
|
||||
#define dev_name(dev) ((dev)->bus_id)
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
|
||||
#endif
|
||||
|
||||
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 +383,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 +401,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 +492,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 +759,60 @@ 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;
|
||||
|
||||
dev->parent = parent;
|
||||
dev->bus = &dahdi_device_bus;
|
||||
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 +820,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 +872,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 */
|
||||
|
||||
@@ -400,6 +400,7 @@ static void dahdi_dynamic_release(struct kref *kref)
|
||||
for (x = 0; x < d->span.channels; x++)
|
||||
kfree(d->chans[x]);
|
||||
|
||||
dahdi_free_device(d->ddev);
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
@@ -469,7 +470,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dahdi_unregister(&d->span);
|
||||
dahdi_unregister_device(d->ddev);
|
||||
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
@@ -578,8 +579,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);
|
||||
@@ -657,8 +658,9 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -769,7 +771,7 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
|
||||
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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -123,6 +128,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
|
||||
@@ -156,6 +172,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:
|
||||
@@ -184,6 +211,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);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#ifndef _GPAKCUST_H /* prevent multiple inclusion */
|
||||
#define _GPAKCUST_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2205,7 +2205,7 @@ static const char *b4xxp_echocan_name(const struct dahdi_chan *chan)
|
||||
{
|
||||
struct b4xxp_span *bspan = container_of(chan->span, struct b4xxp_span,
|
||||
span);
|
||||
if (bspan->parent->card_type == B410P)
|
||||
if (vpmsupport && (B410P == bspan->parent->card_type))
|
||||
return "LASVEGAS2";
|
||||
return NULL;
|
||||
}
|
||||
@@ -2475,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;
|
||||
@@ -2494,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 */
|
||||
@@ -2930,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2973,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);
|
||||
@@ -2997,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:
|
||||
@@ -3011,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);
|
||||
@@ -3033,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
|
||||
endif
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
|
||||
@@ -25,3 +25,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,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
|
||||
tOCT6100_CHANNEL_OPEN *ChannelOpen;
|
||||
UINT32 ulResult;
|
||||
unsigned int sout_stream, rout_stream;
|
||||
struct vpm450m *vpm450m;
|
||||
int x,y,law;
|
||||
|
||||
@@ -467,15 +468,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 +515,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 +527,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 & 0x07])
|
||||
law = cOCT6100_PCM_A_LAW;
|
||||
else
|
||||
law = cOCT6100_PCM_U_LAW;
|
||||
@@ -529,11 +541,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 +557,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)
|
||||
|
||||
|
||||
@@ -73,20 +73,6 @@
|
||||
dev_info(&(wc)->pdev->dev, _fmt, ## _args); \
|
||||
} \
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
|
||||
/* also added in RHEL kernels with the OpenInfiniband backport: */
|
||||
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 9) || !defined(DEFINE_SPINLOCK)
|
||||
@@ -488,6 +474,7 @@ wctc4xxp_skb_to_cmd(struct wcdte *wc, const struct sk_buff *skb)
|
||||
return cmd;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
|
||||
static void
|
||||
wctc4xxp_net_set_multi(struct net_device *netdev)
|
||||
{
|
||||
@@ -495,6 +482,15 @@ wctc4xxp_net_set_multi(struct net_device *netdev)
|
||||
DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n",
|
||||
__func__, netdev->promiscuity);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
wctc4xxp_set_rx_mode(struct net_device *netdev)
|
||||
{
|
||||
struct wcdte *wc = wcdte_from_netdev(netdev);
|
||||
DTE_DEBUG(DTE_DEBUG_GENERAL, "%s promiscuity:%d\n",
|
||||
__func__, netdev->promiscuity);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
wctc4xxp_net_up(struct net_device *netdev)
|
||||
@@ -658,7 +654,11 @@ wctc4xxp_net_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
|
||||
|
||||
#ifdef HAVE_NET_DEVICE_OPS
|
||||
static const struct net_device_ops wctc4xxp_netdev_ops = {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
|
||||
.ndo_set_multicast_list = &wctc4xxp_net_set_multi,
|
||||
#else
|
||||
.ndo_set_rx_mode = &wctc4xxp_set_rx_mode,
|
||||
#endif
|
||||
.ndo_open = &wctc4xxp_net_up,
|
||||
.ndo_stop = &wctc4xxp_net_down,
|
||||
.ndo_start_xmit = &wctc4xxp_net_hard_start_xmit,
|
||||
@@ -2158,12 +2158,13 @@ wctc4xxp_write(struct file *file, const char __user *frame,
|
||||
}
|
||||
|
||||
if (DAHDI_FORMAT_G723_1 == dtc->srcfmt) {
|
||||
if ((G723_5K_BYTES != count) && (G723_6K_BYTES != count)) {
|
||||
if ((G723_5K_BYTES != count) && (G723_6K_BYTES != count) &&
|
||||
(G723_SID_BYTES != count)) {
|
||||
DTE_DEBUG(DTE_DEBUG_GENERAL,
|
||||
"Trying to transcode packet into G723 format " \
|
||||
"that is %Zu bytes instead of the expected " \
|
||||
"%d/%d bytes.\n", count, G723_5K_BYTES,
|
||||
G723_6K_BYTES);
|
||||
"%d/%d/%d bytes.\n", count, G723_5K_BYTES,
|
||||
G723_6K_BYTES, G723_SID_BYTES);
|
||||
return -EINVAL;
|
||||
}
|
||||
cpvt->timestamp += G723_SAMPLES;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -55,13 +55,18 @@
|
||||
#error VOICEBUS_SFRAME_SIZE != SFRAME_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#endif
|
||||
|
||||
static int debug;
|
||||
static int j1mode = 0;
|
||||
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', or 't1' */
|
||||
static int latency = VOICEBUS_DEFAULT_LATENCY;
|
||||
static unsigned int max_latency = VOICEBUS_DEFAULT_MAXLATENCY;
|
||||
static int vpmsupport = 1;
|
||||
@@ -750,7 +755,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 +776,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 +820,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 */
|
||||
|
||||
@@ -1004,12 +1021,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,14 +1035,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);
|
||||
if (wc->vpmadt032) {
|
||||
wc->ddev->devicetype = kasprintf(GFP_KERNEL,
|
||||
"%s (VPMADT032)", wc->variety);
|
||||
} else if (wc->vpmoct) {
|
||||
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)
|
||||
@@ -1046,7 +1077,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;
|
||||
@@ -1086,7 +1117,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;
|
||||
@@ -1101,7 +1132,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;
|
||||
|
||||
@@ -1154,7 +1185,7 @@ static inline void t1_check_sigbits(struct t1 *wc)
|
||||
|
||||
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
|
||||
return;
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (dahdi_is_e1_span(&wc->span)) {
|
||||
for (i = 0; i < 15; i++) {
|
||||
a = t1_getreg(wc, 0x71 + i);
|
||||
if (a > -1) {
|
||||
@@ -1249,7 +1280,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");
|
||||
@@ -1321,7 +1352,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:
|
||||
@@ -1570,6 +1601,7 @@ static int vpm_start_load(struct t1 *wc)
|
||||
work->wc = wc;
|
||||
|
||||
queue_work(wc->wq, &work->work);
|
||||
wc->not_ready++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1616,12 +1648,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;
|
||||
@@ -1660,6 +1703,8 @@ static void check_and_load_vpm(struct t1 *wc)
|
||||
|
||||
vpmoct_init(vpmoct, t1_vpm_load_complete);
|
||||
}
|
||||
|
||||
set_span_devicetype(wc);
|
||||
}
|
||||
#else
|
||||
static inline void check_and_load_vpm(const struct t1 *wc)
|
||||
@@ -1674,7 +1719,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 */
|
||||
@@ -1757,54 +1802,46 @@ 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) {
|
||||
if (type == E1) {
|
||||
wc->span.channels = 31;
|
||||
wc->span.spantype = "E1";
|
||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 |
|
||||
@@ -1817,24 +1854,89 @@ static int t1_software_init(struct t1 *wc)
|
||||
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||
}
|
||||
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",
|
||||
(dahdi_is_e1_span(&wc->span) ? "E1" : "T1"));
|
||||
|
||||
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 E1 to T1 line mode.\n");
|
||||
res = t1_software_init(wc, T1);
|
||||
} else if (!strcasecmp(linemode, "e1")) {
|
||||
dev_info(&wc->vb.pdev->dev,
|
||||
"Changing from T1 to E1 line mode.\n");
|
||||
res = t1_software_init(wc, E1);
|
||||
} 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
|
||||
@@ -1853,39 +1955,53 @@ 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) {
|
||||
pr_info("t1e1override is deprecated. Please use 'default_linemode'.\n");
|
||||
*type = (t1e1override) ? E1 : 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 {
|
||||
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" : "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);
|
||||
@@ -1913,7 +2029,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
|
||||
@@ -2239,7 +2355,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 "
|
||||
@@ -2522,14 +2638,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]) {
|
||||
@@ -2548,18 +2681,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;
|
||||
@@ -2580,6 +2717,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
|
||||
@@ -2611,6 +2764,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;
|
||||
}
|
||||
|
||||
@@ -2624,36 +2778,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;
|
||||
}
|
||||
|
||||
@@ -2663,10 +2814,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;
|
||||
}
|
||||
|
||||
@@ -2681,7 +2829,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);
|
||||
|
||||
@@ -2772,6 +2920,16 @@ static int __init te12xp_init(void)
|
||||
if (!cmd_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
if (-1 != t1e1override) {
|
||||
pr_info("'t1e1override' is deprecated. "
|
||||
"Please use 'default_linemode' instead\n");
|
||||
} else if (strcasecmp(default_linemode, "auto") &&
|
||||
strcasecmp(default_linemode, "t1") &&
|
||||
strcasecmp(default_linemode, "e1")) {
|
||||
pr_err("'%s' is an unknown span type.", default_linemode);
|
||||
default_linemode = "auto";
|
||||
return -EINVAL;
|
||||
}
|
||||
res = dahdi_pci_module(&te12xp_driver);
|
||||
if (res) {
|
||||
kmem_cache_destroy(cmd_cache);
|
||||
@@ -2790,6 +2948,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,10 @@
|
||||
#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,
|
||||
};
|
||||
|
||||
struct command {
|
||||
struct list_head node;
|
||||
@@ -94,7 +96,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 +117,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 */
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
static const char rcsid[] = "$Id$";
|
||||
|
||||
#ifndef DAHDI_SIG_HARDHDLC
|
||||
#error Cannot build BRI without HARDHDLC supprt
|
||||
#endif
|
||||
|
||||
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
||||
static DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)");
|
||||
static DEF_PARM_BOOL(nt_keepalive, 1, 0644, "Force BRI_NT to keep trying connection");
|
||||
@@ -129,22 +133,7 @@ typedef union {
|
||||
#define REG30_LOST 3 /* in polls */
|
||||
#define DCHAN_LOST 15000 /* in ticks */
|
||||
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
#define BRI_DCHAN_SIGCAP ( \
|
||||
DAHDI_SIG_EM | \
|
||||
DAHDI_SIG_CLEAR | \
|
||||
DAHDI_SIG_FXSLS | \
|
||||
DAHDI_SIG_FXSGS | \
|
||||
DAHDI_SIG_FXSKS | \
|
||||
DAHDI_SIG_FXOLS | \
|
||||
DAHDI_SIG_FXOGS | \
|
||||
DAHDI_SIG_FXOKS | \
|
||||
DAHDI_SIG_CAS | \
|
||||
DAHDI_SIG_SF \
|
||||
)
|
||||
#else
|
||||
#define BRI_DCHAN_SIGCAP DAHDI_SIG_HARDHDLC
|
||||
#endif
|
||||
#define BRI_BCHAN_SIGCAP (DAHDI_SIG_CLEAR | DAHDI_SIG_DACS)
|
||||
|
||||
#define IS_NT(xpd) (PHONEDEV(xpd).direction == TO_PHONE)
|
||||
@@ -218,13 +207,7 @@ struct BRI_priv_data {
|
||||
/*
|
||||
* D-Chan: buffers + extra state info.
|
||||
*/
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
int dchan_r_idx;
|
||||
byte dchan_rbuf[DCHAN_BUFSIZE];
|
||||
#else
|
||||
atomic_t hdlc_pending;
|
||||
#endif
|
||||
byte dchan_tbuf[DCHAN_BUFSIZE];
|
||||
bool txframe_begin;
|
||||
|
||||
uint tick_counter;
|
||||
@@ -438,22 +421,6 @@ static void nt_activation(xpd_t *xpd, bool on)
|
||||
/*
|
||||
* D-Chan receive
|
||||
*/
|
||||
static void bri_hdlc_abort(xpd_t *xpd, struct dahdi_chan *dchan, int event)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
if(debug & DBG_COMMANDS)
|
||||
dump_hex_buf(xpd, "D-Chan(abort) RX: dchan_rbuf",
|
||||
priv->dchan_rbuf, priv->dchan_r_idx);
|
||||
priv->dchan_r_idx = 0;
|
||||
#else
|
||||
dahdi_hdlc_abort(dchan, event);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, byte *buf, int len)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
@@ -461,21 +428,11 @@ static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, byte *buf, int l
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
if(priv->dchan_r_idx < 4) {
|
||||
XPD_NOTICE(xpd, "D-Chan RX short frame (dchan_r_idx=%d)\n",
|
||||
priv->dchan_r_idx);
|
||||
dump_hex_buf(xpd, "D-Chan RX: current packet", buf, len);
|
||||
bri_hdlc_abort(xpd, dchan, DAHDI_EVENT_ABORT);
|
||||
return -EPROTO;
|
||||
}
|
||||
#else
|
||||
if(len <= 0) {
|
||||
XPD_NOTICE(xpd, "D-Chan RX DROP: short frame (len=%d)\n", len);
|
||||
bri_hdlc_abort(xpd, dchan, DAHDI_EVENT_ABORT);
|
||||
dahdi_hdlc_abort(dchan, DAHDI_EVENT_ABORT);
|
||||
return -EPROTO;
|
||||
}
|
||||
#endif
|
||||
status = buf[len-1];
|
||||
if(status) {
|
||||
int event = DAHDI_EVENT_ABORT;
|
||||
@@ -487,132 +444,12 @@ static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, byte *buf, int l
|
||||
event = DAHDI_EVENT_BADFCS;
|
||||
}
|
||||
dump_hex_buf(xpd, "D-Chan RX: current packet", buf, len);
|
||||
bri_hdlc_abort(xpd, dchan, event);
|
||||
dahdi_hdlc_abort(dchan, event);
|
||||
return -EPROTO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bri_hdlc_putbuf(xpd_t *xpd, struct dahdi_chan *dchan,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
struct BRI_priv_data *priv;
|
||||
byte *dchan_buf;
|
||||
byte *dst;
|
||||
int idx;
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
dchan_buf = dchan->readchunk;
|
||||
idx = priv->dchan_r_idx;
|
||||
if(idx + len >= DCHAN_BUFSIZE) {
|
||||
XPD_ERR(xpd, "D-Chan RX overflow: %d\n", idx);
|
||||
dump_hex_buf(xpd, " current packet", buf, len);
|
||||
dump_hex_buf(xpd, " dchan_buf", dchan_buf, idx);
|
||||
return -ENOSPC;
|
||||
}
|
||||
dst = dchan_buf + idx;
|
||||
idx += len;
|
||||
priv->dchan_r_idx = idx;
|
||||
memcpy(dst, buf, len);
|
||||
#else
|
||||
dahdi_hdlc_putbuf(dchan, buf, len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bri_hdlc_finish(xpd_t *xpd, struct dahdi_chan *dchan)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
dchan->bytes2receive = priv->dchan_r_idx - 1;
|
||||
dchan->eofrx = 1;
|
||||
#else
|
||||
dahdi_hdlc_finish(dchan);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
byte *src;
|
||||
byte *dst;
|
||||
byte *dchan_buf;
|
||||
struct dahdi_chan *dchan;
|
||||
uint len;
|
||||
bool eoframe;
|
||||
int idx;
|
||||
int ret = 0;
|
||||
|
||||
src = REG_XDATA(regcmd);
|
||||
len = regcmd->bytes;
|
||||
eoframe = regcmd->eoframe;
|
||||
if(len <= 0)
|
||||
return 0;
|
||||
if(!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */
|
||||
return 0;
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
xbus = xpd->xbus;
|
||||
dchan = XPD_CHAN(xpd, 2);
|
||||
if(!IS_OFFHOOK(xpd, 2)) { /* D-chan is used? */
|
||||
static int rate_limit;
|
||||
|
||||
if((rate_limit++ % 1000) == 0)
|
||||
XPD_DBG(SIGNAL, xpd, "D-Chan unused\n");
|
||||
dchan->bytes2receive = 0;
|
||||
dchan->bytes2transmit = 0;
|
||||
goto out;
|
||||
}
|
||||
dchan_buf = dchan->readchunk;
|
||||
idx = priv->dchan_r_idx;
|
||||
if(idx + len >= DCHAN_BUFSIZE) {
|
||||
XPD_ERR(xpd, "D-Chan RX overflow: %d\n", idx);
|
||||
dump_hex_buf(xpd, " current packet", src, len);
|
||||
dump_hex_buf(xpd, " dchan_buf", dchan_buf, idx);
|
||||
ret = -ENOSPC;
|
||||
if(eoframe)
|
||||
goto drop;
|
||||
goto out;
|
||||
}
|
||||
dst = dchan_buf + idx;
|
||||
idx += len;
|
||||
priv->dchan_r_idx = idx;
|
||||
memcpy(dst, src, len);
|
||||
if(!eoframe)
|
||||
goto out;
|
||||
if(idx < 4) {
|
||||
XPD_NOTICE(xpd, "D-Chan RX short frame (idx=%d)\n", idx);
|
||||
dump_hex_buf(xpd, "D-Chan RX: current packet", src, len);
|
||||
dump_hex_buf(xpd, "D-Chan RX: chan_buf", dchan_buf, idx);
|
||||
ret = -EPROTO;
|
||||
goto drop;
|
||||
}
|
||||
if((ret = bri_check_stat(xpd, dchan, dchan_buf, idx)) < 0)
|
||||
goto drop;
|
||||
if(debug)
|
||||
dump_dchan_packet(xpd, 0, dchan_buf, idx /* - 3 */); /* Print checksum? */
|
||||
/*
|
||||
* Tell Dahdi that we received idx-1 bytes. They include the data and a 2-byte checksum.
|
||||
* The last byte (that we don't pass on) is 0 if the checksum is correct. If it were wrong,
|
||||
* we would drop the packet in the "if(dchan_buf[idx-1])" above.
|
||||
*/
|
||||
dchan->bytes2receive = idx - 1;
|
||||
dchan->eofrx = 1;
|
||||
priv->dchan_rx_counter++;
|
||||
priv->dchan_norx_ticks = 0;
|
||||
drop:
|
||||
priv->dchan_r_idx = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
@@ -638,16 +475,10 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
|
||||
if((rate_limit++ % 1000) == 0)
|
||||
XPD_DBG(SIGNAL, xpd, "D-Chan unused\n");
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
dchan->bytes2receive = 0;
|
||||
dchan->bytes2transmit = 0;
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "D-Chan RX: eoframe=%d len=%d\n", eoframe, len);
|
||||
ret = bri_hdlc_putbuf(xpd, dchan, src, (eoframe) ? len - 1 : len);
|
||||
if(ret < 0)
|
||||
goto out;
|
||||
dahdi_hdlc_putbuf(dchan, src, (eoframe) ? len - 1 : len);
|
||||
if(!eoframe)
|
||||
goto out;
|
||||
if((ret = bri_check_stat(xpd, dchan, src, len)) < 0)
|
||||
@@ -657,18 +488,16 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
|
||||
* The last byte (that we don't pass on) is 0 if the checksum is correct. If it were wrong,
|
||||
* we would drop the packet in the "if(src[len-1])" above.
|
||||
*/
|
||||
bri_hdlc_finish(xpd, dchan);
|
||||
dahdi_hdlc_finish(dchan);
|
||||
priv->dchan_rx_counter++;
|
||||
priv->dchan_norx_ticks = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* D-Chan transmit
|
||||
*/
|
||||
#ifndef CONFIG_DAHDI_BRI_DCHANS
|
||||
/* DAHDI calls this when it has data it wants to send to the HDLC controller */
|
||||
static void bri_hdlc_hard_xmit(struct dahdi_chan *chan)
|
||||
{
|
||||
@@ -683,86 +512,129 @@ static void bri_hdlc_hard_xmit(struct dahdi_chan *chan)
|
||||
atomic_inc(&priv->hdlc_pending);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int bri_hdlc_getbuf(struct dahdi_chan *dchan, unsigned char *buf,
|
||||
unsigned int *size)
|
||||
static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof)
|
||||
{
|
||||
int len = *size;
|
||||
int eoframe;
|
||||
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
len = dchan->bytes2transmit; /* dchan's hdlc package len */
|
||||
if(len > *size)
|
||||
len = *size; /* Silent truncation */
|
||||
eoframe = dchan->eoftx; /* dchan's end of frame */
|
||||
dchan->bytes2transmit = 0;
|
||||
dchan->eoftx = 0;
|
||||
dchan->bytes2receive = 0;
|
||||
dchan->eofrx = 0;
|
||||
#else
|
||||
eoframe = dahdi_hdlc_getbuf(dchan, buf, &len);
|
||||
#endif
|
||||
*size = len;
|
||||
return eoframe;
|
||||
}
|
||||
|
||||
static int tx_dchan(xpd_t *xpd)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
struct dahdi_chan *dchan;
|
||||
int len;
|
||||
int eoframe;
|
||||
int ret;
|
||||
struct BRI_priv_data *priv;
|
||||
int ret;
|
||||
|
||||
XPD_DBG(COMMANDS, xpd, "eoframe=%d\n", is_eof);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
#ifndef CONFIG_DAHDI_BRI_DCHANS
|
||||
if(atomic_read(&priv->hdlc_pending) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
if(!SPAN_REGISTERED(xpd) || !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
|
||||
return 0;
|
||||
dchan = XPD_CHAN(xpd, 2);
|
||||
len = ARRAY_SIZE(priv->dchan_tbuf);
|
||||
if(len > MULTIBYTE_MAX_LEN)
|
||||
len = MULTIBYTE_MAX_LEN;
|
||||
eoframe = bri_hdlc_getbuf(dchan, priv->dchan_tbuf, &len);
|
||||
if(len <= 0)
|
||||
return 0; /* Nothing to transmit on D channel */
|
||||
if(len > MULTIBYTE_MAX_LEN) {
|
||||
XPD_ERR(xpd, "%s: len=%d. need to split. Unimplemented.\n", __FUNCTION__, len);
|
||||
dump_hex_buf(xpd, "D-Chan TX:", priv->dchan_tbuf, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
||||
if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
|
||||
&& !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
||||
XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n");
|
||||
if(! IS_NT(xpd))
|
||||
if (!IS_NT(xpd))
|
||||
te_activation(xpd, 1);
|
||||
else
|
||||
nt_activation(xpd, 1);
|
||||
}
|
||||
if(debug)
|
||||
dump_dchan_packet(xpd, 1, priv->dchan_tbuf, len);
|
||||
if(eoframe)
|
||||
priv->txframe_begin = 1;
|
||||
else
|
||||
priv->txframe_begin = 0;
|
||||
XPD_DBG(COMMANDS, xpd, "eoframe=%d len=%d\n", eoframe, len);
|
||||
ret = send_multibyte_request(xpd->xbus, xpd->addr.unit, xpd->addr.subunit,
|
||||
eoframe, priv->dchan_tbuf, len);
|
||||
if(ret < 0)
|
||||
XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__);
|
||||
if(eoframe) {
|
||||
#ifndef CONFIG_DAHDI_BRI_DCHANS
|
||||
dump_xframe("send_dchan_frame", xpd->xbus, xframe, debug);
|
||||
ret = send_cmd_frame(xpd->xbus, xframe);
|
||||
if (ret < 0)
|
||||
XPD_ERR(xpd, "%s: failed sending xframe\n", __func__);
|
||||
if (is_eof) {
|
||||
atomic_dec(&priv->hdlc_pending);
|
||||
#endif
|
||||
priv->dchan_tx_counter++;
|
||||
}
|
||||
priv->txframe_begin = 1;
|
||||
} else
|
||||
priv->txframe_begin = 0;
|
||||
priv->dchan_notx_ticks = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill a single multibyte REGISTER_REQUEST
|
||||
*/
|
||||
static void fill_multibyte(xpd_t *xpd, xpacket_t *pack, bool eoframe,
|
||||
char *buf, int len)
|
||||
{
|
||||
reg_cmd_t *reg_cmd;
|
||||
char *p;
|
||||
|
||||
XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
|
||||
XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = len;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = xpd->addr.subunit;
|
||||
reg_cmd->eoframe = eoframe;
|
||||
p = REG_XDATA(reg_cmd);
|
||||
memcpy(p, buf, len);
|
||||
if (debug)
|
||||
dump_dchan_packet(xpd, 1, p, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit available D-Channel frames
|
||||
*
|
||||
* - FPGA firmware expect to get this as a sequence of REGISTER_REQUEST
|
||||
* multibyte commands.
|
||||
* - The payload of each command is limited to MULTIBYTE_MAX_LEN bytes.
|
||||
* - We batch several REGISTER_REQUEST packets into a single xframe.
|
||||
* - The xframe is terminated when we get a bri "end of frame"
|
||||
* or when the xframe is full (should not happen).
|
||||
*/
|
||||
static int tx_dchan(xpd_t *xpd)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
int packet_count;
|
||||
int eoframe;
|
||||
int ret;
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if (atomic_read(&priv->hdlc_pending) == 0)
|
||||
return 0;
|
||||
if (!SPAN_REGISTERED(xpd) ||
|
||||
!(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
|
||||
return 0;
|
||||
/* Allocate frame */
|
||||
xframe = ALLOC_SEND_XFRAME(xpd->xbus);
|
||||
if (!xframe) {
|
||||
XPD_NOTICE(xpd, "%s: failed to allocate new xframe\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
|
||||
int packet_len = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
|
||||
char buf[MULTIBYTE_MAX_LEN];
|
||||
int len = MULTIBYTE_MAX_LEN;
|
||||
|
||||
/* Reserve packet */
|
||||
pack = xframe_next_packet(xframe, packet_len);
|
||||
if (!pack) {
|
||||
BUG_ON(!packet_count);
|
||||
/*
|
||||
* A split. Send what we currently have.
|
||||
*/
|
||||
XPD_NOTICE(xpd,
|
||||
"%s: xframe is full (%d packets)\n",
|
||||
__func__, packet_count);
|
||||
break;
|
||||
}
|
||||
/* Get data from DAHDI */
|
||||
eoframe = dahdi_hdlc_getbuf(XPD_CHAN(xpd, 2), buf, &len);
|
||||
if (len <= 0) {
|
||||
/*
|
||||
* Already checked priv->hdlc_pending,
|
||||
* should never get here.
|
||||
*/
|
||||
if (printk_ratelimit())
|
||||
XPD_ERR(xpd,
|
||||
"%s: hdlc_pending, but nothing to transmit?\n",
|
||||
__func__);
|
||||
FREE_SEND_XFRAME(xpd->xbus, xframe);
|
||||
return -EINVAL;
|
||||
}
|
||||
BUG_ON(len > MULTIBYTE_MAX_LEN);
|
||||
fill_multibyte(xpd, pack, eoframe != 0, buf, len);
|
||||
}
|
||||
return send_dchan_frame(xpd, xframe, eoframe != 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*---------------- BRI: Methods -------------------------------------------*/
|
||||
|
||||
static void bri_proc_remove(xbus_t *xbus, xpd_t *xpd)
|
||||
@@ -853,9 +725,7 @@ static const struct dahdi_span_ops BRI_span_ops = {
|
||||
.chanconfig = bri_chanconfig,
|
||||
.startup = bri_startup,
|
||||
.shutdown = bri_shutdown,
|
||||
#ifndef CONFIG_DAHDI_BRI_DCHANS
|
||||
.hdlc_hard_xmit = bri_hdlc_hard_xmit,
|
||||
#endif
|
||||
.open = xpp_open,
|
||||
.close = xpp_close,
|
||||
.hooksig = xpp_hooksig, /* Only with RBS bits */
|
||||
@@ -863,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
|
||||
@@ -903,19 +774,7 @@ static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
cur_chan->sigcap = BRI_DCHAN_SIGCAP;
|
||||
clear_bit(DAHDI_FLAGBIT_HDLC, &cur_chan->flags);
|
||||
priv->txframe_begin = 1;
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
priv->dchan_r_idx = 0;
|
||||
set_bit(DAHDI_FLAGBIT_BRIDCHAN, &cur_chan->flags);
|
||||
/* Setup big buffers for D-Channel rx/tx */
|
||||
cur_chan->readchunk = priv->dchan_rbuf;
|
||||
cur_chan->writechunk = priv->dchan_tbuf;
|
||||
|
||||
cur_chan->maxbytes2transmit = MULTIBYTE_MAX_LEN;
|
||||
cur_chan->bytes2transmit = 0;
|
||||
cur_chan->bytes2receive = 0;
|
||||
#else
|
||||
atomic_set(&priv->hdlc_pending, 0);
|
||||
#endif
|
||||
} else {
|
||||
cur_chan->sigcap = BRI_BCHAN_SIGCAP;
|
||||
}
|
||||
@@ -1145,15 +1004,6 @@ static int BRI_card_open(xpd_t *xpd, lineno_t pos)
|
||||
static int BRI_card_close(xpd_t *xpd, lineno_t pos)
|
||||
{
|
||||
/* Clear D-Channel pending data */
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, pos);
|
||||
|
||||
/* Clear D-Channel pending data */
|
||||
chan->bytes2receive = 0;
|
||||
chan->eofrx = 0;
|
||||
chan->bytes2transmit = 0;
|
||||
chan->eoftx = 0;
|
||||
#endif
|
||||
if(pos == 2) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "ONHOOK the whole span\n");
|
||||
BIT_CLR(PHONEDEV(xpd).offhook_state, 0);
|
||||
@@ -1201,6 +1051,8 @@ static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
framingstr, codingstr, crcstr,
|
||||
lc->lineconfig,
|
||||
lc->sync);
|
||||
PHONEDEV(xpd).timing_priority = lc->sync;
|
||||
elect_syncer("BRI-spanconfig");
|
||||
/*
|
||||
* FIXME: validate
|
||||
*/
|
||||
@@ -1252,9 +1104,6 @@ static int bri_startup(struct file *file, struct dahdi_span *span)
|
||||
*
|
||||
* Don't Get Mad, Get Even: Now we override dahdi :-)
|
||||
*/
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
set_bit(DAHDI_FLAGBIT_BRIDCHAN, &dchan->flags);
|
||||
#endif
|
||||
clear_bit(DAHDI_FLAGBIT_HDLC, &dchan->flags);
|
||||
}
|
||||
return 0;
|
||||
@@ -1428,6 +1277,18 @@ static void BRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
||||
}
|
||||
}
|
||||
|
||||
static int BRI_timing_priority(xpd_t *xpd)
|
||||
{
|
||||
struct BRI_priv_data *priv;
|
||||
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if (priv->layer1_up)
|
||||
return PHONEDEV(xpd).timing_priority;
|
||||
XPD_DBG(SYNC, xpd, "No timing priority (no layer1)\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int BRI_echocancel_timeslot(xpd_t *xpd, int pos)
|
||||
{
|
||||
return xpd->addr.subunit * 4 + pos;
|
||||
@@ -1695,7 +1556,7 @@ static const struct phoneops bri_phoneops = {
|
||||
.card_pcm_recompute = BRI_card_pcm_recompute,
|
||||
.card_pcm_fromspan = BRI_card_pcm_fromspan,
|
||||
.card_pcm_tospan = BRI_card_pcm_tospan,
|
||||
.card_timing_priority = generic_timing_priority,
|
||||
.card_timing_priority = BRI_timing_priority,
|
||||
.echocancel_timeslot = BRI_echocancel_timeslot,
|
||||
.echocancel_setmask = BRI_echocancel_setmask,
|
||||
.card_ioctl = BRI_card_ioctl,
|
||||
@@ -1775,9 +1636,6 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in
|
||||
} else {
|
||||
len += sprintf(page + len, "(dead)\n");
|
||||
}
|
||||
#ifndef CONFIG_DAHDI_BRI_DCHANS
|
||||
len += sprintf(page + len, "hdlc_pending=%d\n", atomic_read(&priv->hdlc_pending));
|
||||
#endif
|
||||
len += sprintf(page + len, "dchan_notx_ticks: %d\n", priv->dchan_notx_ticks);
|
||||
len += sprintf(page + len, "dchan_norx_ticks: %d\n", priv->dchan_norx_ticks);
|
||||
len += sprintf(page + len, "LED: %-10s = %d\n", "GREEN", priv->ledstate[GREEN_LED]);
|
||||
@@ -1797,22 +1655,6 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in
|
||||
}
|
||||
#endif
|
||||
|
||||
static DRIVER_ATTR_READER(dchan_hardhdlc_show, drv,buf)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
#if defined(CONFIG_DAHDI_BRI_DCHANS)
|
||||
len += sprintf(buf + len, "0\n");
|
||||
#elif defined(DAHDI_SIG_HARDHDLC)
|
||||
len += sprintf(buf + len, "1\n");
|
||||
#else
|
||||
#error Cannot build BRI without BRISTUFF or HARDHDLC supprt
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
static DRIVER_ATTR(dchan_hardhdlc,S_IRUGO,dchan_hardhdlc_show,NULL);
|
||||
|
||||
static int bri_xpd_probe(struct device *dev)
|
||||
{
|
||||
xpd_t *xpd;
|
||||
@@ -1855,18 +1697,7 @@ static int __init card_bri_startup(void)
|
||||
|
||||
if((ret = xpd_driver_register(&bri_driver.driver)) < 0)
|
||||
return ret;
|
||||
ret = driver_create_file(&bri_driver.driver, &driver_attr_dchan_hardhdlc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
INFO("revision %s\n", XPP_VERSION);
|
||||
#if defined(CONFIG_DAHDI_BRI_DCHANS)
|
||||
INFO("FEATURE: WITH BRISTUFF\n");
|
||||
#elif defined(DAHDI_SIG_HARDHDLC)
|
||||
INFO("FEATURE: WITH HARDHDLC\n");
|
||||
#else
|
||||
#error Cannot build BRI without BRISTUFF or HARDHDLC supprt
|
||||
#endif
|
||||
|
||||
xproto_register(&PROTO_TABLE(BRI));
|
||||
return 0;
|
||||
}
|
||||
@@ -1875,7 +1706,6 @@ static void __exit card_bri_cleanup(void)
|
||||
{
|
||||
DBG(GENERAL, "\n");
|
||||
xproto_unregister(&PROTO_TABLE(BRI));
|
||||
driver_remove_file(&bri_driver.driver, &driver_attr_dchan_hardhdlc);
|
||||
xpd_driver_unregister(&bri_driver.driver);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -134,6 +134,7 @@ struct FXS_priv_data {
|
||||
xpp_line_t want_dtmf_events; /* what dahdi want */
|
||||
xpp_line_t want_dtmf_mute; /* what dahdi want */
|
||||
xpp_line_t prev_key_down; /* DTMF down sets the bit */
|
||||
xpp_line_t neon_blinking;
|
||||
struct timeval prev_key_time[CHANNELS_PERXPD];
|
||||
int led_counter[NUM_LEDS][CHANNELS_PERXPD];
|
||||
int ohttimer[CHANNELS_PERXPD];
|
||||
@@ -386,6 +387,8 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
||||
int regular_channels;
|
||||
struct FXS_priv_data *priv;
|
||||
int i;
|
||||
int d_inputs = 0;
|
||||
int d_outputs = 0;
|
||||
|
||||
if(!to_phone) {
|
||||
XBUS_NOTICE(xbus,
|
||||
@@ -398,16 +401,30 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
||||
else
|
||||
regular_channels = min(8, subunit_ports);
|
||||
channels = regular_channels;
|
||||
if(unit == 0 && subtype != 4)
|
||||
/* Calculate digital inputs/outputs */
|
||||
if(unit == 0 && subtype != 4) {
|
||||
channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
|
||||
d_inputs = LINES_DIGI_INP;
|
||||
d_outputs = LINES_DIGI_OUT;
|
||||
}
|
||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct FXS_priv_data), proto_table, channels);
|
||||
if(!xpd)
|
||||
return NULL;
|
||||
if(unit == 0) {
|
||||
XBUS_DBG(GENERAL, xbus, "First XPD detected. Initialize digital outputs/inputs\n");
|
||||
PHONEDEV(xpd).digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels;
|
||||
PHONEDEV(xpd).digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT);
|
||||
}
|
||||
/* Initialize digital inputs/outputs */
|
||||
if (d_inputs) {
|
||||
XBUS_DBG(GENERAL, xbus, "Initialize %d digital inputs\n",
|
||||
d_inputs);
|
||||
PHONEDEV(xpd).digital_inputs =
|
||||
BITMASK(d_inputs) << (regular_channels + d_outputs);
|
||||
} else
|
||||
XBUS_DBG(GENERAL, xbus, "No digital inputs\n");
|
||||
if (d_outputs) {
|
||||
XBUS_DBG(GENERAL, xbus, "Initialize %d digital outputs\n",
|
||||
d_outputs);
|
||||
PHONEDEV(xpd).digital_outputs =
|
||||
BITMASK(d_outputs) << regular_channels;
|
||||
} else
|
||||
XBUS_DBG(GENERAL, xbus, "No digital outputs\n");
|
||||
PHONEDEV(xpd).direction = TO_PHONE;
|
||||
xpd->type_name = "FXS";
|
||||
if(fxs_proc_create(xbus, xpd) < 0)
|
||||
@@ -548,12 +565,16 @@ static int FXS_card_dahdi_postregistration(xpd_t *xpd, bool on)
|
||||
*/
|
||||
static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
|
||||
{
|
||||
struct FXS_priv_data *priv;
|
||||
|
||||
priv = xpd->priv;
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE");
|
||||
if(muteit)
|
||||
BIT_SET(PHONEDEV(xpd).mute_dtmf, pos);
|
||||
else
|
||||
BIT_CLR(PHONEDEV(xpd).mute_dtmf, pos);
|
||||
CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0); /* already spinlocked */
|
||||
/* already spinlocked */
|
||||
CALL_PHONE_METHOD(card_pcm_recompute, xpd, priv->search_fsk_pattern);
|
||||
}
|
||||
|
||||
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
@@ -568,6 +589,7 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
if (VMWI_NEON(priv, pos) && msg_waiting) {
|
||||
/* A write to register 0x40 will now turn on/off the VM led */
|
||||
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
|
||||
BIT_SET(priv->neon_blinking, pos);
|
||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
|
||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B);
|
||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00);
|
||||
@@ -602,6 +624,7 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
} else {
|
||||
/* A write to register 0x40 will now turn on/off the ringer */
|
||||
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
|
||||
BIT_CLR(priv->neon_blinking, pos);
|
||||
|
||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00);
|
||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x77, 0x01);
|
||||
@@ -861,7 +884,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
if (IS_SET(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).digital_outputs, pos))
|
||||
return 0; /* Nothing to do */
|
||||
oht_pcm(xpd, pos, 1); /* Get ready of VMWI FSK tones */
|
||||
if(priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE) {
|
||||
if (priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE ||
|
||||
IS_SET(priv->neon_blinking, pos)) {
|
||||
priv->ohttimer[pos] = val;
|
||||
priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
|
||||
vmwi_search(xpd, pos, 1);
|
||||
@@ -924,10 +948,25 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
case DAHDI_SETPOLARITY:
|
||||
if (get_user(val, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
/* Can't change polarity while ringing or when open */
|
||||
/*
|
||||
* Asterisk may send us this if chan_dahdi config
|
||||
* has "hanguponpolarityswitch=yes" to notify
|
||||
* that the other side has hanged up.
|
||||
*
|
||||
* This has no effect on normal phone (but we may
|
||||
* be connected to another FXO equipment).
|
||||
* note that this chan_dahdi settings has different
|
||||
* meaning for FXO, where it signals polarity
|
||||
* reversal *detection* logic.
|
||||
*
|
||||
* It seems that sometimes we get this from
|
||||
* asterisk in wrong state (e.g: while ringing).
|
||||
* In these cases, silently ignore it.
|
||||
*/
|
||||
if (priv->lasttxhook[pos] == FXS_LINE_RING || priv->lasttxhook[pos] == FXS_LINE_OPEN) {
|
||||
LINE_ERR(xpd, pos, "DAHDI_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n",
|
||||
(val)?"ON":"OFF", priv->lasttxhook[pos]);
|
||||
LINE_DBG(SIGNAL, xpd, pos,
|
||||
"DAHDI_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n",
|
||||
(val)?"ON":"OFF", priv->lasttxhook[pos]);
|
||||
return -EINVAL;
|
||||
}
|
||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_SETPOLARITY: %s\n", (val)?"ON":"OFF");
|
||||
@@ -1029,7 +1068,8 @@ static void handle_linefeed(xpd_t *xpd)
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
for_each_line(xpd, i) {
|
||||
if (priv->lasttxhook[i] == FXS_LINE_RING) {
|
||||
if (priv->lasttxhook[i] == FXS_LINE_RING &&
|
||||
!IS_SET(priv->neon_blinking, i)) {
|
||||
/* RINGing, prepare for OHT */
|
||||
priv->ohttimer[i] = OHT_TIMER;
|
||||
priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS;
|
||||
@@ -1142,7 +1182,7 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
#ifdef POLL_DIGITAL_INPUTS
|
||||
if(poll_digital_inputs && xpd->xbus_idx == 0) {
|
||||
if (poll_digital_inputs && PHONEDEV(xpd).digital_inputs) {
|
||||
if((xpd->timer_count % poll_digital_inputs) == 0)
|
||||
poll_inputs(xpd);
|
||||
}
|
||||
@@ -1254,6 +1294,13 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
|
||||
bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
|
||||
xpp_line_t lines = BIT(info->portnum);
|
||||
|
||||
/* Sanity check */
|
||||
if (!PHONEDEV(xpd).digital_inputs) {
|
||||
XPD_NOTICE(xpd,
|
||||
"%s called without digital inputs. Ignored\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
/* Map SLIC number into line number */
|
||||
for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
|
||||
int channo = input_channels[i];
|
||||
@@ -1277,7 +1324,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'
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1299,12 +1347,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);
|
||||
@@ -1366,7 +1408,7 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
/*
|
||||
* Process digital inputs polling results
|
||||
*/
|
||||
else if(xpd->xbus_idx == 0 && !indirect && regnum == REG_DIGITAL_IOCTRL) {
|
||||
else if (!indirect && regnum == REG_DIGITAL_IOCTRL) {
|
||||
process_digital_inputs(xpd, info);
|
||||
}
|
||||
#endif
|
||||
@@ -1481,11 +1523,13 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
len += sprintf(page + len, "%-8s %-10s %-10s %-10s\n",
|
||||
len += sprintf(page + len, "%-8s %-10s %-10s %-10s %-10s %-10s\n",
|
||||
"Channel",
|
||||
"idletxhookstate",
|
||||
"lasttxhook",
|
||||
"ohttimer"
|
||||
"ohttimer",
|
||||
"neon_blinking",
|
||||
"search_fsk_pattern"
|
||||
);
|
||||
for_each_line(xpd, i) {
|
||||
char pref;
|
||||
@@ -1496,12 +1540,14 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
||||
pref = 'I';
|
||||
else
|
||||
pref = ' ';
|
||||
len += sprintf(page + len, "%c%7d %10d %10d %10d\n",
|
||||
len += sprintf(page + len, "%c%7d %10d %10d %10d %10d %10d\n",
|
||||
pref,
|
||||
i,
|
||||
priv->idletxhookstate[i],
|
||||
priv->lasttxhook[i],
|
||||
priv->ohttimer[i]
|
||||
priv->ohttimer[i],
|
||||
IS_SET(priv->neon_blinking, i),
|
||||
IS_SET(priv->search_fsk_pattern, i)
|
||||
);
|
||||
}
|
||||
len += sprintf(page + len, "\n");
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -40,6 +40,36 @@ extern int debug;
|
||||
|
||||
/*---------------- GLOBAL PROC handling -----------------------------------*/
|
||||
|
||||
static int send_magic_request(xbus_t *xbus,
|
||||
unsigned unit, xportno_t portno, bool eoftx)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Zero length multibyte is legal and has special meaning for the
|
||||
* firmware:
|
||||
* eoftx==1: Start sending us D-channel packets.
|
||||
* eoftx==0: Stop sending us D-channel packets.
|
||||
*/
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = 0;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->eoframe = eoftx;
|
||||
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
|
||||
if (debug & DBG_REGS)
|
||||
dump_xframe(__func__, xbus, xframe, debug);
|
||||
ret = send_cmd_frame(xbus, xframe);
|
||||
if (ret < 0)
|
||||
PORT_ERR(xbus, unit, portno,
|
||||
"%s: failed sending xframe\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_hexbyte(const char *buf)
|
||||
{
|
||||
char *endp;
|
||||
@@ -155,8 +185,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
addr_mode, argc - argno);
|
||||
goto out;
|
||||
}
|
||||
ret = send_multibyte_request(xpd->xbus, xpd->addr.unit, portno,
|
||||
addr_mode == 'm', NULL, 0);
|
||||
ret = send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
||||
addr_mode == 'm');
|
||||
goto out;
|
||||
}
|
||||
/* Normal (non-Magic) register commands */
|
||||
@@ -370,44 +400,6 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int send_multibyte_request(xbus_t *xbus,
|
||||
unsigned unit, xportno_t portno,
|
||||
bool eoftx, byte *buf, unsigned len)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Zero length multibyte is legal and has special meaning for the
|
||||
* firmware:
|
||||
* eoftx==1: Start sending us D-channel packets.
|
||||
* eoftx==0: Stop sending us D-channel packets.
|
||||
*/
|
||||
if(len > MULTIBYTE_MAX_LEN) {
|
||||
PORT_ERR(xbus, unit, portno, "%s: len=%d is too long. dropping.\n", __FUNCTION__, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
reg_cmd->bytes = len;
|
||||
reg_cmd->is_multibyte = 1;
|
||||
reg_cmd->portnum = portno;
|
||||
reg_cmd->eoframe = eoftx;
|
||||
if(len > 0) {
|
||||
memcpy(REG_XDATA(reg_cmd), (byte *)buf, len);
|
||||
} else {
|
||||
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
|
||||
}
|
||||
if(debug & DBG_REGS)
|
||||
dump_xframe(__FUNCTION__, xbus, xframe, debug);
|
||||
ret = send_cmd_frame(xbus, xframe);
|
||||
if(ret < 0)
|
||||
PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The XPD parameter is totaly ignored by the driver and firmware as well.
|
||||
*/
|
||||
@@ -642,7 +634,6 @@ static void global_packet_dump(const char *msg, xpacket_t *pack)
|
||||
DBG(GENERAL, "%s\n", msg);
|
||||
}
|
||||
|
||||
#define MAX_ENV_STR 40
|
||||
#define MAX_PATH_STR 128
|
||||
|
||||
int run_initialize_registers(xpd_t *xpd)
|
||||
@@ -651,6 +642,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
xbus_t *xbus;
|
||||
char busstr[MAX_ENV_STR];
|
||||
char busnumstr[MAX_ENV_STR];
|
||||
char modelstr[MAX_ENV_STR];
|
||||
char unitstr[MAX_ENV_STR];
|
||||
char subunitsstr[MAX_ENV_STR];
|
||||
char typestr[MAX_ENV_STR];
|
||||
@@ -668,6 +660,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
char *envp[] = {
|
||||
busstr,
|
||||
busnumstr,
|
||||
modelstr,
|
||||
unitstr,
|
||||
subunitsstr,
|
||||
typestr,
|
||||
@@ -703,6 +696,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
}
|
||||
snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
|
||||
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
|
||||
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s", xbus->transport.model_string);
|
||||
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
|
||||
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
|
||||
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
|
||||
@@ -750,4 +744,3 @@ err:
|
||||
EXPORT_SYMBOL(sync_mode_name);
|
||||
EXPORT_SYMBOL(run_initialize_registers);
|
||||
EXPORT_SYMBOL(xpp_register_request);
|
||||
EXPORT_SYMBOL(send_multibyte_request);
|
||||
|
||||
@@ -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)
|
||||
@@ -1019,6 +1034,17 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
||||
}
|
||||
#endif
|
||||
if(force_cas) {
|
||||
if(priv->pri_protocol == PRI_PROTO_E1) {
|
||||
int rs1 = 0x0B;
|
||||
|
||||
/*
|
||||
* Set correct X1-X3 bits in the E1 CAS MFAS
|
||||
* They are unused in E1 and should be 1
|
||||
*/
|
||||
XPD_DBG(GENERAL, xpd, "%s: rs1(0x%02X) = 0x%02X\n",
|
||||
__FUNCTION__, REG_RS1_E, rs1);
|
||||
write_subunit(xpd, REG_RS1_E, rs1);
|
||||
}
|
||||
xsp |= REG_XSP_E_CASEN; /* Same as REG_FMR5_T_EIBR for T1 */
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "%s: xsp(0x%02X) = 0x%02X\n", __FUNCTION__, REG_XSP_E, xsp);
|
||||
@@ -1029,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
|
||||
*/
|
||||
@@ -1204,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,
|
||||
@@ -1215,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
|
||||
@@ -1227,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;
|
||||
@@ -1237,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;
|
||||
@@ -1268,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;
|
||||
@@ -1424,14 +1478,17 @@ static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
return -ENODEV;
|
||||
chan = XPD_CHAN(xpd, pos);
|
||||
switch (cmd) {
|
||||
/*
|
||||
* Asterisk may send FXS type ioctl()'s to us:
|
||||
* - Some are sent to everybody (DAHDI_TONEDETECT)
|
||||
* - Some are sent because we may be in CAS mode
|
||||
* (FXS signalling)
|
||||
* Ignore them.
|
||||
*/
|
||||
case DAHDI_TONEDETECT:
|
||||
/*
|
||||
* Asterisk call all span types with this (FXS specific)
|
||||
* call. Silently ignore it.
|
||||
*/
|
||||
LINE_DBG(SIGNAL, xpd, pos, "PRI: TONEDETECT (%s)\n",
|
||||
(chan->flags & DAHDI_FLAG_AUDIO) ?
|
||||
"AUDIO" : "SILENCE");
|
||||
"AUDIO" : "SILENCE");
|
||||
return -ENOTTY;
|
||||
case DAHDI_ONHOOKTRANSFER:
|
||||
LINE_DBG(SIGNAL, xpd, pos, "PRI: ONHOOKTRANSFER\n");
|
||||
@@ -1442,6 +1499,10 @@ static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
case DAHDI_VMWI_CONFIG:
|
||||
LINE_DBG(SIGNAL, xpd, pos, "PRI: VMWI_CONFIG\n");
|
||||
return -ENOTTY;
|
||||
case DAHDI_SETPOLARITY:
|
||||
LINE_DBG(SIGNAL, xpd, pos, "PRI: SETPOLARITY\n");
|
||||
return -ENOTTY;
|
||||
/* report on really bad ioctl()'s */
|
||||
default:
|
||||
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
|
||||
return -ENOTTY;
|
||||
@@ -2210,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,
|
||||
@@ -2234,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)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# $Id: PIC_TYPE_1.hex 9732 2011-08-24 19:13:55Z dima $
|
||||
# $Id: PIC_TYPE_1.hex 9841 2011-09-08 17:00:23Z dima $
|
||||
#
|
||||
:03000000A1EA4A28
|
||||
:03000100C41C41DB
|
||||
@@ -31,8 +31,8 @@
|
||||
:03001B00D00D0005
|
||||
:03001C00A17A17AF
|
||||
:03001D0080080058
|
||||
:03001E00C0710BA3
|
||||
:03001F0016603830
|
||||
:03001E00C0010B13
|
||||
:03001F0019A038ED
|
||||
:03002000743C0627
|
||||
:03002100A26D804D
|
||||
:03002200C01024E7
|
||||
@@ -42,451 +42,445 @@
|
||||
:03002600C03030B7
|
||||
:0300270018C901F4
|
||||
:030028006432043B
|
||||
:03002900A4C03040
|
||||
:03002900A4A03060
|
||||
:03002A0020C901E9
|
||||
:03002B007432022A
|
||||
:03002C00AFA03052
|
||||
:03002D0020990116
|
||||
:03002E00021C8031
|
||||
:03002F00C40FFFFC
|
||||
:03003000D8016490
|
||||
:03003100024C106E
|
||||
:03003200C00FFFFD
|
||||
:0300330002215057
|
||||
:03003400201D0884
|
||||
:030035000306B906
|
||||
:03003600901D100A
|
||||
:0300370020402244
|
||||
:03003800030201BF
|
||||
:03003900901030F4
|
||||
:03003A0020290179
|
||||
:03003B00030204B9
|
||||
:03003C00901030F1
|
||||
:03003D00C11901E5
|
||||
:03003E00190202A2
|
||||
:03003F00643030FA
|
||||
:03004000A45901BF
|
||||
:03004100C22800D2
|
||||
:030042001902148C
|
||||
:03004300743E7098
|
||||
:03004400A483088A
|
||||
:03004500209308FD
|
||||
:030046001253084A
|
||||
:03004700A4B30857
|
||||
:03004800209027DE
|
||||
:03004900FFF800BD
|
||||
:03004A00165C0041
|
||||
:03004B00AFA0392A
|
||||
:03004C00209038C9
|
||||
:03004D00145C0739
|
||||
:03004E00643D40CE
|
||||
:03004F00A8C03412
|
||||
:03005000209C08E9
|
||||
:0300510002103862
|
||||
:03005200C40219CC
|
||||
:03005300D80E07BD
|
||||
:0300540002402047
|
||||
:03005500C0036085
|
||||
:0300560002236022
|
||||
:0300570020136013
|
||||
:030058000303603F
|
||||
:03005900901C10E8
|
||||
:03005A002040380B
|
||||
:03005B0003021984
|
||||
:03005C00901E07EC
|
||||
:03005D002021203F
|
||||
:03005E00030C1080
|
||||
:03005F009011807D
|
||||
:03006000C11E704E
|
||||
:0300610019074339
|
||||
:03006200643A728B
|
||||
:03006300A68C0266
|
||||
:03006400C2218036
|
||||
:03006500190E076A
|
||||
:03006600743643AA
|
||||
:03006700A8CA75AF
|
||||
:03006800209C03D6
|
||||
:0300690002118001
|
||||
:03006A00C44E077A
|
||||
:03006B00D8064371
|
||||
:03006C00024A75D0
|
||||
:03006D00C00C04C0
|
||||
:03006E00022180EC
|
||||
:03006F00201E0749
|
||||
:0300700003064341
|
||||
:03007100901A756D
|
||||
:03007200204C011E
|
||||
:030073000300384F
|
||||
:03007400901A746B
|
||||
:03007500202C1824
|
||||
:030076000300384C
|
||||
:03007700901219CB
|
||||
:03007800210E0F47
|
||||
:03007900E0303D37
|
||||
:03007A00743C00D3
|
||||
:03007B00C040384A
|
||||
:03007C00190C025A
|
||||
:03007D007481800B
|
||||
:03007E00A8CE0702
|
||||
:03007F00C0474334
|
||||
:03008000FFFA85FF
|
||||
:03008100150C3F1C
|
||||
:03008200643031B6
|
||||
:03008300A87C1640
|
||||
:03008400209A922D
|
||||
:0300850013EC0376
|
||||
:03008600A8A180AE
|
||||
:03008700209E07B1
|
||||
:03008800FFF7433C
|
||||
:0300890017EA8EE5
|
||||
:03008A0021ECFF67
|
||||
:03008B00035031EE
|
||||
:03008C00C14C184C
|
||||
:03008D00D80A92FC
|
||||
:03008E00024C031E
|
||||
:03008F00C000317D
|
||||
:03009000022C122D
|
||||
:03009100201A92A0
|
||||
:0300920003003C2C
|
||||
:03009300901E0FAD
|
||||
:0300940020409D6C
|
||||
:030095000307035B
|
||||
:03009600901A9C21
|
||||
:03009700202C0F0B
|
||||
:03009800030FFF54
|
||||
:0300990090115C67
|
||||
:03009A0021011D24
|
||||
:03009B00E01A9DCB
|
||||
:03009C0002721CD1
|
||||
:03009D00C18030EF
|
||||
:03009E00D80E0F6A
|
||||
:03009F0002403CE0
|
||||
:0300A000C00C028F
|
||||
:0300A10002203901
|
||||
:0300A200201C001F
|
||||
:0300A3000300391E
|
||||
:0300A400901C802D
|
||||
:0300A500204024D4
|
||||
:0300A600030C0840
|
||||
:0300A700901104B1
|
||||
:0300A800202039DC
|
||||
:0300A900030C0045
|
||||
:0300AA009010397A
|
||||
:0300AB00210C0025
|
||||
:0300AC0003B02678
|
||||
:0300AD00C140252A
|
||||
:0300AE0002403ECF
|
||||
:0300AF00C0102B53
|
||||
:0300B000022C031C
|
||||
:0300B10020102CF0
|
||||
:0300B200030C40FC
|
||||
:0300B30090103971
|
||||
:0300B4002047D909
|
||||
:0300B500030AB487
|
||||
:0300B600901C009B
|
||||
:0300B700207208AC
|
||||
:0300B80003003012
|
||||
:0300B9009019019A
|
||||
:0300BA0021AC80F6
|
||||
:0300BB0014120814
|
||||
:0300BC0070703031
|
||||
:0300BD00AC09018A
|
||||
:0300BE00181C40CB
|
||||
:0300BF00AC303929
|
||||
:0300C00069BC0117
|
||||
:0300C100AFA037B6
|
||||
:0300C200F00C60DF
|
||||
:0300C3002282C8CE
|
||||
:0300C400643AC3D8
|
||||
:0300C500AFAC00DD
|
||||
:0300C6001BA03745
|
||||
:0300C700C106D996
|
||||
:0300C800FFFACC70
|
||||
:0300C90017B6F96E
|
||||
:0300CA0021ABCF98
|
||||
:0300CB00141AC73D
|
||||
:0300CC0064394252
|
||||
:0300CD00AD0C0275
|
||||
:0300CE00C10180ED
|
||||
:0300CF0013BE0756
|
||||
:0300D000C507431E
|
||||
:0300D100039AEDA2
|
||||
:0300D200799C0610
|
||||
:0300D300AD2195C7
|
||||
:0300D40020B7430F
|
||||
:0300D500D00AED61
|
||||
:0300D6000387D3CA
|
||||
:0300D700219AED7E
|
||||
:0300D800E07C06C3
|
||||
:0300D900348187E8
|
||||
:0300DA0034874325
|
||||
:0300DB00348ADE86
|
||||
:0300DC00348C035E
|
||||
:0300DD00030AEB28
|
||||
:0300DE00206C078C
|
||||
:0300DF00348187E2
|
||||
:0300E0003487431F
|
||||
:0300E100348AE47A
|
||||
:0300E200348C015A
|
||||
:0300E300D05AEB05
|
||||
:0300E400031C03F7
|
||||
:0300E500C00187D0
|
||||
:0300E600032743AA
|
||||
:0300E700033AEAEF
|
||||
:0300E800C70C0042
|
||||
:0300E900039AEB8C
|
||||
:0300EA00C5020745
|
||||
:0300EB0003902758
|
||||
:0300EC00C18AFACC
|
||||
:0300ED00030C06FB
|
||||
:0300EE00C00195B9
|
||||
:0300EF00031643B2
|
||||
:0300F00021BAFA38
|
||||
:0300F100032C01DC
|
||||
:0300F200C001C783
|
||||
:0300F30003309C3B
|
||||
:0300F400C7070338
|
||||
:0300F500039AFA71
|
||||
:0300F600C50CFF37
|
||||
:0300F70003902251
|
||||
:0300F800C400271A
|
||||
:0300F900039B6204
|
||||
:0300FA00369C0031
|
||||
:0300FB00C016F339
|
||||
:0300FC001E6CFF78
|
||||
:0300FD0021C021FE
|
||||
:0300FE00086C018A
|
||||
:0300FF0074302436
|
||||
:03010000A1E90A68
|
||||
:030101000266B3E0
|
||||
:03010200C02B8986
|
||||
:03010300FFFC01FD
|
||||
:0301040016B02F03
|
||||
:03010500C0221500
|
||||
:0301060023E6D31A
|
||||
:03010700743D80C4
|
||||
:0301080012B0240E
|
||||
:0301090020B2170A
|
||||
:03010A000380224D
|
||||
:03010B00C44C06DB
|
||||
:03010C00039195C7
|
||||
:03010D00C40743E1
|
||||
:03010E00039B51FF
|
||||
:03010F00C006D354
|
||||
:03011000023B515E
|
||||
:03011100ABECE074
|
||||
:03011200B12157C1
|
||||
:03011300000643A0
|
||||
:03011400000B518C
|
||||
:03011500000C00DB
|
||||
:030116000007B728
|
||||
:03011700000C05D4
|
||||
:030118000007D706
|
||||
:03011900000C10C7
|
||||
:03011A000007F7E4
|
||||
:03011B00000C02D3
|
||||
:03011C00000027B9
|
||||
:03011D00000C10C3
|
||||
:03011E00000D02CF
|
||||
:03011F00000FFFCF
|
||||
:0301200000014299
|
||||
:030121000006973E
|
||||
:03012200000D02CB
|
||||
:030123000006379C
|
||||
:03012400000D10BB
|
||||
:03012500000022B5
|
||||
:03012600000C804A
|
||||
:03012700000124B0
|
||||
:03012800000C02C6
|
||||
:0301290000018052
|
||||
:03012A00000E07BD
|
||||
:03012B0000074387
|
||||
:03012C00000B3F86
|
||||
:03012D00000C05BE
|
||||
:03012E0000014786
|
||||
:03012F0000064384
|
||||
:03013000000B3F82
|
||||
:03013100000C01BE
|
||||
:0301320000018148
|
||||
:030133000007437F
|
||||
:03013400000B3885
|
||||
:03013500000C10AB
|
||||
:03013600000021A5
|
||||
:03013700000B3F7B
|
||||
:03013800000C10A8
|
||||
:0301390000018141
|
||||
:03013A0000074378
|
||||
:03013B00000B3F77
|
||||
:03013C00000C2094
|
||||
:03013D000000219E
|
||||
:03013E00000B3F74
|
||||
:03013F00000201BA
|
||||
:03002C00AE803073
|
||||
:03002D00C4090102
|
||||
:03002E00D80C806B
|
||||
:03002F00024FFF7E
|
||||
:03003000C00164A8
|
||||
:03003100022C108E
|
||||
:03003200209FFF0D
|
||||
:0300330003015076
|
||||
:03003400901D0814
|
||||
:030035002046B9A9
|
||||
:03003600030D10A7
|
||||
:0300370090102204
|
||||
:0300380020220182
|
||||
:0300390003003091
|
||||
:03003A0090190119
|
||||
:03003B00C11204EB
|
||||
:03003C0019003078
|
||||
:03003D0064390122
|
||||
:03003E00A43202E7
|
||||
:03003F00C22030AC
|
||||
:030040001909019A
|
||||
:0300410074380010
|
||||
:03004200A46214A1
|
||||
:03004300209E708C
|
||||
:030044001253084C
|
||||
:03004500A4930879
|
||||
:03004600209308FC
|
||||
:03004700FFF308BC
|
||||
:0300480016502728
|
||||
:03004900AE88007E
|
||||
:03004A00209C00F7
|
||||
:03004B0014503915
|
||||
:03004C00643038E5
|
||||
:03004D00A8603F69
|
||||
:03004E00C40C07D8
|
||||
:03004F00D80D4089
|
||||
:0300500002403437
|
||||
:03005100C00C08D8
|
||||
:0300520002203851
|
||||
:03005300209219DF
|
||||
:03005400030E0791
|
||||
:03005500901020E8
|
||||
:03005600204360E4
|
||||
:0300570003036040
|
||||
:03005800901360A2
|
||||
:0300590020236001
|
||||
:03005A00030C1084
|
||||
:03005B00901038CA
|
||||
:03005C00C11219B5
|
||||
:03005D00190E0772
|
||||
:03005E00643120EA
|
||||
:03005F00A64C109C
|
||||
:03006000C221803A
|
||||
:03006100190E7005
|
||||
:03006200743743AD
|
||||
:03006300A86A7315
|
||||
:03006400C44C0287
|
||||
:03006500D801803F
|
||||
:03006600024E0740
|
||||
:03006700C006438D
|
||||
:03006800022A76F3
|
||||
:03006900209C03D5
|
||||
:03006A000301800F
|
||||
:03006B00901E07DD
|
||||
:03006C00204643E8
|
||||
:03006D00030A760D
|
||||
:03006E00901C04DF
|
||||
:03006F00202180CD
|
||||
:03007000030E0775
|
||||
:03007100901643A3
|
||||
:03007200210A76EA
|
||||
:03007300E03C016D
|
||||
:03007400743038AD
|
||||
:03007500C04A7509
|
||||
:03007600190C184A
|
||||
:030077007480385A
|
||||
:03007800A8621962
|
||||
:03007900C04E0F67
|
||||
:03007A00FFF03D57
|
||||
:03007B00150C0061
|
||||
:03007C00643038B5
|
||||
:03007D00A81C02BA
|
||||
:03007E002091804E
|
||||
:03007F0013EE0776
|
||||
:03008000A847434B
|
||||
:03008100209A863C
|
||||
:03008200FFFC3F41
|
||||
:0300830017E03152
|
||||
:0300840021EC1656
|
||||
:03008500035A9388
|
||||
:03008600C14C0367
|
||||
:03008700D801801D
|
||||
:03008800024E071E
|
||||
:03008900C007436A
|
||||
:03008A00022A8FB8
|
||||
:03008B00209CFFB7
|
||||
:03008C000300313D
|
||||
:03008D00901C18AC
|
||||
:03008E00204A9372
|
||||
:03008F00030C035C
|
||||
:030090009010319C
|
||||
:03009100202C120E
|
||||
:03009200030A93CB
|
||||
:0300930090103C8E
|
||||
:03009400210E0F2B
|
||||
:0300950002709D59
|
||||
:03009600C147035C
|
||||
:03009700024A9D7D
|
||||
:03009800209C0F9A
|
||||
:03009900030FFF53
|
||||
:03009A0090115C66
|
||||
:03009B0020411DE4
|
||||
:03009C00030A9EB6
|
||||
:03009D0090121CA2
|
||||
:03009E002070309F
|
||||
:03009F00030E0F3E
|
||||
:0300A00090103C81
|
||||
:0300A100C18C020D
|
||||
:0300A200D800394A
|
||||
:0300A300024C000C
|
||||
:0300A400C0003960
|
||||
:0300A500022C80AA
|
||||
:0300A60020902483
|
||||
:0300A700030C083F
|
||||
:0300A800901104B0
|
||||
:0300A900204039BB
|
||||
:0300AA00030C0044
|
||||
:0300AB0090103979
|
||||
:0300AC00202C0005
|
||||
:0300AD0003003A13
|
||||
:0300AE009010258A
|
||||
:0300AF0021003EEF
|
||||
:0300B00003B02B6F
|
||||
:0300B100707C035D
|
||||
:0300B200AB602C14
|
||||
:0300B300209C404E
|
||||
:0300B40013F0390D
|
||||
:0300B500ABE7D9DD
|
||||
:0300B600209AB5D8
|
||||
:0300B70015FC0035
|
||||
:0300B800643208A7
|
||||
:0300B900AE8030E6
|
||||
:0300BA0069B90120
|
||||
:0300BB00AE8C8088
|
||||
:0300BC0020920887
|
||||
:0300BD001BF03005
|
||||
:0300BE00C5090170
|
||||
:0300BF00039C405F
|
||||
:0300C000799039FB
|
||||
:0300C100AC06D9B1
|
||||
:0300C20020BAC69B
|
||||
:0300C300D006F96B
|
||||
:0300C400038BC9E2
|
||||
:0300C500219AC1BC
|
||||
:0300C600E079429C
|
||||
:0300C700348C0274
|
||||
:0300C80034818000
|
||||
:0300C900348E076B
|
||||
:0300CA0034874335
|
||||
:0300CB00030AE73E
|
||||
:0300CC0021AC065E
|
||||
:0300CD00348195E6
|
||||
:0300CE0034874331
|
||||
:0300CF00348AE789
|
||||
:0300D0003487D39F
|
||||
:0300D100D05AE71B
|
||||
:0300D200031C0606
|
||||
:0300D300C00187E2
|
||||
:0300D400032743BC
|
||||
:0300D500033AD813
|
||||
:0300D600C70C0351
|
||||
:0300D700039AE5A4
|
||||
:0300D800C50C074D
|
||||
:0300D90003918709
|
||||
:0300DA00C1874398
|
||||
:0300DB00030ADE37
|
||||
:0300DC00C00C0154
|
||||
:0300DD00031AE51E
|
||||
:0300DE0021BC033F
|
||||
:0300DF0003218773
|
||||
:0300E000C0074313
|
||||
:0300E100033AE4FB
|
||||
:0300E200C70C0048
|
||||
:0300E300039AE598
|
||||
:0300E400C502074B
|
||||
:0300E5000390275E
|
||||
:0300E600C40AF455
|
||||
:0300E700039C0671
|
||||
:0300E800369195B9
|
||||
:0300E900C01643FB
|
||||
:0300EA001FAAF456
|
||||
:0300EB0021CC0124
|
||||
:0300EC0009A1C7A0
|
||||
:0300ED0074309CD0
|
||||
:0300EE00A1E70384
|
||||
:0300EF0003AAF46D
|
||||
:0300F000C02CFF22
|
||||
:0300F100FFF022FB
|
||||
:0300F20016B0271E
|
||||
:0300F300C02B5CC3
|
||||
:0300F40023EC00FA
|
||||
:0300F5007436F36B
|
||||
:0300F60012BCFF3A
|
||||
:0300F70020B02115
|
||||
:0300F800038C0175
|
||||
:0300F900C44024DC
|
||||
:0300FA0003990A5D
|
||||
:0300FB00C406B385
|
||||
:0300FC00039B83E0
|
||||
:0300FD00C00C0133
|
||||
:0300FE0002302F9E
|
||||
:0300FF00ABF2154C
|
||||
:03010000B006D373
|
||||
:03010100000D806E
|
||||
:03010200000024D6
|
||||
:03010300000217E0
|
||||
:03010400000022D6
|
||||
:03010500000C06E5
|
||||
:0301060000019560
|
||||
:03010700000743AB
|
||||
:03010800000B4B9E
|
||||
:030109000006D31A
|
||||
:03010A00000B4B9C
|
||||
:03010B00000CE005
|
||||
:03010C0000015798
|
||||
:03010D00000643A6
|
||||
:03010E00000B4B98
|
||||
:03010F00000C00E1
|
||||
:030110000007B72E
|
||||
:03011100000C05DA
|
||||
:030112000007D70C
|
||||
:03011300000C10CD
|
||||
:030114000007F7EA
|
||||
:03011500000C02D9
|
||||
:03011600000027BF
|
||||
:03011700000C10C9
|
||||
:03011800000D02D5
|
||||
:03011900000FFFD5
|
||||
:03011A000001429F
|
||||
:03011B0000069744
|
||||
:03011C00000D02D1
|
||||
:03011D00000637A2
|
||||
:03011E00000D10C1
|
||||
:03011F00000022BB
|
||||
:03012000000C8050
|
||||
:03012100000124B6
|
||||
:03012200000C02CC
|
||||
:0301230000018058
|
||||
:03012400000E07C3
|
||||
:030125000007438D
|
||||
:03012600000B3992
|
||||
:03012700000C05C4
|
||||
:030128000001478C
|
||||
:030129000006438A
|
||||
:03012A00000B398E
|
||||
:03012B00000C01C4
|
||||
:03012C000001814E
|
||||
:03012D0000074385
|
||||
:03012E00000B3291
|
||||
:03012F00000C10B1
|
||||
:03013000000021AB
|
||||
:03013100000B3987
|
||||
:03013200000C10AE
|
||||
:0301330000018147
|
||||
:030134000007437E
|
||||
:03013500000B3983
|
||||
:03013600000C209A
|
||||
:03013700000021A4
|
||||
:03013800000B3980
|
||||
:03013900000201C0
|
||||
:03013A0000003092
|
||||
:03013B00000901B7
|
||||
:03013C00000204BA
|
||||
:03013D000000308F
|
||||
:03013E00000901B4
|
||||
:03013F00000202B9
|
||||
:030140000000308C
|
||||
:03014100000901B1
|
||||
:03014200000204B4
|
||||
:0301430000003089
|
||||
:03014400000901AE
|
||||
:03014500000202B3
|
||||
:0301460000003086
|
||||
:03014700000901AB
|
||||
:03014800000C8028
|
||||
:03014900000FFFA5
|
||||
:03014A000001644D
|
||||
:03014B00000207A8
|
||||
:03014C000001624D
|
||||
:03014D00000FFFA1
|
||||
:03014E000001505D
|
||||
:03014F00000D0898
|
||||
:0301500000012289
|
||||
:03015100000201A8
|
||||
:03014200000C802E
|
||||
:03014300000FFFAB
|
||||
:0301440000016453
|
||||
:03014500000207AE
|
||||
:0301460000016253
|
||||
:03014700000FFFA7
|
||||
:0301480000015063
|
||||
:03014900000D089E
|
||||
:03014A000001228F
|
||||
:03014B00000201AE
|
||||
:03014C0000003080
|
||||
:03014D00000901A5
|
||||
:03014E00000204A8
|
||||
:03014F000000307D
|
||||
:03015000000901A2
|
||||
:03015100000202A7
|
||||
:030152000000307A
|
||||
:030153000009019F
|
||||
:03015400000204A2
|
||||
:0301550000003077
|
||||
:030156000009019C
|
||||
:03015700000202A1
|
||||
:0301580000003074
|
||||
:0301590000090199
|
||||
:03015A00000C0096
|
||||
:03015B0000002F72
|
||||
:03015C000007D3C6
|
||||
:03015D00000B8410
|
||||
:03015E000002108C
|
||||
:03015F000000227B
|
||||
:0301600000020E8C
|
||||
:0301610000002774
|
||||
:03016200000C503E
|
||||
:0301630000003960
|
||||
:03016400000799F8
|
||||
:03016500000B6428
|
||||
:0301660000021282
|
||||
:0301670000003065
|
||||
:030168000002147E
|
||||
:0301690000003162
|
||||
:03016A000002137D
|
||||
:03016B000006B3D8
|
||||
:03016C00000D1073
|
||||
:03016D000000325D
|
||||
:03016E00000C0082
|
||||
:03016F000000335A
|
||||
:03017000000C7010
|
||||
:0301710000003952
|
||||
:03017200000C502E
|
||||
:0301730000003950
|
||||
:0301740000021571
|
||||
:0301750000003057
|
||||
:030176000002166E
|
||||
:0301770000003154
|
||||
:0301780000020280
|
||||
:0301790000003251
|
||||
:03017A00000C0076
|
||||
:03017B000006B3C8
|
||||
:03017C0000020777
|
||||
:03017D000000334C
|
||||
:03017E00000C7002
|
||||
:03015400000C009C
|
||||
:0301550000002F78
|
||||
:030156000007D3CC
|
||||
:03015700000B7E1C
|
||||
:0301580000021092
|
||||
:0301590000002281
|
||||
:03015A0000020E92
|
||||
:03015B000000277A
|
||||
:03015C00000C5044
|
||||
:03015D0000003966
|
||||
:03015E00000799FE
|
||||
:03015F00000B5E34
|
||||
:0301600000021288
|
||||
:030161000000306B
|
||||
:0301620000021484
|
||||
:0301630000003168
|
||||
:0301640000021383
|
||||
:030165000006B3DE
|
||||
:03016600000D1079
|
||||
:0301670000003263
|
||||
:03016800000C0088
|
||||
:0301690000003360
|
||||
:03016A00000C7016
|
||||
:03016B0000003958
|
||||
:03016C00000C5034
|
||||
:03016D0000003956
|
||||
:03016E0000021577
|
||||
:03016F000000305D
|
||||
:0301700000021674
|
||||
:030171000000315A
|
||||
:0301720000020286
|
||||
:0301730000003257
|
||||
:03017400000C007C
|
||||
:030175000006B3CE
|
||||
:030176000002077D
|
||||
:0301770000003352
|
||||
:03017800000C7008
|
||||
:030179000000394A
|
||||
:03017A00000C5026
|
||||
:03017B0000003948
|
||||
:03017C00000C4034
|
||||
:03017D0000003946
|
||||
:03017E00000C0072
|
||||
:03017F0000003944
|
||||
:03018000000C5020
|
||||
:0301810000003942
|
||||
:03018200000C402E
|
||||
:0301830000003940
|
||||
:03018400000C006C
|
||||
:030185000000393E
|
||||
:03018600000C006A
|
||||
:03018000000C0070
|
||||
:03018100000C006F
|
||||
:03018200000ABFB1
|
||||
:03018300000C026B
|
||||
:0301840000002F49
|
||||
:03018500000C0A61
|
||||
:0301860000002A4C
|
||||
:03018700000C0069
|
||||
:03018800000ABEAC
|
||||
:03018900000C0265
|
||||
:03018A0000002F43
|
||||
:03018B00000C0A5B
|
||||
:03018C0000002A46
|
||||
:03018D00000C0063
|
||||
:03018E000000244A
|
||||
:03018F000007D393
|
||||
:03019000000BACB5
|
||||
:0301910000020168
|
||||
:0301880000002450
|
||||
:030189000007D399
|
||||
:03018A00000BA6C1
|
||||
:03018B000002016E
|
||||
:03018C0000003040
|
||||
:03018D0000090165
|
||||
:03018E0000021557
|
||||
:03018F000000303D
|
||||
:0301900000090162
|
||||
:0301910000021653
|
||||
:030192000000303A
|
||||
:030193000009015F
|
||||
:0301940000021551
|
||||
:0301950000003037
|
||||
:030196000009015C
|
||||
:030197000002164D
|
||||
:03019400000C1F3D
|
||||
:03019500000D80DA
|
||||
:0301960000002244
|
||||
:0301970000020162
|
||||
:0301980000003034
|
||||
:0301990000090159
|
||||
:03019A00000C1F37
|
||||
:03019B00000D80D4
|
||||
:03019C000000223E
|
||||
:03019D000002015C
|
||||
:03019A000002025E
|
||||
:03019B0000003031
|
||||
:03019C0000090156
|
||||
:03019D0000020459
|
||||
:03019E000000302E
|
||||
:03019F0000090153
|
||||
:0301A00000020258
|
||||
:0301A1000000302B
|
||||
:0301A20000090150
|
||||
:0301A30000020453
|
||||
:0301A40000003028
|
||||
:0301A5000009014D
|
||||
:0301A6000002EA6A
|
||||
:0301A7000007103E
|
||||
:0301A800000BAA9F
|
||||
:0301A900000B9DAB
|
||||
:0301AA000007D378
|
||||
:0301AB00000BCA7C
|
||||
:0301AC00000C1D27
|
||||
:0301AD000006D376
|
||||
:0301AE00000D80C1
|
||||
:0301AF000000222B
|
||||
:0301B00000020149
|
||||
:0301A0000002EA70
|
||||
:0301A10000071044
|
||||
:0301A200000BA4AB
|
||||
:0301A300000B97B7
|
||||
:0301A4000007D37E
|
||||
:0301A500000BC488
|
||||
:0301A600000C1D2D
|
||||
:0301A7000006D37C
|
||||
:0301A800000D80C7
|
||||
:0301A90000002231
|
||||
:0301AA000002014F
|
||||
:0301AB0000003021
|
||||
:0301AC0000090146
|
||||
:0301AD000002024B
|
||||
:0301AE000000301E
|
||||
:0301AF0000090143
|
||||
:0301B00000021832
|
||||
:0301B1000000301B
|
||||
:0301B20000090140
|
||||
:0301B30000020245
|
||||
:0301B40000003018
|
||||
:0301B5000009013D
|
||||
:0301B6000002182C
|
||||
:0301B70000003015
|
||||
:0301B8000009013A
|
||||
:0301B90000021031
|
||||
:0301BA0000002E14
|
||||
:0301BB00000C1C19
|
||||
:0301BC000006D367
|
||||
:0301BD00000D80B2
|
||||
:0301BE000000221C
|
||||
:0301BF000002013A
|
||||
:0301B30000021037
|
||||
:0301B40000002E1A
|
||||
:0301B500000C1C1F
|
||||
:0301B6000006D36D
|
||||
:0301B700000D80B8
|
||||
:0301B80000002222
|
||||
:0301B90000020140
|
||||
:0301BA0000003012
|
||||
:0301BB0000090137
|
||||
:0301BC000002023C
|
||||
:0301BD000000300F
|
||||
:0301BE0000090134
|
||||
:0301BF0000021724
|
||||
:0301C0000000300C
|
||||
:0301C10000090131
|
||||
:0301C20000020236
|
||||
:0301C30000003009
|
||||
:0301C4000009012E
|
||||
:0301C5000002171E
|
||||
:0301C60000003006
|
||||
:0301C7000009012B
|
||||
:0301C8000007D35A
|
||||
:0301C900000B9197
|
||||
:0301CA00000C0026
|
||||
:0301CB0000002F02
|
||||
:0301CC000007D356
|
||||
:0301CD00000B84A0
|
||||
:0301CE00000B5EC5
|
||||
:0301CF00000C071A
|
||||
:0301D00000002FFD
|
||||
:0301D100000C041B
|
||||
:0301D20000002109
|
||||
:0301D300000C001D
|
||||
:0301D40000091E01
|
||||
:0301C2000007D360
|
||||
:0301C300000B8BA3
|
||||
:0301C400000C002C
|
||||
:0301C50000002F08
|
||||
:0301C6000007D35C
|
||||
:0301C700000B7EAC
|
||||
:0301C800000B58D1
|
||||
:0301C900000C0720
|
||||
:0301CA0000002F03
|
||||
:0301CB00000C0421
|
||||
:0301CC000000210F
|
||||
:0301CD00000C0023
|
||||
:0301CE0000091E07
|
||||
:0301CF00000C1011
|
||||
:0301D0000000210B
|
||||
:0301D100000C0817
|
||||
:0301D20000091E03
|
||||
:0301D300000C40DD
|
||||
:0301D40000002107
|
||||
:0301D500000C100B
|
||||
:0301D60000002105
|
||||
:0301D700000C0811
|
||||
:0301D80000091EFD
|
||||
:0301D900000C40D7
|
||||
:0301DA0000002101
|
||||
:0301DB00000C1005
|
||||
:0301DC0000091EF9
|
||||
:0301DD00000C0013
|
||||
:0301DE00000026F8
|
||||
:0301DF00000C0110
|
||||
:0301E000000029F3
|
||||
:0301E100000C000F
|
||||
:0301E20000002FEB
|
||||
:0301E300000C20ED
|
||||
:0301E400000023F5
|
||||
:0301E500000A000D
|
||||
:0301E600000ABE4E
|
||||
:0301E700000BE723
|
||||
:0301D60000091EFF
|
||||
:0301D700000C0019
|
||||
:0301D80000003AEA
|
||||
:0301D900000C0116
|
||||
:0301DA00000029F9
|
||||
:0301DB00000C0015
|
||||
:0301DC0000002FF1
|
||||
:0301DD00000C20F3
|
||||
:0301DE00000023FB
|
||||
:0301DF00000A0013
|
||||
:0301E000000ABF53
|
||||
:0301E100000BE12F
|
||||
:00000001FF
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,7 @@ BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
|
||||
use XppConfig $init_dir;
|
||||
my $unit_id;
|
||||
my %opts;
|
||||
my $vbat_48 = 0;
|
||||
|
||||
getopts('o:', \%opts);
|
||||
|
||||
@@ -78,6 +79,7 @@ if (-t STDERR) {
|
||||
foreach my $k (qw(
|
||||
XBUS_NAME
|
||||
XBUS_NUMBER
|
||||
XBUS_MODEL_STRING
|
||||
UNIT_NUMBER
|
||||
UNIT_TYPE
|
||||
UNIT_SUBUNITS
|
||||
@@ -90,6 +92,10 @@ if (-t STDERR) {
|
||||
die;
|
||||
}
|
||||
}
|
||||
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
|
||||
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
|
||||
$vbat_48 = 1;
|
||||
}
|
||||
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
|
||||
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
|
||||
if(! -f $chipregs) {
|
||||
@@ -286,11 +292,15 @@ sub init_indirect_registers() {
|
||||
}
|
||||
|
||||
sub init_early_direct_regs() {
|
||||
my $lbv = ($vbat_48) ? "20" : "10";
|
||||
my $vcm = ($vbat_48) ? "02" : "03";
|
||||
|
||||
return write_to_slic_file("#
|
||||
* WD 08 00 # Audio Path Loopback Control
|
||||
* WD 6C 01
|
||||
* WD 4A 3F # High Battery Voltage
|
||||
* WD 4B 10 # Low Battery Voltage
|
||||
* WD 4B $lbv # Low Battery Voltage
|
||||
* WD 49 $vcm # Common Mode Voltage (VCM)
|
||||
* WD 40 00 # Line Feed Control
|
||||
#")
|
||||
}
|
||||
@@ -578,9 +588,6 @@ __DATA__
|
||||
# On-Hook Line Voltage (VOC)
|
||||
* WD 48 20
|
||||
|
||||
# Common Mode Voltage (VCM)
|
||||
* WD 49 03
|
||||
|
||||
* WS 1E 23 00 80
|
||||
* WS 1E 24 20 03
|
||||
* WS 1E 25 8C 00
|
||||
|
||||
@@ -58,9 +58,11 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer,
|
||||
|
||||
/* Command line parameters */
|
||||
extern int debug;
|
||||
static DEF_PARM(uint, command_queue_length, 1000, 0444, "Maximal command queue length");
|
||||
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;
|
||||
@@ -871,6 +872,100 @@ err:
|
||||
goto out;
|
||||
}
|
||||
|
||||
int xbus_is_registered(xbus_t *xbus)
|
||||
{
|
||||
return xbus->ddev && xbus->ddev->dev.parent;
|
||||
}
|
||||
|
||||
int xbus_register_dahdi_device(xbus_t *xbus)
|
||||
{
|
||||
int i;
|
||||
int offset = 0;
|
||||
|
||||
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
||||
if (xbus_is_registered(xbus)) {
|
||||
XBUS_ERR(xbus, "Already registered to DAHDI\n");
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
xbus->ddev = dahdi_create_device();
|
||||
/*
|
||||
* 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)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* 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");
|
||||
return -ENODEV;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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__);
|
||||
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;
|
||||
}
|
||||
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 +1029,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 +1303,12 @@ 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_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] */
|
||||
}
|
||||
|
||||
@@ -1316,7 +1413,6 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *tran
|
||||
xbus = xbus_alloc();
|
||||
if(!xbus) {
|
||||
ERR("%s: Failed allocating new xbus\n", __FUNCTION__);
|
||||
module_put(THIS_MODULE);
|
||||
return NULL;
|
||||
}
|
||||
snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%02d", xbus->num);
|
||||
@@ -1788,10 +1884,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();
|
||||
}
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
#include "xframe_queue.h"
|
||||
#include "xbus-pcm.h"
|
||||
|
||||
#define MAX_BUSES 32
|
||||
#define XFRAME_DATASIZE 512
|
||||
#define MAX_BUSES 128
|
||||
#define XFRAME_DATASIZE 512
|
||||
#define MAX_ENV_STR 40
|
||||
|
||||
/* forward declarations */
|
||||
struct xbus_workqueue;
|
||||
@@ -108,6 +109,7 @@ struct xbus_transport {
|
||||
atomic_t transport_refcount;
|
||||
wait_queue_head_t transport_unused;
|
||||
spinlock_t lock;
|
||||
char model_string[MAX_ENV_STR];
|
||||
};
|
||||
|
||||
#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
|
||||
@@ -188,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];
|
||||
@@ -340,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);
|
||||
|
||||
@@ -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();
|
||||
@@ -776,7 +726,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;
|
||||
}
|
||||
|
||||
@@ -915,6 +864,7 @@ static void echocan_free(struct dahdi_chan *chan,
|
||||
LINE_DBG(GENERAL, xpd, pos, "mode=0x%X\n", ec->status.mode);
|
||||
CALL_EC_METHOD(ec_set, xbus, xpd, pos, 0);
|
||||
CALL_EC_METHOD(ec_update, xbus, xbus);
|
||||
put_xpd(__FUNCTION__, xpd); /* aquired in xpp_echocan_create() */
|
||||
}
|
||||
|
||||
static const struct dahdi_echocan_features xpp_ec_features = {
|
||||
@@ -937,7 +887,7 @@ const char *xpp_echocan_name(const struct dahdi_chan *chan)
|
||||
xpd = chan->pvt;
|
||||
xbus = xpd->xbus;
|
||||
pos = chan->chanpos - 1;
|
||||
LINE_DBG(GENERAL, xpd, pos, "%s:\n", __func__);
|
||||
LINE_DBG(GENERAL, xpd, pos, "\n");
|
||||
if (!ECHOOPS(xbus))
|
||||
return NULL;
|
||||
/*
|
||||
@@ -986,6 +936,7 @@ int xpp_echocan_create(struct dahdi_chan *chan,
|
||||
*ec = phonedev->ec[pos];
|
||||
(*ec)->ops = &xpp_ec_ops;
|
||||
(*ec)->features = xpp_ec_features;
|
||||
xpd = get_xpd(__FUNCTION__, xpd); /* Returned in echocan_free() */
|
||||
LINE_DBG(GENERAL, xpd, pos, "(tap=%d, param_count=%d)\n",
|
||||
ecp->tap_length, ecp->param_count);
|
||||
ret = CALL_EC_METHOD(ec_set, xbus, xpd, pos, 1);
|
||||
@@ -994,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,
|
||||
@@ -1050,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 = {
|
||||
@@ -1061,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);
|
||||
|
||||
@@ -1078,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);
|
||||
@@ -1161,6 +1074,48 @@ 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)
|
||||
{
|
||||
unsigned long flags;
|
||||
if (!xpd)
|
||||
return;
|
||||
XPD_DBG(DEVICES, xpd, "\n");
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
xpd->card_present = 0;
|
||||
xpd_setstate(xpd, XPD_STATE_NOHW);
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
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)
|
||||
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)
|
||||
@@ -1181,11 +1136,6 @@ static int __init xpp_dahdi_init(void)
|
||||
|
||||
INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION,
|
||||
MAX_XPDS, MAX_UNIT, MAX_SUBUNIT);
|
||||
#ifdef CONFIG_DAHDI_BRI_DCHANS
|
||||
INFO("FEATURE: with BRISTUFF support\n");
|
||||
#else
|
||||
INFO("FEATURE: without BRISTUFF support\n");
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
|
||||
if(!xpp_proc_toplevel) {
|
||||
@@ -1220,12 +1170,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);
|
||||
@@ -46,6 +47,7 @@ int xpp_close(struct dahdi_chan *chan);
|
||||
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);
|
||||
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'"
|
||||
|
||||
@@ -737,6 +737,12 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
|
||||
retval = -ENOMEM;
|
||||
goto probe_failed;
|
||||
}
|
||||
snprintf(xbus->transport.model_string,
|
||||
ARRAY_SIZE(xbus->transport.model_string),
|
||||
"usb:%04x/%04x/%x",
|
||||
udev->descriptor.idVendor,
|
||||
udev->descriptor.idProduct,
|
||||
udev->descriptor.bcdDevice);
|
||||
spin_lock_irqsave(&xusb_lock, flags);
|
||||
for(i = 0; i < MAX_BUSES; i++) {
|
||||
if(xusb_array[i] == NULL)
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
#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>
|
||||
|
||||
#ifdef CONFIG_DAHDI_NET
|
||||
@@ -54,6 +55,8 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/interrupt.h>
|
||||
#endif
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include <linux/poll.h>
|
||||
|
||||
@@ -885,6 +888,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 {
|
||||
@@ -892,14 +927,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
|
||||
@@ -913,7 +944,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 */
|
||||
@@ -933,7 +963,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 {
|
||||
@@ -950,6 +984,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);
|
||||
@@ -1031,6 +1067,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;
|
||||
@@ -1038,6 +1075,7 @@ struct dahdi_dynamic {
|
||||
int timing;
|
||||
int master;
|
||||
unsigned char *msgbuf;
|
||||
struct device *dev;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
@@ -1101,6 +1139,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);
|
||||
|
||||
@@ -1115,10 +1169,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);
|
||||
@@ -1133,9 +1189,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);
|
||||
|
||||
@@ -1364,6 +1417,24 @@ static inline void list_replace(struct list_head *old, struct list_head *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, 17)
|
||||
#ifndef POLLRDHUP
|
||||
#define POLLRDHUP 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)
|
||||
@@ -1390,12 +1461,17 @@ typedef u32 __bitwise pm_message_t;
|
||||
#endif /* 2.6.11 */
|
||||
#endif /* 2.6.12 */
|
||||
#endif /* 2.6.14 */
|
||||
#endif /* 2.6.17 */
|
||||
#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
|
||||
@@ -1461,6 +1537,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.
|
||||
*/
|
||||
@@ -1472,6 +1568,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, \
|
||||
@@ -1484,6 +1581,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