Compare commits
69 Commits
switched_t
...
branched-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66edd67565 | ||
|
|
897cbb01de | ||
|
|
f9e4bf52c2 | ||
|
|
44a5add969 | ||
|
|
d18ec7f3b9 | ||
|
|
f69326bb66 | ||
|
|
c95385bb06 | ||
|
|
76468854ed | ||
|
|
2242c5394b | ||
|
|
62c5402a24 | ||
|
|
b222cfeb5d | ||
|
|
bd373e5075 | ||
|
|
49d2e93245 | ||
|
|
c573e5eaf5 | ||
|
|
7559b61e54 | ||
|
|
f4cffb0c1a | ||
|
|
42c0efb700 | ||
|
|
4afe8d0213 | ||
|
|
ae9d3a0bdc | ||
|
|
d635b1ef61 | ||
|
|
6527164a02 | ||
|
|
2f55744b15 | ||
|
|
5ddb6535f7 | ||
|
|
172ddb07b9 | ||
|
|
94a00c0f00 | ||
|
|
47fbd9bcc3 | ||
|
|
1a9b8662ad | ||
|
|
c3f65d39fa | ||
|
|
c36b6cd738 | ||
|
|
14f64038b0 | ||
|
|
a135f4e817 | ||
|
|
1e8c9fb797 | ||
|
|
0893461985 | ||
|
|
8edbfa881e | ||
|
|
43412bc513 | ||
|
|
1cf2b86e75 | ||
|
|
380ceed257 | ||
|
|
3408c774ce | ||
|
|
2de79e8905 | ||
|
|
99f1c099ec | ||
|
|
136ab72d6c | ||
|
|
e667e47418 | ||
|
|
90c209f77b | ||
|
|
2ecf474a07 | ||
|
|
2fefa9dd60 | ||
|
|
d624adb358 | ||
|
|
40942e2a43 | ||
|
|
78c92b52ed | ||
|
|
1bf7ebc42f | ||
|
|
7a275dc70b | ||
|
|
9fb13e2f6c | ||
|
|
fcbde772c4 | ||
|
|
2bc2ebd1de | ||
|
|
0f8559b045 | ||
|
|
d6075a4c78 | ||
|
|
c6e5ab448c | ||
|
|
8ff6810740 | ||
|
|
f3262ae381 | ||
|
|
c3c891abdd | ||
|
|
2fb5d7d6d7 | ||
|
|
08ce93306d | ||
|
|
dac1d88399 | ||
|
|
5218e90962 | ||
|
|
da2406db64 | ||
|
|
0b52fb24a0 | ||
|
|
2f880acd10 | ||
|
|
950a3f2486 | ||
|
|
2405c809e7 | ||
|
|
eb1c6cbeed |
212
README
212
README
@@ -17,7 +17,6 @@ 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
|
||||
@@ -163,24 +162,6 @@ to the script:
|
||||
./build_tools/make_static_devs -d tmp/newroot/dev/dahdi
|
||||
|
||||
|
||||
DKMS
|
||||
~~~~
|
||||
DKMS, Dynamic Kernel Module Support, is a framework for building Linux
|
||||
kernel modules. It is used, among others, by several distributions that
|
||||
package the DAHDI kernel modules.
|
||||
|
||||
DKMS is designed to provide updates over drivers installed from original
|
||||
kernel modules tree. Thus it installed modules into /lib/modules/updates
|
||||
or /lib/modules/VERSION/updates . This is generally not an issue on
|
||||
normal operation. However if you try to install DAHDI from source on
|
||||
a system with DAHDI installed from DKMS this way (potentially of an
|
||||
older version), be sure to remove the DKMS-installed modules from the
|
||||
updates directory. If you're not sure, the following command will give
|
||||
you a clue of the versions installed:
|
||||
|
||||
find /lib/modules -name dahdi.ko
|
||||
|
||||
|
||||
Installing the B410P drivers with mISDN
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
DAHDI includes the wcb4xxp driver for the B410P, however, support for the
|
||||
@@ -248,15 +229,6 @@ be reported on the
|
||||
https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing
|
||||
list].
|
||||
|
||||
Alternatively you can also get the OSLEC code from the dahdi-linux-extra
|
||||
GIT repository:
|
||||
|
||||
git clone git://gitorious.org/dahdi-extra/dahdi-linux-extra.git
|
||||
cd dahdi-linux-extra
|
||||
git archive extra-2.6 drivers/staging | (cd ..; tar xf -)
|
||||
cd ..; rm -rf dahdi-linux-extra
|
||||
|
||||
|
||||
Live Install
|
||||
~~~~~~~~~~~~
|
||||
In many cases you already have DAHDI installed on your system but would
|
||||
@@ -494,9 +466,6 @@ max_pseudo_channels (dahdi)::
|
||||
create. Pseudo channels are used when conferencing channels together.
|
||||
The default is 512.
|
||||
|
||||
auto_assign_spans (dahdi)::
|
||||
See <<_span_assignments,Span Assignments>> below.
|
||||
|
||||
To get a list of parameters supported by a module, use
|
||||
|
||||
modinfo module_name
|
||||
@@ -566,7 +535,6 @@ timing device it will hang forever in the first cycle. Otherwise it will just
|
||||
give you in each cycle the percent of how close it was. Also try running it
|
||||
with the option -v for a verbose output.
|
||||
|
||||
|
||||
Spans and Channels
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
DAHDI provides telephony *channels* to the userspace applications.
|
||||
@@ -586,81 +554,6 @@ There are up to 128 spans and 1024 channels. This is a hard-wired limit
|
||||
number fits in a 16 bits number). Channel and span numbers start at 1.
|
||||
|
||||
|
||||
Span Assignments
|
||||
~~~~~~~~~~~~~~~~
|
||||
A DAHDI device (e.g. a PCI card) is represented within the DAHDI drivers
|
||||
as a 'DAHDI device'. Normally (with auto_assign_spans=1 in the module
|
||||
dahdi, which is the default), when a device is discovered and loaded,
|
||||
it registers with the DAHDI core and its spans automatically become
|
||||
available. However if you have more than one device, you may be
|
||||
interested to set explicit spans and channels numbers for them. To use
|
||||
manual span assigment, set 'auto_assign_spans' to 0 . e.g. in a file
|
||||
under /etc/modprobe.d/ include the following line:
|
||||
|
||||
options dahdi auto_assign_spans=0
|
||||
|
||||
You will then need to assign the spans manually at device startup. You
|
||||
will need to assign a span number and channel numbers for each
|
||||
available span on the system. On my test system I have one BRI PCI card
|
||||
and one Astribank BRI+FXS:
|
||||
|
||||
# grep . /sys/bus/dahdi_devices/devices/*/spantype
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:1:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:2:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:3:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:4:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:5:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:6:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:7:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:8:BRI
|
||||
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:9:FXS
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:1:TE
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:2:TE
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:3:NT
|
||||
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:4:NT
|
||||
|
||||
All spans here, except the FXS one, are BRI spans with 3 channels per span.
|
||||
|
||||
In order to assign a span, we write three numbers separated by colns to
|
||||
the file 'assign_span' in the SysFS node
|
||||
|
||||
local_num:span_num:base_chan_num
|
||||
|
||||
Thus:
|
||||
|
||||
echo 9:5:10 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
echo 2:8:40 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
|
||||
echo 1:1:1 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
echo 4:6:20 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
|
||||
echo 3:2:5 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
|
||||
|
||||
As you can see, the order of span numbers or local span number is
|
||||
insignificant. However the order of channel numbers must be the same as
|
||||
that of span numbers.
|
||||
|
||||
Which indeed produced:
|
||||
|
||||
# head -n3 -q /proc/dahdi/*
|
||||
Span 1: XBUS-00/XPD-00 "Xorcom XPD [usb:LAB-0003].1: BRI_NT"
|
||||
|
||||
1 XPP_BRI_NT/00/00/0
|
||||
Span 2: XBUS-00/XPD-02 "Xorcom XPD [usb:LAB-0003].3: BRI_TE"
|
||||
|
||||
5 XPP_BRI_TE/00/02/0
|
||||
Span 5: XBUS-00/XPD-10 "Xorcom XPD [usb:LAB-0003].9: FXS" (MASTER)
|
||||
|
||||
10 XPP_FXS/00/10/0
|
||||
Span 6: B4/0/4 "B4XXP (PCI) Card 0 Span 4" RED
|
||||
|
||||
23 B4/0/4/1 YELLOW
|
||||
Span 8: B4/0/2 "B4XXP (PCI) Card 0 Span 2" RED
|
||||
|
||||
40 B4/0/2/1 RED
|
||||
|
||||
Likewise spans can be unassigned by writing to the 'unassign-span'
|
||||
"file".
|
||||
|
||||
|
||||
Dynamic Spans
|
||||
~~~~~~~~~~~~~
|
||||
Dynamic spans are spans that are not represented by real hardware.
|
||||
@@ -748,109 +641,6 @@ see an extra '(In use)':
|
||||
2 XPP_FXS/0/0/1 FXOLS (In use)
|
||||
|
||||
|
||||
SysFS Interface
|
||||
~~~~~~~~~~~~~~~
|
||||
DAHDI exposes several interfaces under the SysFS virtual file system.
|
||||
SysFS represents kernel objects in nodes - directories. There properties
|
||||
are often files. They may also contain other nodes or include symlinks
|
||||
to other nodes.
|
||||
|
||||
Class DAHDI
|
||||
^^^^^^^^^^^
|
||||
under /sys/class/dadhi there exists a node for 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/lineconfig
|
||||
The framing and coding of the span, for a digital span. Textual
|
||||
represenation:
|
||||
|
||||
<B8ZS|AMI|HDB3>/<D4|ESF|CCS>[/CRC4]
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/local_spanno
|
||||
The number of the span within the DAHDI device.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/name
|
||||
A concise name for this span.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/spantype
|
||||
A very short type string.
|
||||
|
||||
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
|
||||
Current sync source.
|
||||
|
||||
|
||||
User-space Interface
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
User-space programs can only work with DAHDI channels. The basic
|
||||
@@ -928,7 +718,7 @@ standard HDLC rate of 64k).
|
||||
Low-Level Drivers
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Low-level drivers create spans ('struct dahdi_span'). They register the
|
||||
spans with the DAHDI core using 'dahdi_device_register()'.
|
||||
spans with the DAHDI core using 'dahdi_register()'.
|
||||
|
||||
'struct dahdi_span' has a number of informative members that are updated
|
||||
solely by the low-level driver:
|
||||
|
||||
@@ -293,10 +293,6 @@ load)
|
||||
# TODO: A local copy of Asterisk, configured with dahdi_gnconf.
|
||||
# doable, but trickier.
|
||||
run_asterisk
|
||||
if [ "$LIVE_DAHDI_FREEPBXDB" = 'yes' ]; then
|
||||
GENCONF_PARAMETERS=$DESTDIR/etc/dahdi/genconf_parameters \
|
||||
dahdi_genconf freepbxdb
|
||||
fi
|
||||
;;
|
||||
genconf)
|
||||
genconf
|
||||
|
||||
@@ -77,7 +77,7 @@ CFLAGS_dahdi_dynamic_ethmf.o := -DNEW_SKB_LINEARIZE
|
||||
endif
|
||||
endif
|
||||
|
||||
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-sysfs-chan.o dahdi-version.o
|
||||
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-version.o
|
||||
|
||||
###############################################################################
|
||||
# Find appropriate ARCH value for VPMADT032 and HPEC binary modules
|
||||
|
||||
6
drivers/dahdi/Makefile
Normal file
6
drivers/dahdi/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,215 +0,0 @@
|
||||
/* dahdi-sysfs-chan.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, Xorcom
|
||||
* Copyright (C) 2011-2012, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#define DAHDI_PRINK_MACROS_USE_debug
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <dahdi/kernel.h>
|
||||
#include "dahdi.h"
|
||||
#include "dahdi-sysfs.h"
|
||||
|
||||
/* shortcuts, for code readability */
|
||||
#define MAKE_DAHDI_DEV(num, name) \
|
||||
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
|
||||
#define DEL_DAHDI_DEV(num) \
|
||||
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
|
||||
|
||||
static struct class *dahdi_class;
|
||||
|
||||
int chan_sysfs_create(struct dahdi_chan *chan)
|
||||
{
|
||||
char chan_name[32];
|
||||
void *dummy;
|
||||
int res = 0;
|
||||
|
||||
if (chan->channo >= 250)
|
||||
return 0;
|
||||
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
return 0;
|
||||
snprintf(chan_name, sizeof(chan_name), "dahdi!%d", chan->channo);
|
||||
dummy = (void *)MAKE_DAHDI_DEV(chan->channo, chan_name);
|
||||
if (IS_ERR(dummy)) {
|
||||
res = PTR_ERR(dummy);
|
||||
chan_err(chan, "Failed creating sysfs device: %d\n",
|
||||
res);
|
||||
return res;
|
||||
}
|
||||
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void chan_sysfs_remove(struct dahdi_chan *chan)
|
||||
{
|
||||
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
return;
|
||||
DEL_DAHDI_DEV(chan->channo);
|
||||
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by dahdi_transcode.c
|
||||
*/
|
||||
int dahdi_register_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
static const char *DAHDI_STRING = "dahdi!";
|
||||
char *udevname;
|
||||
|
||||
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
|
||||
GFP_KERNEL);
|
||||
if (!udevname)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(udevname, DAHDI_STRING);
|
||||
strcat(udevname, dev->name);
|
||||
MAKE_DAHDI_DEV(dev->minor, udevname);
|
||||
kfree(udevname);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_register_chardev);
|
||||
|
||||
/*
|
||||
* Used by dahdi_transcode.c
|
||||
*/
|
||||
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
DEL_DAHDI_DEV(dev->minor);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_unregister_chardev);
|
||||
|
||||
/*--------- Sysfs Device handling ----*/
|
||||
|
||||
/*
|
||||
* Describe fixed device files and maintain their
|
||||
* pointer so fixed_devfiles_remove() can always be called
|
||||
* and work cleanly
|
||||
*/
|
||||
static struct {
|
||||
int minor;
|
||||
char *name;
|
||||
void *dev; /* FIXME: wrong type because of old kernels */
|
||||
} fixed_minors[] = {
|
||||
{ DAHDI_CTL, "dahdi!ctl", },
|
||||
{ DAHDI_TIMER, "dahdi!timer", },
|
||||
{ DAHDI_CHANNEL, "dahdi!channel",},
|
||||
{ DAHDI_PSEUDO, "dahdi!pseudo", },
|
||||
};
|
||||
|
||||
/*
|
||||
* Removes /dev/dahdi/{ctl,timer,channel,pseudo}
|
||||
*
|
||||
* It is safe to call it during initialization error handling,
|
||||
* as it skips non existing objects.
|
||||
*/
|
||||
static void fixed_devfiles_remove(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dahdi_class)
|
||||
return;
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
|
||||
void *d = fixed_minors[i].dev;
|
||||
if (d && !IS_ERR(d))
|
||||
dahdi_dbg(DEVICES, "Removing fixed device file %s\n",
|
||||
fixed_minors[i].name);
|
||||
DEL_DAHDI_DEV(fixed_minors[i].minor);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates /dev/dahdi/{ctl,timer,channel,pseudo}
|
||||
*/
|
||||
static int fixed_devfiles_create(void)
|
||||
{
|
||||
int i;
|
||||
int res = 0;
|
||||
|
||||
if (!dahdi_class) {
|
||||
dahdi_err("%s: dahdi_class is not initialized yet!\n",
|
||||
__func__);
|
||||
res = -ENODEV;
|
||||
goto cleanup;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
|
||||
char *name = fixed_minors[i].name;
|
||||
int minor = fixed_minors[i].minor;
|
||||
void *dummy;
|
||||
|
||||
dahdi_dbg(DEVICES, "Making fixed device file %s\n", name);
|
||||
dummy = (void *)MAKE_DAHDI_DEV(minor, name);
|
||||
if (IS_ERR(dummy)) {
|
||||
int res = PTR_ERR(dummy);
|
||||
|
||||
dahdi_err("%s: failed (%d: %s). Error: %d\n",
|
||||
__func__, minor, name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
fixed_minors[i].dev = dummy;
|
||||
}
|
||||
return 0;
|
||||
cleanup:
|
||||
fixed_devfiles_remove();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during driver unload and while handling any error during
|
||||
* driver load.
|
||||
* Always clean any (and only) objects that were initialized (invariant)
|
||||
*/
|
||||
static void sysfs_channels_cleanup(void)
|
||||
{
|
||||
fixed_devfiles_remove();
|
||||
if (dahdi_class) {
|
||||
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
|
||||
class_destroy(dahdi_class);
|
||||
dahdi_class = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int __init dahdi_sysfs_chan_init(const struct file_operations *fops)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
dahdi_class = class_create(THIS_MODULE, "dahdi");
|
||||
if (IS_ERR(dahdi_class)) {
|
||||
res = PTR_ERR(dahdi_class);
|
||||
dahdi_err("%s: class_create(dahi_chan) failed. Error: %d\n",
|
||||
__func__, res);
|
||||
goto cleanup;
|
||||
}
|
||||
res = fixed_devfiles_create();
|
||||
if (res)
|
||||
goto cleanup;
|
||||
return 0;
|
||||
cleanup:
|
||||
sysfs_channels_cleanup();
|
||||
return res;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_chan_exit(void)
|
||||
{
|
||||
sysfs_channels_cleanup();
|
||||
}
|
||||
@@ -1,346 +1,123 @@
|
||||
/* dahdi-sysfs.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, Xorcom
|
||||
* Copyright (C) 2011-2012, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2 as published by the
|
||||
* Free Software Foundation. See the LICENSE file included with
|
||||
* this program for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#define DAHDI_PRINK_MACROS_USE_debug
|
||||
#include <dahdi/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#include "dahdi.h"
|
||||
#include "dahdi-sysfs.h"
|
||||
|
||||
/* FIXME: Move to kernel.h */
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#define SPAN_VAR_BLOCK \
|
||||
do { \
|
||||
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
|
||||
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
|
||||
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
|
||||
} while (0)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(envp, num_envp, &i, \
|
||||
buffer, buffer_size, &len, \
|
||||
fmt, val); \
|
||||
if (err) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int span_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int i = 0;
|
||||
int len = 0;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
if (!span)
|
||||
return -ENODEV;
|
||||
|
||||
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
|
||||
dev_name(dev), span->name);
|
||||
SPAN_VAR_BLOCK;
|
||||
envp[i] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, NULL, "%s", name)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, name)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
class_device_create(class, NULL, devt, device, name)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
class_device_create(class, devt, device, name)
|
||||
#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;
|
||||
}
|
||||
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
class_simple_device_add(class, devt, device, name)
|
||||
#endif
|
||||
|
||||
#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); \
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
device_destroy(class, devt)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
class_device_destroy(class, devt)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
class_simple_device_remove(devt)
|
||||
#else
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
class_simple_device_remove(class, devt)
|
||||
#endif
|
||||
|
||||
span_attr(name, "%s\n");
|
||||
span_attr(desc, "%s\n");
|
||||
span_attr(alarms, "0x%x\n");
|
||||
span_attr(lbo, "%d\n");
|
||||
span_attr(syncsrc, "%d\n");
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
|
||||
static struct class *dahdi_class = NULL;
|
||||
#else
|
||||
static struct class_simple *dahdi_class = NULL;
|
||||
#define class_create class_simple_create
|
||||
#define class_destroy class_simple_destroy
|
||||
#endif
|
||||
|
||||
static BUS_ATTR_READER(spantype_show, dev, buf)
|
||||
|
||||
int dahdi_register_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
static const char *DAHDI_STRING = "dahdi!";
|
||||
char *udevname;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
return sprintf(buf, "%s\n", dahdi_spantype2str(span->spantype));
|
||||
}
|
||||
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
|
||||
GFP_KERNEL);
|
||||
if (!udevname)
|
||||
return -ENOMEM;
|
||||
|
||||
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);
|
||||
if (!span->channels)
|
||||
return -ENODEV;
|
||||
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 BUS_ATTR_READER(lineconfig_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int len = 0;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
len += lineconfig_str(span->lineconfig, buf, 20);
|
||||
len += sprintf(buf + len, "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static BUS_ATTR_READER(linecompat_show, dev, buf)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
int bit;
|
||||
int len = 0;
|
||||
|
||||
span = dev_to_span(dev);
|
||||
for (bit = 4; bit <= 12; bit++) {
|
||||
if (span->linecompat & (1 << bit)) {
|
||||
const char *name = dahdi_lineconfig_bit_name(bit);
|
||||
if (name)
|
||||
len += sprintf(buf + len, "%s ", name);
|
||||
}
|
||||
}
|
||||
/* chomp */
|
||||
while (len > 0 && isspace(buf[len - 1]))
|
||||
buf[--len] = '\0';
|
||||
len += sprintf(buf + len, "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
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_RO(lineconfig),
|
||||
__ATTR_RO(linecompat),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct driver_attribute dahdi_attrs[] = {
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct bus_type spans_bus_type = {
|
||||
.name = "dahdi_spans",
|
||||
.match = span_match,
|
||||
.uevent = span_uevent,
|
||||
.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");
|
||||
strcpy(udevname, DAHDI_STRING);
|
||||
strcat(udevname, dev->name);
|
||||
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor), NULL, udevname);
|
||||
kfree(udevname);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_register_chardev);
|
||||
|
||||
static int span_remove(struct device *dev)
|
||||
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor));
|
||||
|
||||
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,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
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);
|
||||
kobject_uevent(kobj, act);
|
||||
}
|
||||
|
||||
static void span_release(struct device *dev)
|
||||
{
|
||||
dahdi_dbg(DEVICES, "%s: %s\n", __func__, dev_name(dev));
|
||||
}
|
||||
EXPORT_SYMBOL(dahdi_unregister_chardev);
|
||||
|
||||
void span_sysfs_remove(struct dahdi_span *span)
|
||||
{
|
||||
struct device *span_device;
|
||||
int x;
|
||||
for (x = 0; x < span->channels; x++) {
|
||||
struct dahdi_chan *chan = span->chans[x];
|
||||
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
continue;
|
||||
|
||||
span_dbg(DEVICES, span, "\n");
|
||||
span_device = span->span_device;
|
||||
|
||||
if (!span_device)
|
||||
return;
|
||||
|
||||
for (x = 0; x < span->channels; x++)
|
||||
chan_sysfs_remove(span->chans[x]);
|
||||
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;
|
||||
CLASS_DEV_DESTROY(dahdi_class,
|
||||
MKDEV(DAHDI_MAJOR, chan->channo));
|
||||
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
}
|
||||
}
|
||||
|
||||
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++) {
|
||||
res = chan_sysfs_create(span->chans[x]);
|
||||
if (res)
|
||||
struct dahdi_chan *chan = span->chans[x];
|
||||
char chan_name[32];
|
||||
void *dummy;
|
||||
|
||||
if (chan->channo >= 250)
|
||||
continue;
|
||||
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
|
||||
continue;
|
||||
|
||||
snprintf(chan_name, sizeof(chan_name), "dahdi!%d",
|
||||
chan->channo);
|
||||
dummy = (void *)CLASS_DEV_CREATE(dahdi_class,
|
||||
MKDEV(DAHDI_MAJOR, chan->channo),
|
||||
NULL, chan_name);
|
||||
if (IS_ERR(dummy)) {
|
||||
res = PTR_ERR(dummy);
|
||||
chan_err(chan, "Failed creating sysfs device: %d\n",
|
||||
res);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -349,342 +126,105 @@ cleanup:
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MAKE_DAHDI_DEV(num, name) \
|
||||
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
|
||||
#define DEL_DAHDI_DEV(num) \
|
||||
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
|
||||
|
||||
/* Only used to flag that the device exists: */
|
||||
static struct {
|
||||
unsigned int clean_dahdi_driver:1;
|
||||
unsigned int clean_span_bus_type:1;
|
||||
unsigned int clean_device_bus:1;
|
||||
unsigned int clean_chardev:1;
|
||||
} should_cleanup;
|
||||
unsigned int ctl:1;
|
||||
unsigned int timer:1;
|
||||
unsigned int channel:1;
|
||||
unsigned int pseudo:1;
|
||||
} dummy_dev;
|
||||
|
||||
static inline struct dahdi_device *to_ddev(struct device *dev)
|
||||
void dahdi_sysfs_exit(void)
|
||||
{
|
||||
return container_of(dev, struct dahdi_device, dev);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_manufacturer_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
return sprintf(buf, "%s\n", ddev->manufacturer);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
return sprintf(buf, "%s\n", ddev->devicetype);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_span_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_hardware_id_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
(ddev->hardware_id) ? ddev->hardware_id : "");
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct dahdi_device *ddev = to_ddev(dev);
|
||||
dahdi_assign_device_spans(ddev);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
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, "bad input (should be <num>:<num>:<num>)\n");
|
||||
return -EINVAL;
|
||||
if (dummy_dev.pseudo) {
|
||||
dahdi_dbg(DEVICES, "Removing /dev/dahdi/pseudo:\n");
|
||||
DEL_DAHDI_DEV(DAHDI_PSEUDO);
|
||||
dummy_dev.pseudo = 0;
|
||||
}
|
||||
|
||||
if (desired_spanno && !desired_basechanno) {
|
||||
dev_notice(dev, "Must set span number AND base chan number\n");
|
||||
return -EINVAL;
|
||||
if (dummy_dev.channel) {
|
||||
dahdi_dbg(DEVICES, "Removing /dev/dahdi/channel:\n");
|
||||
DEL_DAHDI_DEV(DAHDI_CHANNEL);
|
||||
dummy_dev.channel = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (dummy_dev.timer) {
|
||||
dahdi_dbg(DEVICES, "Removing /dev/dahdi/timer:\n");
|
||||
DEL_DAHDI_DEV(DAHDI_TIMER);
|
||||
dummy_dev.timer = 0;
|
||||
}
|
||||
dev_notice(dev, "no match for local span number %d\n",
|
||||
local_span_number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
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 (dummy_dev.ctl) {
|
||||
dahdi_dbg(DEVICES, "Removing /dev/dahdi/ctl:\n");
|
||||
DEL_DAHDI_DEV(DAHDI_CTL);
|
||||
dummy_dev.ctl = 0;
|
||||
}
|
||||
if (-ENODEV == ret) {
|
||||
if (printk_ratelimit()) {
|
||||
dev_info(dev, "'%d' is an invalid local span number.\n",
|
||||
local_span_number);
|
||||
}
|
||||
return -EINVAL;
|
||||
if (dahdi_class) {
|
||||
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
|
||||
class_destroy(dahdi_class);
|
||||
dahdi_class = NULL;
|
||||
}
|
||||
return (ret < 0) ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_spantype_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
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), dahdi_spantype2str(span->spantype));
|
||||
buf += count;
|
||||
total += count;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct dahdi_device *const ddev = to_ddev(dev);
|
||||
int ret;
|
||||
struct dahdi_span *span;
|
||||
unsigned int local_span_number;
|
||||
char spantype_name[80];
|
||||
enum spantypes spantype;
|
||||
|
||||
ret = sscanf(buf, "%u:%70s", &local_span_number, spantype_name);
|
||||
if (ret != 2) {
|
||||
dev_err(&ddev->dev, "Wrong input format: '%s'\n", buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
spantype = dahdi_str2spantype(spantype_name);
|
||||
if (spantype == SPANTYPE_INVALID) {
|
||||
dev_err(&ddev->dev, "Invalid spantype: '%s'\n", buf);
|
||||
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, spantype);
|
||||
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,
|
||||
};
|
||||
|
||||
static void dahdi_sysfs_cleanup(void)
|
||||
{
|
||||
dahdi_dbg(DEVICES, "SYSFS\n");
|
||||
if (should_cleanup.clean_dahdi_driver) {
|
||||
dahdi_dbg(DEVICES, "Unregister driver\n");
|
||||
driver_unregister(&dahdi_driver);
|
||||
should_cleanup.clean_dahdi_driver = 0;
|
||||
}
|
||||
if (should_cleanup.clean_span_bus_type) {
|
||||
dahdi_dbg(DEVICES, "Unregister span bus type\n");
|
||||
bus_unregister(&spans_bus_type);
|
||||
should_cleanup.clean_span_bus_type = 0;
|
||||
}
|
||||
dahdi_sysfs_chan_exit();
|
||||
if (should_cleanup.clean_chardev) {
|
||||
dahdi_dbg(DEVICES, "Unregister character device\n");
|
||||
unregister_chrdev(DAHDI_MAJOR, "dahdi");
|
||||
should_cleanup.clean_chardev = 0;
|
||||
}
|
||||
|
||||
if (should_cleanup.clean_device_bus) {
|
||||
dahdi_dbg(DEVICES, "Unregister DAHDI device bus\n");
|
||||
bus_unregister(&dahdi_device_bus);
|
||||
should_cleanup.clean_device_bus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dahdi_device_release(struct device *dev)
|
||||
{
|
||||
struct dahdi_device *ddev = container_of(dev, struct dahdi_device, dev);
|
||||
kfree(ddev);
|
||||
}
|
||||
|
||||
/**
|
||||
* dahdi_sysfs_add_device - Add the dahdi_device into the sysfs hierarchy.
|
||||
* @ddev: The device to add.
|
||||
* @parent: The physical device that is implementing this device.
|
||||
*
|
||||
* By adding the dahdi_device to the sysfs hierarchy user space can control
|
||||
* how spans are numbered.
|
||||
*
|
||||
*/
|
||||
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent)
|
||||
{
|
||||
int ret;
|
||||
struct device *const dev = &ddev->dev;
|
||||
const char *dn;
|
||||
|
||||
dev->parent = parent;
|
||||
dev->bus = &dahdi_device_bus;
|
||||
dn = dev_name(dev);
|
||||
if (!dn || !*dn) {
|
||||
/* Invent default name based on parent */
|
||||
if (!parent)
|
||||
return -EINVAL;
|
||||
dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent));
|
||||
}
|
||||
ret = device_add(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_init_device(struct dahdi_device *ddev)
|
||||
{
|
||||
device_initialize(&ddev->dev);
|
||||
ddev->dev.release = dahdi_device_release;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev)
|
||||
{
|
||||
device_del(&ddev->dev);
|
||||
unregister_chrdev(DAHDI_MAJOR, "dahdi");
|
||||
}
|
||||
|
||||
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
|
||||
{
|
||||
int res = 0;
|
||||
void *dev;
|
||||
|
||||
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
|
||||
res = bus_register(&dahdi_device_bus);
|
||||
if (res)
|
||||
return res;
|
||||
should_cleanup.clean_device_bus = 1;
|
||||
|
||||
dahdi_dbg(DEVICES,
|
||||
"Registering character device (major=%d)\n", DAHDI_MAJOR);
|
||||
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);
|
||||
module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR);
|
||||
return res;
|
||||
}
|
||||
should_cleanup.clean_chardev = 1;
|
||||
|
||||
res = dahdi_sysfs_chan_init(dahdi_fops);
|
||||
if (res)
|
||||
goto cleanup;
|
||||
|
||||
res = bus_register(&spans_bus_type);
|
||||
if (res) {
|
||||
dahdi_err("%s: bus_register(%s) failed. Error number %d",
|
||||
__func__, spans_bus_type.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.clean_span_bus_type = 1;
|
||||
|
||||
res = driver_register(&dahdi_driver);
|
||||
if (res) {
|
||||
dahdi_err("%s: driver_register(%s) failed. Error number %d",
|
||||
__func__, dahdi_driver.name, res);
|
||||
goto cleanup;
|
||||
}
|
||||
should_cleanup.clean_dahdi_driver = 1;
|
||||
|
||||
module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n",
|
||||
DAHDI_MAJOR);
|
||||
module_printk(KERN_INFO, "Version: %s\n", dahdi_version);
|
||||
|
||||
dahdi_class = class_create(THIS_MODULE, "dahdi");
|
||||
if (!dahdi_class) {
|
||||
res = -EEXIST;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dahdi_dbg(DEVICES, "Creating /dev/dahdi/timer:\n");
|
||||
dev = MAKE_DAHDI_DEV(DAHDI_TIMER, "dahdi!timer");
|
||||
if (IS_ERR(dev)) {
|
||||
res = PTR_ERR(dev);
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.timer = 1;
|
||||
|
||||
dahdi_dbg(DEVICES, "Creating /dev/dahdi/channel:\n");
|
||||
dev = MAKE_DAHDI_DEV(DAHDI_CHANNEL, "dahdi!channel");
|
||||
if (IS_ERR(dev)) {
|
||||
res = PTR_ERR(dev);
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.channel = 1;
|
||||
|
||||
dahdi_dbg(DEVICES, "Creating /dev/dahdi/pseudo:\n");
|
||||
dev = MAKE_DAHDI_DEV(DAHDI_PSEUDO, "dahdi!pseudo");
|
||||
if (IS_ERR(dev)) {
|
||||
res = PTR_ERR(dev);
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.pseudo = 1;
|
||||
|
||||
dahdi_dbg(DEVICES, "Creating /dev/dahdi/ctl:\n");
|
||||
dev = MAKE_DAHDI_DEV(DAHDI_CTL, "dahdi!ctl");
|
||||
if (IS_ERR(dev)) {
|
||||
res = PTR_ERR(dev);
|
||||
goto cleanup;
|
||||
}
|
||||
dummy_dev.ctl = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
dahdi_sysfs_cleanup();
|
||||
dahdi_sysfs_exit();
|
||||
return res;
|
||||
}
|
||||
|
||||
void dahdi_sysfs_exit(void)
|
||||
{
|
||||
dahdi_sysfs_cleanup();
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef DAHDI_SYSFS_H
|
||||
#define DAHDI_SYSFS_H
|
||||
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count)
|
||||
#define BUS_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf)
|
||||
#define BUS_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count)
|
||||
|
||||
#define DRIVER_ATTR_READER(name, drv, buf) \
|
||||
ssize_t name(struct device_driver *drv, char * buf)
|
||||
|
||||
/* Device file creation macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, NULL, "%s", name)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
device_create(class, device, devt, name)
|
||||
#else
|
||||
#define CLASS_DEV_CREATE(class, devt, device, name) \
|
||||
class_device_create(class, NULL, devt, device, name)
|
||||
#endif
|
||||
|
||||
/* Device file destruction macros */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
device_destroy(class, devt)
|
||||
#else
|
||||
#define CLASS_DEV_DESTROY(class, devt) \
|
||||
class_device_destroy(class, devt)
|
||||
#endif
|
||||
|
||||
/* Global */
|
||||
int __init dahdi_sysfs_chan_init(const struct file_operations *fops);
|
||||
void dahdi_sysfs_chan_exit(void);
|
||||
|
||||
/* Channel Handling */
|
||||
int chan_sysfs_create(struct dahdi_chan *chan);
|
||||
void chan_sysfs_remove(struct dahdi_chan *chan);
|
||||
|
||||
#endif /* DAHDI_SYSFS_H */
|
||||
@@ -6,7 +6,6 @@
|
||||
*
|
||||
* Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
|
||||
* Copyright (C) 2011, Xorcom
|
||||
* Copyright (C) 2011, Digium, Inc
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -35,28 +34,4 @@ void span_sysfs_remove(struct dahdi_span *span);
|
||||
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops);
|
||||
void dahdi_sysfs_exit(void);
|
||||
|
||||
void dahdi_sysfs_init_device(struct dahdi_device *ddev);
|
||||
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent);
|
||||
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev);
|
||||
|
||||
int dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
|
||||
unsigned int basechan, int prefmaster);
|
||||
int dahdi_unassign_span(struct dahdi_span *span);
|
||||
int dahdi_assign_device_spans(struct dahdi_device *ddev);
|
||||
|
||||
static inline int get_span(struct dahdi_span *span)
|
||||
{
|
||||
return try_module_get(span->ops->owner);
|
||||
}
|
||||
|
||||
static inline void put_span(struct dahdi_span *span)
|
||||
{
|
||||
module_put(span->ops->owner);
|
||||
}
|
||||
|
||||
static inline int local_spanno(struct dahdi_span *span)
|
||||
{
|
||||
return span->offset + 1;
|
||||
}
|
||||
|
||||
#endif /* _DAHDI_H */
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* Converted to use HighResTimers on i386 by Jeffery Palmer <jeff@triggerinc.com>
|
||||
*
|
||||
* Copyright (C) 2002, Hermes Softlab
|
||||
* Copyright (C) 2004-2012, Digium, Inc.
|
||||
* Copyright (C) 2004-2009, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -75,7 +75,6 @@ static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
|
||||
#endif
|
||||
|
||||
struct dahdi_dummy {
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan _chan;
|
||||
struct dahdi_chan *chan;
|
||||
@@ -206,44 +205,37 @@ static const struct dahdi_span_ops dummy_ops = {
|
||||
|
||||
static int dahdi_dummy_initialize(struct dahdi_dummy *ztd)
|
||||
{
|
||||
int res = 0;
|
||||
/* DAHDI stuff */
|
||||
ztd->ddev = dahdi_create_device();
|
||||
if (!ztd->ddev)
|
||||
return -ENOMEM;
|
||||
dev_set_name(&ztd->ddev->dev, "dahdi_dummy");
|
||||
ztd->chan = &ztd->_chan;
|
||||
sprintf(ztd->span.name, "DAHDI_DUMMY/1");
|
||||
snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1);
|
||||
sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0);
|
||||
ztd->ddev->devicetype = "DAHDI Dummy Timing";
|
||||
strlcpy(ztd->span.devicetype, "DAHDI Dummy Timing",
|
||||
sizeof(ztd->span.devicetype));
|
||||
ztd->chan->chanpos = 1;
|
||||
ztd->span.chans = &ztd->chan;
|
||||
ztd->span.channels = 0; /* no channels on our span */
|
||||
ztd->span.deflaw = DAHDI_LAW_MULAW;
|
||||
ztd->chan->pvt = ztd;
|
||||
ztd->span.ops = &dummy_ops;
|
||||
list_add_tail(&ztd->span.device_node, &ztd->ddev->spans);
|
||||
res = dahdi_register_device(ztd->ddev, NULL);
|
||||
return res;
|
||||
if (dahdi_register(&ztd->span, 0)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
int res;
|
||||
ztd = kzalloc(sizeof(*ztd), GFP_KERNEL);
|
||||
if (ztd == NULL) {
|
||||
printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = dahdi_dummy_initialize(ztd);
|
||||
if (res) {
|
||||
printk(KERN_ERR
|
||||
"dahdi_dummy: Unable to intialize DAHDI driver (%d)\n",
|
||||
res);
|
||||
if (dahdi_dummy_initialize(ztd)) {
|
||||
printk(KERN_ERR "dahdi_dummy: Unable to intialize DAHDI driver\n");
|
||||
kfree(ztd);
|
||||
return res;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#if defined(USE_HIGHRESTIMER)
|
||||
@@ -281,8 +273,7 @@ void cleanup_module(void)
|
||||
atomic_set(&shutdown, 1);
|
||||
del_timer_sync(&timer);
|
||||
#endif
|
||||
dahdi_unregister_device(ztd->ddev);
|
||||
dahdi_free_device(ztd->ddev);
|
||||
dahdi_unregister(&ztd->span);
|
||||
kfree(ztd);
|
||||
if (debug)
|
||||
printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Written by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* Copyright (C) 2001-2012, Digium, Inc.
|
||||
* Copyright (C) 2001-2010, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -385,18 +385,32 @@ static void dahdi_dynamic_release(struct kref *kref)
|
||||
|
||||
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
|
||||
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
__module_get(d->driver->owner);
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(d->msgbuf);
|
||||
|
||||
for (x = 0; x < d->span.channels; x++)
|
||||
kfree(d->chans[x]);
|
||||
|
||||
dahdi_free_device(d->ddev);
|
||||
kfree(d);
|
||||
}
|
||||
|
||||
static inline int dynamic_put(struct dahdi_dynamic *d)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
|
||||
kref_put(&d->kref, dahdi_dynamic_release);
|
||||
return 1;
|
||||
#else
|
||||
return kref_put(&d->kref, dahdi_dynamic_release);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void dynamic_get(struct dahdi_dynamic *d)
|
||||
@@ -455,25 +469,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy) {
|
||||
if (!try_module_get(d->driver->owner)) {
|
||||
/* The driver for this device is in the
|
||||
* process of unloading. Leave this dynamic on
|
||||
* the list so it's cleaned up when the driver
|
||||
* unregisters. */
|
||||
dynamic_put(d);
|
||||
return -ENXIO;
|
||||
}
|
||||
d->driver->destroy(d);
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
d->pvt = NULL;
|
||||
}
|
||||
|
||||
dahdi_unregister_device(d->ddev);
|
||||
dahdi_unregister(&d->span);
|
||||
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
@@ -582,8 +578,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
kref_init(&d->kref);
|
||||
d->ddev = dahdi_create_device();
|
||||
|
||||
for (x = 0; x < dds->numchans; x++) {
|
||||
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
||||
@@ -608,10 +604,9 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
strlcpy(d->dname, dds->driver, sizeof(d->dname));
|
||||
strlcpy(d->addr, dds->addr, sizeof(d->addr));
|
||||
d->timing = dds->timing;
|
||||
snprintf(d->span.name, sizeof(d->span.name), "DYN/%s/%s",
|
||||
dds->driver, dds->addr);
|
||||
snprintf(d->span.desc, sizeof(d->span.desc),
|
||||
"Dynamic '%s' span at '%s'", dds->driver, dds->addr);
|
||||
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
|
||||
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
|
||||
dds->driver, dds->addr);
|
||||
d->span.deflaw = DAHDI_LAW_MULAW;
|
||||
d->span.flags |= DAHDI_FLAG_RBS;
|
||||
d->span.chans = d->chans;
|
||||
@@ -662,12 +657,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
|
||||
return res;
|
||||
}
|
||||
|
||||
d->ddev->devicetype = d->span.name;
|
||||
d->ddev->hardware_id = d->span.name;
|
||||
dev_set_name(&d->ddev->dev, "dynamic:%s:%d", dds->driver, dtd->id++);
|
||||
list_add_tail(&d->span.device_node, &d->ddev->spans);
|
||||
/* Whee! We're created. Now register the span */
|
||||
if (dahdi_register_device(d->ddev, d->dev)) {
|
||||
if (dahdi_register(&d->span, 0)) {
|
||||
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
||||
d->span.name);
|
||||
dynamic_put(d);
|
||||
@@ -770,17 +761,19 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
|
||||
list_for_each_entry_safe(d, n, &dspan_list, list) {
|
||||
if (d->driver == dri) {
|
||||
if (d->pvt) {
|
||||
if (d->driver && d->driver->destroy)
|
||||
if (d->driver && d->driver->destroy) {
|
||||
__module_get(d->driver->owner);
|
||||
d->driver->destroy(d);
|
||||
else
|
||||
module_put(d->driver->owner);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
dahdi_unregister_device(d->ddev);
|
||||
dahdi_unregister(&d->span);
|
||||
spin_lock_irqsave(&dspan_lock, flags);
|
||||
list_del_rcu(&d->list);
|
||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||
synchronize_rcu();
|
||||
d->driver = NULL;
|
||||
dynamic_put(d);
|
||||
}
|
||||
}
|
||||
@@ -824,13 +817,10 @@ static void check_for_red_alarm(unsigned long ignored)
|
||||
mod_timer(&alarmcheck, jiffies + 1 * HZ);
|
||||
}
|
||||
|
||||
static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = dahdi_dynamic_ioctl,
|
||||
};
|
||||
|
||||
static int dahdi_dynamic_init(void)
|
||||
{
|
||||
dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl);
|
||||
|
||||
/* Start process to check for RED ALARM */
|
||||
init_timer(&alarmcheck);
|
||||
alarmcheck.expires = 0;
|
||||
@@ -841,25 +831,19 @@ static int dahdi_dynamic_init(void)
|
||||
#ifdef ENABLE_TASKLETS
|
||||
tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
|
||||
#endif
|
||||
dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
|
||||
|
||||
printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dahdi_dynamic_cleanup(void)
|
||||
{
|
||||
dahdi_set_dynamic_ops(NULL);
|
||||
|
||||
#ifdef ENABLE_TASKLETS
|
||||
if (taskletpending) {
|
||||
tasklet_disable(&dahdi_dynamic_tlet);
|
||||
tasklet_kill(&dahdi_dynamic_tlet);
|
||||
}
|
||||
#endif
|
||||
del_timer_sync(&alarmcheck);
|
||||
/* Must call again in case it was running before and rescheduled
|
||||
* itself. */
|
||||
dahdi_set_dynamic_ioctl(NULL);
|
||||
del_timer(&alarmcheck);
|
||||
printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Written by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* Copyright (C) 2001-2012, Digium, Inc.
|
||||
* Copyright (C) 2001-2008, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -71,12 +71,14 @@ static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short sub
|
||||
if (z)
|
||||
span = z->span;
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
|
||||
return NULL;
|
||||
return span;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
|
||||
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
|
||||
#else
|
||||
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
|
||||
#endif
|
||||
{
|
||||
struct dahdi_span *span;
|
||||
struct ztdeth_header *zh;
|
||||
@@ -85,7 +87,11 @@ static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
|
||||
#else
|
||||
zh = (struct ztdeth_header *)skb->nh.raw;
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
|
||||
span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
|
||||
#else
|
||||
span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr);
|
||||
#endif
|
||||
if (span) {
|
||||
skb_pull(skb, sizeof(struct ztdeth_header));
|
||||
#ifdef NEW_SKB_LINEARIZE
|
||||
@@ -146,7 +152,7 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
|
||||
spin_lock_irqsave(&zlock, flags);
|
||||
z = dyn->pvt;
|
||||
if (z && z->dev) {
|
||||
if (z->dev) {
|
||||
/* Copy fields to local variables to remove spinlock ASAP */
|
||||
dev = z->dev;
|
||||
memcpy(addr, z->addr, sizeof(z->addr));
|
||||
@@ -185,44 +191,15 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* dahdi_dynamic_flush_work_fn - Flush all pending transactions.
|
||||
*
|
||||
* This function is run in a work queue since we can't guarantee interrupts
|
||||
* will be enabled when we're called, and dev_queue_xmit() requires that
|
||||
* interrupts be enabled.
|
||||
*
|
||||
*/
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static void dahdi_dynamic_flush_work_fn(void *data)
|
||||
#else
|
||||
static void dahdi_dynamic_flush_work_fn(struct work_struct *work)
|
||||
#endif
|
||||
|
||||
static int ztdeth_flush(void)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Handle all transmissions now */
|
||||
while ((skb = skb_dequeue(&skbs))) {
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
|
||||
dahdi_dynamic_flush_work_fn, NULL);
|
||||
#else
|
||||
static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
|
||||
dahdi_dynamic_flush_work_fn);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ztdeth_flush - Flush all pending transactions.
|
||||
*
|
||||
* This function is called in interrupt context while processing the master
|
||||
* span.
|
||||
*/
|
||||
static int ztdeth_flush(void)
|
||||
{
|
||||
schedule_work(&dahdi_dynamic_eth_flush_work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -307,12 +284,11 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
if (cur == z) { /* Successfully removed */
|
||||
dyn->pvt = NULL;
|
||||
printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
|
||||
kfree(z);
|
||||
}
|
||||
spin_unlock_irqrestore(&zlock, flags);
|
||||
}
|
||||
|
||||
static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
|
||||
@@ -435,27 +411,20 @@ static struct notifier_block ztdeth_nblock = {
|
||||
|
||||
static int __init ztdeth_init(void)
|
||||
{
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
dev_add_pack(&ztdeth_ptype);
|
||||
register_netdevice_notifier(&ztdeth_nblock);
|
||||
dahdi_dynamic_register_driver(&ztd_eth);
|
||||
|
||||
skb_queue_head_init(&skbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ztdeth_exit(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
flush_scheduled_work();
|
||||
#else
|
||||
cancel_work_sync(&dahdi_dynamic_eth_flush_work);
|
||||
#endif
|
||||
dahdi_dynamic_unregister_driver(&ztd_eth);
|
||||
unregister_netdevice_notifier(&ztdeth_nblock);
|
||||
dev_remove_pack(&ztdeth_ptype);
|
||||
|
||||
skb_queue_purge(&skbs);
|
||||
unregister_netdevice_notifier(&ztdeth_nblock);
|
||||
dahdi_dynamic_unregister_driver(&ztd_eth);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support");
|
||||
|
||||
@@ -224,8 +224,13 @@ static inline int ethmf_trx_spans_ready(unsigned int addr_hash, struct ztdeth *(
|
||||
/**
|
||||
* Ethernet receiving side processing function.
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
||||
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt, struct net_device *orig_dev)
|
||||
#else
|
||||
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *pt)
|
||||
#endif
|
||||
{
|
||||
int num_spans = 0, span_index = 0;
|
||||
unsigned char *data;
|
||||
@@ -262,8 +267,13 @@ static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
|
||||
find_ethmf(eth_hdr(skb)->h_source,
|
||||
htons(span_index), &z, &span);
|
||||
#else
|
||||
find_ethmf(skb->mac.ethernet->h_source,
|
||||
htons(span_index), &z, &span);
|
||||
#endif
|
||||
if (unlikely(!z || !span)) {
|
||||
/* The recv'd span does not belong to us */
|
||||
/* ethmf_errors_inc(); */
|
||||
@@ -386,6 +396,10 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
struct net_device *dev;
|
||||
unsigned char addr[ETH_ALEN];
|
||||
int spans_ready = 0, index = 0;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
unsigned long flags;
|
||||
#endif
|
||||
|
||||
if (atomic_read(&shutdown))
|
||||
return;
|
||||
@@ -397,12 +411,24 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
return;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
|
||||
if (!atomic_read(&z->ready)) {
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
atomic_inc(&z->ready);
|
||||
if (1 == atomic_read(&z->ready)) {
|
||||
memcpy(z->msgbuf, msg, msglen);
|
||||
z->msgbuf_len = msglen;
|
||||
}
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
}
|
||||
#else
|
||||
if (!atomic_read(&z->ready)) {
|
||||
if (atomic_inc_return(&z->ready) == 1) {
|
||||
memcpy(z->msgbuf, msg, msglen);
|
||||
z->msgbuf_len = msglen;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
spans_ready = ethmf_trx_spans_ready(z->addr_hash, &ready_spans);
|
||||
if (spans_ready) {
|
||||
|
||||
@@ -78,11 +78,10 @@ static LIST_HEAD(dynamic_local_list);
|
||||
static void
|
||||
dahdi_dynamic_local_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
|
||||
{
|
||||
struct dahdi_dynamic_local *d;
|
||||
struct dahdi_dynamic_local *const d = dyn->pvt;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&local_lock, flags);
|
||||
d = dyn->pvt;
|
||||
if (d && d->peer && d->peer->span) {
|
||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->peer->span->flags))
|
||||
dahdi_dynamic_receive(d->peer->span, msg, msglen);
|
||||
@@ -131,12 +130,11 @@ static int digit2int(char d)
|
||||
|
||||
static void dahdi_dynamic_local_destroy(struct dahdi_dynamic *dyn)
|
||||
{
|
||||
struct dahdi_dynamic_local *d;
|
||||
struct dahdi_dynamic_local *d = dyn->pvt;
|
||||
unsigned long flags;
|
||||
struct dahdi_dynamic_local *cur;
|
||||
|
||||
spin_lock_irqsave(&local_lock, flags);
|
||||
d = dyn->pvt;
|
||||
list_for_each_entry(cur, &dynamic_local_list, node) {
|
||||
if (cur->peer == d)
|
||||
cur->peer = NULL;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* This "echo can" will completely hose your audio.
|
||||
* Don't use it unless you're absolutely sure you know what you're doing.
|
||||
*
|
||||
* Copyright (C) 2007-2012, Digium, Inc.
|
||||
* Copyright (C) 2007-2008, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -38,6 +38,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
|
||||
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Based upon mec2.h
|
||||
*
|
||||
* Copyright (C) 2002-2012, Digium, Inc.
|
||||
* Copyright (C) 2002, Digium, Inc.
|
||||
*
|
||||
* Additional background on the techniques used in this code can be found in:
|
||||
*
|
||||
@@ -44,6 +44,9 @@
|
||||
static int debug;
|
||||
static int aggressive;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */
|
||||
/* #define MEC2_STATS 4000 */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Based upon kb1ec.h and mec2.h
|
||||
*
|
||||
* Copyright (C) 2002-2012, Digium, Inc.
|
||||
* Copyright (C) 2002, Digium, Inc.
|
||||
*
|
||||
* Additional background on the techniques used in this code can be found in:
|
||||
*
|
||||
@@ -44,6 +44,9 @@
|
||||
static int debug;
|
||||
static int aggressive;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#define ABS(a) abs(a!=-32768?a:-32767)
|
||||
|
||||
#define RESTORE_COEFFS {\
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
|
||||
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
|
||||
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#include "arith.h"
|
||||
|
||||
#ifndef NULL
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#include "fir.h"
|
||||
|
||||
#ifndef NULL
|
||||
|
||||
@@ -24,16 +24,14 @@
|
||||
|
||||
OCT6114_064_VERSION:=1.05.01
|
||||
OCT6114_128_VERSION:=1.05.01
|
||||
OCT6114_256_VERSION:=1.05.01
|
||||
TC400M_VERSION:=MR6.12
|
||||
VPMADT032_VERSION:=1.25.0
|
||||
HX8_VERSION:=2.06
|
||||
VPMOCT032_VERSION:=1.12.0
|
||||
WCT820_VERSION:=1.76
|
||||
VPMOCT032_VERSION:=1.11.0
|
||||
|
||||
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
|
||||
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820
|
||||
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032
|
||||
|
||||
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
|
||||
# First example: dahdi-fw-oct6114-064-1.05.01
|
||||
@@ -44,18 +42,15 @@ ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRM
|
||||
# Build a list of firmware package filenames we need
|
||||
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-HX8=dahdi-fw-hx8-$(HX8_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz)
|
||||
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
|
||||
|
||||
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
|
||||
|
||||
# Build a list of object files if hotplug will not be used
|
||||
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-HX8=dahdi-fw-hx8.o)
|
||||
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
|
||||
@@ -129,17 +124,6 @@ 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
|
||||
@@ -173,17 +157,6 @@ 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:
|
||||
@@ -212,11 +185,6 @@ 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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* DAHDI Telephony Interface to Digium High-Performance Echo Canceller
|
||||
*
|
||||
* Copyright (C) 2006-2012 Digium, Inc.
|
||||
* Copyright (C) 2006-2008 Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
static int debug;
|
||||
|
||||
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
|
||||
|
||||
#include "hpec_user.h"
|
||||
#include "hpec.h"
|
||||
|
||||
@@ -72,9 +75,18 @@ static int __attribute__((regparm(0), format(printf, 1, 2))) logger(const char *
|
||||
int res;
|
||||
va_list args;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
|
||||
va_start(args, format);
|
||||
res = vprintk(format, args);
|
||||
va_end(args);
|
||||
#else
|
||||
char buf[256];
|
||||
|
||||
va_start(args, format);
|
||||
res = vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
printk(KERN_INFO "%s" buf);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ $Octasic_Revision: 171 $
|
||||
|
||||
/* Max defines.*/
|
||||
#ifndef cOCT6100_MAX_ECHO_CHANNELS
|
||||
#define cOCT6100_MAX_ECHO_CHANNELS 256
|
||||
#define cOCT6100_MAX_ECHO_CHANNELS 128
|
||||
#endif
|
||||
#define cOCT6100_MAX_TSI_CNCTS 1530
|
||||
#define cOCT6100_MAX_CALLER_ID_PLAYOUT_BUFFERS ( 3328 + 6 )
|
||||
|
||||
@@ -146,7 +146,6 @@ struct encdec
|
||||
|
||||
struct pciradio {
|
||||
struct pci_dev *dev;
|
||||
struct dahdi_device *ddev;
|
||||
struct dahdi_span span;
|
||||
unsigned char ios;
|
||||
int usecount;
|
||||
@@ -1489,7 +1488,7 @@ static int pciradio_initialize(struct pciradio *rad)
|
||||
rad->span.flags = DAHDI_FLAG_RBS;
|
||||
rad->span.ops = &pciradio_span_ops;
|
||||
|
||||
if (dahdi_register_device(rad->ddev, &rad->dev->dev)) {
|
||||
if (dahdi_register(&rad->span, 0)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1778,7 +1777,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_free_device(rad->ddev);
|
||||
dahdi_unregister(&rad->span);
|
||||
kfree(rad);
|
||||
return -EIO;
|
||||
|
||||
@@ -1811,7 +1810,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
|
||||
|
||||
static void pciradio_release(struct pciradio *rad)
|
||||
{
|
||||
dahdi_unregister_device(rad->ddev);
|
||||
dahdi_unregister(&rad->span);
|
||||
if (rad->freeregion)
|
||||
release_region(rad->ioaddr, 0xff);
|
||||
kfree(rad);
|
||||
|
||||
@@ -97,7 +97,6 @@ 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 */
|
||||
@@ -286,16 +285,20 @@ 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;
|
||||
s->linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||
s->spantype = SPANTYPE_DIGITAL_T1;
|
||||
s->spantype = "T1";
|
||||
} else {
|
||||
s->channels = 31;
|
||||
s->deflaw = DAHDI_LAW_ALAW;
|
||||
s->linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
|
||||
s->spantype = SPANTYPE_DIGITAL_E1;
|
||||
s->spantype = "E1";
|
||||
}
|
||||
s->chans = tor->chans[x];
|
||||
s->flags = DAHDI_FLAG_RBS;
|
||||
@@ -319,31 +322,19 @@ 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;
|
||||
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;
|
||||
if (dahdi_register(s, 0)) {
|
||||
printk(KERN_ERR "Unable to register span %s\n", s->name);
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
writew(PLX_INTENA, &tor->plx[INTCSR]); /* enable PLX interrupt */
|
||||
|
||||
@@ -351,6 +342,14 @@ 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)
|
||||
@@ -366,8 +365,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -634,6 +631,7 @@ 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)
|
||||
@@ -643,7 +641,11 @@ static void __devexit tor2_remove(struct pci_dev *pdev)
|
||||
writeb(0, &tor->mem8[LEDREG]);
|
||||
writew(0, &tor->plx[INTCSR]);
|
||||
free_irq(tor->irq, tor);
|
||||
dahdi_unregister_device(tor->ddev);
|
||||
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);
|
||||
}
|
||||
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 2s */
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ*2);
|
||||
/* We'll wait for 200ms */
|
||||
ret = wait_for_completion_timeout(&cmd->complete, HZ/5);
|
||||
if (unlikely(!ret)) {
|
||||
spin_lock_irqsave(&vpm->list_lock, flags);
|
||||
list_del(&cmd->node);
|
||||
|
||||
6
drivers/dahdi/voicebus/Makefile
Normal file
6
drivers/dahdi/voicebus/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
@@ -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_device(NULL, NULL);
|
||||
dahdi_register(NULL, 0);
|
||||
spin_lock_init(&loader_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,15 +57,6 @@
|
||||
* (and not tasklet). */
|
||||
#define CONFIG_VOICEBUS_INTERRUPT
|
||||
|
||||
/*
|
||||
* Enable the following definition in order to disable Active-State Power
|
||||
* Management on the PCIe bridge for PCIe cards. This has been known to work
|
||||
* around issues where the BIOS enables it on the cards even though the
|
||||
* platform does not support it.
|
||||
*
|
||||
*/
|
||||
#undef CONFIG_VOICEBUS_DISABLE_ASPM
|
||||
|
||||
/* Define this to use a FIFO for the software echocan reference.
|
||||
* (experimental) */
|
||||
#undef CONFIG_VOICEBUS_ECREFERENCE
|
||||
|
||||
@@ -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\n");
|
||||
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out :O(\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* DAHDI Telephony Interface to VPMADT032 Firmware Loader
|
||||
*
|
||||
* Copyright (C) 2008-2012 Digium, Inc. All rights reserved.
|
||||
* Copyright (C) 2008-2011 Digium, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -38,9 +38,18 @@ logger(const char *format, ...)
|
||||
int res;
|
||||
va_list args;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
|
||||
va_start(args, format);
|
||||
res = vprintk(format, args);
|
||||
va_end(args);
|
||||
#else
|
||||
char buf[256];
|
||||
|
||||
va_start(args, format);
|
||||
res = vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
printk(KERN_INFO "%s" buf);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
7
drivers/dahdi/wcb4xxp/Makefile
Normal file
7
drivers/dahdi/wcb4xxp/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
else
|
||||
endif
|
||||
@@ -2,7 +2,7 @@
|
||||
* WCB410P Quad-BRI PCI Driver
|
||||
* Written by Andrew Kohlsmith <akohlsmith@mixdown.ca>
|
||||
*
|
||||
* Copyright (C) 2009-2012 Digium, Inc.
|
||||
* Copyright (C) 2009-2011 Digium, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
@@ -90,7 +90,6 @@ static int milliwatt = 0;
|
||||
static int pedanticpci = 0;
|
||||
static int teignorered = 0;
|
||||
static int alarmdebounce = 500;
|
||||
static int persistentlayer1 = 1;
|
||||
static int vpmsupport = 1;
|
||||
static int timer_1_ms = 2000;
|
||||
static int timer_3_ms = 30000;
|
||||
@@ -140,7 +139,7 @@ static struct devtype hfc8s_BN = {"BeroNet BN8S0", .ports = 8, .card_type = BN8S
|
||||
static struct devtype hfc4s_SW = {"Swyx 4xS0 SX2 QuadBri", .ports = 4, .card_type = BSWYX_SX2 };
|
||||
static struct devtype hfc4s_EV = {"CCD HFC-4S Eval. Board", .ports = 4,
|
||||
.card_type = QUADBRI_EVAL };
|
||||
|
||||
|
||||
#define CARD_HAS_EC(card) ((card)->card_type == B410P)
|
||||
|
||||
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
|
||||
@@ -1198,6 +1197,7 @@ static int b4xxp_find_sync(struct b4xxp *b4)
|
||||
return src;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
|
||||
static ssize_t b4_timing_master_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -1225,6 +1225,13 @@ static void remove_sysfs_files(struct b4xxp *b4)
|
||||
&dev_attr_timing_master);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void create_sysfs_files(struct b4xxp *b4) { return; }
|
||||
static inline void remove_sysfs_files(struct b4xxp *b4) { return; }
|
||||
|
||||
#endif /* LINUX_KERNEL > 2.6.18 */
|
||||
|
||||
/*
|
||||
* allocates memory and pretty-prints a given S/T state engine state to it.
|
||||
* calling routine is responsible for freeing the pointer returned!
|
||||
@@ -1295,9 +1302,6 @@ static void hfc_force_st_state(struct b4xxp *b4, int port, int state, int resume
|
||||
hfc_handle_state(&b4->spans[port]);
|
||||
}
|
||||
|
||||
static void hfc_stop_st(struct b4xxp_span *s);
|
||||
static void hfc_start_st(struct b4xxp_span *s);
|
||||
|
||||
/* figures out what to do when an S/T port's timer expires. */
|
||||
static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
|
||||
{
|
||||
@@ -1311,15 +1315,10 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
|
||||
s->hfc_timer_on[t_no]);
|
||||
}
|
||||
/*
|
||||
* There are four timers associated with every HFC S/T port:
|
||||
* T1 is used by the NT state machine, and is the maximum time the NT side
|
||||
* should wait for G3 (active) state.
|
||||
* T2 is not actually used in the driver, it is handled by the HFC-4S
|
||||
* internally.
|
||||
* T3 is used by the TE state machine; it is the maximum time the TE side should
|
||||
* wait for the INFO4 (activated) signal.
|
||||
* T4 is a special timer used for debug purposes for monitoring of L1 state
|
||||
* during activation attempt.
|
||||
* there are three timers associated with every HFC S/T port.
|
||||
* T1 is used by the NT state machine, and is the maximum time the NT side should wait for G3 (active) state.
|
||||
* T2 is not actually used in the driver, it is handled by the HFC-4S internally.
|
||||
* T3 is used by the TE state machine; it is the maximum time the TE side should wait for the INFO4 (activated) signal.
|
||||
*/
|
||||
|
||||
/* First, disable the expired timer; hfc_force_st_state() may activate it again. */
|
||||
@@ -1333,14 +1332,7 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
|
||||
hfc_force_st_state(b4, s->port, 1, 1);
|
||||
break;
|
||||
case HFC_T3: /* switch to F3 (deactivated), resume auto mode */
|
||||
hfc_stop_st(s);
|
||||
if (persistentlayer1)
|
||||
hfc_start_st(s);
|
||||
break;
|
||||
case HFC_T4:
|
||||
hfc_handle_state(s);
|
||||
s->hfc_timers[HFC_T4] = b4->ticks + 1000;
|
||||
s->hfc_timer_on[HFC_T4] = 1;
|
||||
hfc_force_st_state(b4, s->port, 3, 1);
|
||||
break;
|
||||
default:
|
||||
if (printk_ratelimit()) {
|
||||
@@ -1363,9 +1355,9 @@ static void hfc_update_st_timers(struct b4xxp *b4)
|
||||
for (i=0; i < b4->numspans; i++) {
|
||||
s = &b4->spans[i];
|
||||
|
||||
for (j = HFC_T1; j < ARRAY_SIZE(s->hfc_timers); j++) {
|
||||
/* we don't really do timer2, it is expired by the
|
||||
* state change handler */
|
||||
for (j=HFC_T1; j <= HFC_T3; j++) {
|
||||
|
||||
/* we don't really do timer2, it is expired by the state change handler */
|
||||
if (j == HFC_T2)
|
||||
continue;
|
||||
|
||||
@@ -1449,7 +1441,6 @@ static void hfc_handle_state(struct b4xxp_span *s)
|
||||
break;
|
||||
case 0x7: /* TE state F7: Activated */
|
||||
s->hfc_timer_on[HFC_T3] = 0;
|
||||
s->hfc_timer_on[HFC_T4] = 0;
|
||||
s->newalarm = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1471,17 +1462,14 @@ static void hfc_handle_state(struct b4xxp_span *s)
|
||||
|
||||
/* If we're in F3 and receiving INFO0, start T3 and jump to F4 */
|
||||
if (!nt && (sta == 3) && (state & V_INFO0)) {
|
||||
if (persistentlayer1) {
|
||||
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
|
||||
s->hfc_timer_on[HFC_T3] = 1;
|
||||
if (DBG_ST) {
|
||||
dev_info(&b4->pdev->dev,
|
||||
"port %d: receiving INFO0 in state 3, "
|
||||
"setting T3 and jumping to F4\n",
|
||||
s->port + 1);
|
||||
}
|
||||
hfc_start_st(s);
|
||||
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
|
||||
s->hfc_timer_on[HFC_T3] = 1;
|
||||
if (DBG_ST) {
|
||||
dev_info(&b4->pdev->dev,
|
||||
"port %d: receiving INFO0 in state 3, "
|
||||
"setting T3 and jumping to F4\n", s->port + 1);
|
||||
}
|
||||
hfc_force_st_state(b4, s->port, 4, 1);
|
||||
}
|
||||
|
||||
/* read in R_BERT_STA to determine where our current sync source is */
|
||||
@@ -1496,24 +1484,6 @@ static void hfc_handle_state(struct b4xxp_span *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void hfc_stop_all_timers(struct b4xxp_span *s)
|
||||
{
|
||||
s->hfc_timer_on[HFC_T4] = 0;
|
||||
s->hfc_timer_on[HFC_T3] = 0;
|
||||
s->hfc_timer_on[HFC_T2] = 0;
|
||||
s->hfc_timer_on[HFC_T1] = 0;
|
||||
}
|
||||
|
||||
static void hfc_stop_st(struct b4xxp_span *s)
|
||||
{
|
||||
struct b4xxp *b4 = s->parent;
|
||||
|
||||
hfc_stop_all_timers(s);
|
||||
|
||||
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA,
|
||||
V_ST_ACT_DEACTIVATE);
|
||||
}
|
||||
|
||||
/*
|
||||
* resets an S/T interface to a given NT/TE mode
|
||||
*/
|
||||
@@ -1524,16 +1494,10 @@ static void hfc_reset_st(struct b4xxp_span *s)
|
||||
|
||||
b4 = s->parent;
|
||||
|
||||
hfc_stop_st(s);
|
||||
|
||||
/* force state G0/F0 (reset), then force state 1/2 (deactivated/sensing) */
|
||||
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_LD_STA);
|
||||
flush_pci(); /* make sure write hit hardware */
|
||||
|
||||
s->span.alarms = DAHDI_ALARM_RED;
|
||||
s->newalarm = DAHDI_ALARM_RED;
|
||||
dahdi_alarm_notify(&s->span);
|
||||
|
||||
udelay(10);
|
||||
|
||||
/* set up the clock control register. Must be done before we activate the interface. */
|
||||
@@ -1564,13 +1528,9 @@ static void hfc_start_st(struct b4xxp_span *s)
|
||||
|
||||
/* start T1 if in NT mode, T3 if in TE mode */
|
||||
if (s->te_mode) {
|
||||
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
|
||||
s->hfc_timers[HFC_T3] = b4->ticks + 500; /* 500ms wait first time, timer_t3_ms afterward. */
|
||||
s->hfc_timer_on[HFC_T3] = 1;
|
||||
s->hfc_timer_on[HFC_T1] = 0;
|
||||
|
||||
s->hfc_timers[HFC_T4] = b4->ticks + 1000;
|
||||
s->hfc_timer_on[HFC_T4] = 1;
|
||||
|
||||
if (DBG_ST) {
|
||||
dev_info(&b4->pdev->dev,
|
||||
"setting port %d t3 timer to %lu\n",
|
||||
@@ -1588,6 +1548,17 @@ static void hfc_start_st(struct b4xxp_span *s)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* TODO: This function is not called anywhere */
|
||||
static void hfc_stop_st(struct b4xxp_span *s)
|
||||
{
|
||||
b4xxp_setreg_ra(s->parent, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_ACT_DEACTIVATE);
|
||||
|
||||
s->hfc_timer_on[HFC_T1] = 0;
|
||||
s->hfc_timer_on[HFC_T2] = 0;
|
||||
s->hfc_timer_on[HFC_T3] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* read in the HFC GPIO to determine each port's mode (TE or NT).
|
||||
* Then, reset and start the port.
|
||||
@@ -1620,6 +1591,8 @@ static void hfc_init_all_st(struct b4xxp *b4)
|
||||
dev_info(&b4->pdev->dev,
|
||||
"Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE"));
|
||||
|
||||
hfc_reset_st(s);
|
||||
hfc_start_st(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1876,10 +1849,10 @@ static int hdlc_tx_frame(struct b4xxp_span *bspan)
|
||||
char debugbuf[256];
|
||||
unsigned long irq_flags;
|
||||
|
||||
/* if we're ignoring TE red alarms and we are in alarm, restart the
|
||||
* S/T state machine */
|
||||
if (bspan->te_mode && bspan->newalarm != 0)
|
||||
hfc_start_st(bspan);
|
||||
/* if we're ignoring TE red alarms and we are in alarm, restart the S/T state machine */
|
||||
if (bspan->te_mode && teignorered && bspan->newalarm == DAHDI_ALARM_RED) {
|
||||
hfc_force_st_state(b4, bspan->port, 3, 1);
|
||||
}
|
||||
|
||||
fifo = bspan->fifos[2];
|
||||
res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size);
|
||||
@@ -2367,10 +2340,6 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
|
||||
if (lc->sync)
|
||||
b4->spans[lc->sync - 1].sync = (span->offset + 1);
|
||||
|
||||
hfc_reset_st(bspan);
|
||||
if (persistentlayer1)
|
||||
hfc_start_st(bspan);
|
||||
|
||||
b4xxp_reset_span(bspan);
|
||||
|
||||
/* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */
|
||||
@@ -2505,9 +2474,8 @@ static void init_spans(struct b4xxp *b4)
|
||||
bspan = &b4->spans[i];
|
||||
bspan->parent = b4;
|
||||
|
||||
bspan->span.spantype = (bspan->te_mode)
|
||||
? SPANTYPE_DIGITAL_BRI_TE
|
||||
: SPANTYPE_DIGITAL_BRI_NT;
|
||||
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;
|
||||
bspan->span.flags = 0;
|
||||
@@ -2525,6 +2493,11 @@ 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 */
|
||||
@@ -2956,27 +2929,14 @@ 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++) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3012,7 +2972,10 @@ 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:
|
||||
dahdi_unregister_device(b4->ddev);
|
||||
while (x) {
|
||||
dahdi_unregister(&b4->spans[x].span);
|
||||
x--;
|
||||
};
|
||||
|
||||
b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */
|
||||
free_irq(pdev->irq, b4);
|
||||
@@ -3033,8 +2996,6 @@ 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:
|
||||
@@ -3049,11 +3010,14 @@ 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;
|
||||
|
||||
dahdi_unregister_device(b4->ddev);
|
||||
for (i=b4->numspans - 1; i >= 0; i--) {
|
||||
dahdi_unregister(&b4->spans[i].span);
|
||||
}
|
||||
|
||||
b4xxp_init_stage1(b4);
|
||||
remove_sysfs_files(b4);
|
||||
@@ -3068,8 +3032,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -3151,7 +3113,6 @@ module_param(vpmsupport, int, S_IRUGO);
|
||||
module_param(timer_1_ms, int, S_IRUGO | S_IWUSR);
|
||||
module_param(timer_3_ms, int, S_IRUGO | S_IWUSR);
|
||||
module_param(companding, charp, S_IRUGO);
|
||||
module_param(persistentlayer1, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
MODULE_PARM_DESC(debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm");
|
||||
MODULE_PARM_DESC(spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4");
|
||||
|
||||
@@ -376,7 +376,6 @@
|
||||
#define HFC_T1 0
|
||||
#define HFC_T2 1
|
||||
#define HFC_T3 2
|
||||
#define HFC_T4 3
|
||||
|
||||
#define MAX_SPANS_PER_CARD 8
|
||||
|
||||
@@ -397,8 +396,8 @@ struct b4xxp_span {
|
||||
unsigned long alarmtimer;
|
||||
|
||||
int te_mode; /* 1=TE, 0=NT */
|
||||
unsigned long hfc_timers[4]; /* T1, T2, T3, Fake T4 */
|
||||
int hfc_timer_on[4]; /* 1=timer active */
|
||||
unsigned long hfc_timers[WCB4XXP_CHANNELS_PER_SPAN]; /* T1, T2, T3 */
|
||||
int hfc_timer_on[WCB4XXP_CHANNELS_PER_SPAN]; /* 1=timer active */
|
||||
int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */
|
||||
|
||||
/* HDLC controller fields */
|
||||
@@ -475,7 +474,6 @@ struct b4xxp {
|
||||
/* Flags for our bottom half */
|
||||
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
|
||||
struct tasklet_struct b4xxp_tlet;
|
||||
struct dahdi_device *ddev;
|
||||
};
|
||||
|
||||
/* CPLD access bits */
|
||||
|
||||
@@ -135,7 +135,6 @@ 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;
|
||||
@@ -648,24 +647,19 @@ 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);
|
||||
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;
|
||||
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->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
|
||||
@@ -674,8 +668,7 @@ static int wcfxo_initialize(struct wcfxo *wc)
|
||||
|
||||
wc->chan->pvt = wc;
|
||||
wc->span.ops = &wcfxo_span_ops;
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -983,7 +976,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_device(wc->ddev);
|
||||
dahdi_unregister(&wc->span);
|
||||
free_irq(pdev->irq, wc);
|
||||
|
||||
/* Reset PCI chip and registers */
|
||||
@@ -991,8 +984,6 @@ 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;
|
||||
}
|
||||
@@ -1004,11 +995,9 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
|
||||
static void wcfxo_release(struct wcfxo *wc)
|
||||
{
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
dahdi_unregister(&wc->span);
|
||||
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,7 +159,6 @@ 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 */
|
||||
};
|
||||
|
||||
@@ -273,11 +272,10 @@ static void t1xxp_release(struct t1xxp *wc)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
dahdi_unregister(&wc->span);
|
||||
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");
|
||||
}
|
||||
@@ -772,32 +770,26 @@ 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->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.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->span.chans = wc->chans;
|
||||
wc->span.flags = DAHDI_FLAG_RBS;
|
||||
if (wc->ise1) {
|
||||
wc->span.channels = 31;
|
||||
wc->span.deflaw = DAHDI_LAW_ALAW;
|
||||
wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
|
||||
wc->span.spantype = SPANTYPE_DIGITAL_E1;
|
||||
wc->span.spantype = "E1";
|
||||
} else {
|
||||
wc->span.channels = 24;
|
||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||
wc->span.spantype = SPANTYPE_DIGITAL_T1;
|
||||
wc->span.spantype = "T1";
|
||||
}
|
||||
for (x=0;x<wc->span.channels;x++) {
|
||||
sprintf(wc->chans[x]->name, "WCT1/%d/%d", wc->num, x + 1);
|
||||
@@ -809,8 +801,7 @@ static int t1xxp_software_init(struct t1xxp *wc)
|
||||
wc->chans[x]->chanpos = x + 1;
|
||||
}
|
||||
wc->span.ops = &t1xxp_span_ops;
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -917,10 +908,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->ddev->irqmisses++;
|
||||
wc->span.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->ddev->irqmisses++;
|
||||
wc->span.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 $(FIRM_DIR)/dahdi-fw-oct6114-256.o
|
||||
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o
|
||||
$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
|
||||
endif
|
||||
|
||||
@@ -26,6 +26,3 @@ $(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o
|
||||
|
||||
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o
|
||||
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o
|
||||
|
||||
8
drivers/dahdi/wct4xxp/Makefile
Normal file
8
drivers/dahdi/wct4xxp/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
|
||||
else
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Digium, Inc.
|
||||
* Copyright (C) 2005-2006 Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
@@ -28,6 +28,10 @@
|
||||
#include "vpm450m.h"
|
||||
#include "oct6100api/oct6100_api.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
|
||||
/* API for Octasic access */
|
||||
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
|
||||
{
|
||||
@@ -168,9 +172,9 @@ UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
|
||||
|
||||
struct vpm450m {
|
||||
tPOCT6100_INSTANCE_API pApiInstance;
|
||||
UINT32 aulEchoChanHndl[256];
|
||||
int chanflags[256];
|
||||
int ecmode[256];
|
||||
UINT32 aulEchoChanHndl[128];
|
||||
int chanflags[128];
|
||||
int ecmode[128];
|
||||
int numchans;
|
||||
};
|
||||
|
||||
@@ -418,8 +422,6 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
|
||||
tOCT6100_CHANNEL_OPEN *ChannelOpen;
|
||||
UINT32 ulResult;
|
||||
const unsigned int mask = (8 == numspans) ? 0x7 : 0x3;
|
||||
unsigned int sout_stream, rout_stream;
|
||||
struct vpm450m *vpm450m;
|
||||
int x,y,law;
|
||||
|
||||
@@ -465,22 +467,15 @@ 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
|
||||
@@ -512,11 +507,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
|
||||
kfree(ChannelOpen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sout_stream = (8 == numspans) ? 29 : 2;
|
||||
rout_stream = (8 == numspans) ? 24 : 3;
|
||||
|
||||
for (x = 0; x < ((8 == numspans) ? 256 : 128); x++) {
|
||||
for (x = 0; x < ARRAY_SIZE(vpm450m->aulEchoChanHndl); x++) {
|
||||
/* execute this loop always on 4 span cards but
|
||||
* on 2 span cards only execute for the channels related to our spans */
|
||||
if (( numspans > 2) || ((x & 0x03) <2)) {
|
||||
@@ -524,7 +515,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 & mask])
|
||||
if (isalaw[x & 0x03])
|
||||
law = cOCT6100_PCM_A_LAW;
|
||||
else
|
||||
law = cOCT6100_PCM_U_LAW;
|
||||
@@ -538,13 +529,11 @@ 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 = sout_stream;
|
||||
ChannelOpen->TdmConfig.ulSoutStream = 2;
|
||||
ChannelOpen->TdmConfig.ulSoutTimeslot = x;
|
||||
#if 1
|
||||
ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
|
||||
ChannelOpen->TdmConfig.ulRoutStream = rout_stream;
|
||||
ChannelOpen->TdmConfig.ulRoutStream = 3;
|
||||
ChannelOpen->TdmConfig.ulRoutTimeslot = x;
|
||||
#endif
|
||||
ChannelOpen->VqeConfig.fEnableNlp = TRUE;
|
||||
ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
|
||||
ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
|
||||
@@ -554,7 +543,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 %x!\n", x, ulResult);
|
||||
printk(KERN_NOTICE "Failed to open channel %d!\n", x);
|
||||
continue;
|
||||
}
|
||||
for (y = 0; y < ARRAY_SIZE(tones); y++) {
|
||||
|
||||
@@ -54,12 +54,6 @@
|
||||
#define FRMR_SIC3 0x40
|
||||
#define FRMR_CMR1 0x44
|
||||
#define FRMR_CMR2 0x45
|
||||
/* OctalFALC Only */
|
||||
#define FRMR_CMR4 0x41
|
||||
#define FRMR_CMR5 0x42
|
||||
#define FRMR_CMR6 0x43
|
||||
#define FRMR_GPC2 0x8a
|
||||
/* End Octal */
|
||||
#define FRMR_GCR 0x46
|
||||
#define FRMR_ISR0 0x68
|
||||
#define FRMR_ISR0_RME 0x80
|
||||
@@ -82,13 +76,6 @@
|
||||
#define FRMR_CIS_GIS2 0x02
|
||||
#define FRMR_CIS_GIS3 0x04
|
||||
#define FRMR_CIS_GIS4 0x08
|
||||
|
||||
/* CIS - Octal falc bits */
|
||||
#define FRMR_CIS_GIS5 0x10
|
||||
#define FRMR_CIS_GIS6 0x20
|
||||
#define FRMR_CIS_GIS7 0x40
|
||||
#define FRMR_CIS_GIS8 0x80
|
||||
|
||||
#define FRMR_CMDR 0x02
|
||||
#define FRMR_CMDR_SRES 0x01
|
||||
#define FRMR_CMDR_XRES 0x10
|
||||
@@ -126,11 +113,6 @@ 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
|
||||
@@ -138,7 +120,5 @@ struct t4_reg {
|
||||
#define T4_CHANGE_LATENCY 4
|
||||
#define T4_IGNORE_LATENCY 5
|
||||
|
||||
#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
|
||||
#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
|
||||
#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
|
||||
#define WCT4_GET_REGS _IOW (DAHDI_CODE, 60, struct t4_regs)
|
||||
|
||||
|
||||
7
drivers/dahdi/wctc4xxp/Makefile
Normal file
7
drivers/dahdi/wctc4xxp/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
else
|
||||
endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Wildcard TC400B Driver
|
||||
*
|
||||
* Copyright (C) 2006-2012, Digium, Inc.
|
||||
* Copyright (C) 2006-2010, Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -42,7 +42,11 @@
|
||||
|
||||
#include "dahdi/kernel.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
#include <asm/io.h>
|
||||
#else
|
||||
#include <linux/io.h>
|
||||
#endif
|
||||
|
||||
/* COMPILE TIME OPTIONS =================================================== */
|
||||
|
||||
@@ -69,6 +73,13 @@
|
||||
dev_info(&(wc)->pdev->dev, _fmt, ## _args); \
|
||||
} \
|
||||
|
||||
#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)
|
||||
typedef unsigned gfp_t; /* Added in 2.6.14 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* define CONFIG_WCTC4XXP_POLLING to operate in a pure polling mode. This is
|
||||
* was placed in as a debugging tool for a particluar system that wasn't
|
||||
|
||||
@@ -205,7 +205,6 @@ struct wctdm {
|
||||
struct pci_dev *dev;
|
||||
char *variety;
|
||||
struct dahdi_span span;
|
||||
struct dahdi_device *ddev;
|
||||
unsigned char ios;
|
||||
int usecount;
|
||||
unsigned int intcount;
|
||||
@@ -2363,26 +2362,13 @@ 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);
|
||||
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;
|
||||
|
||||
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));
|
||||
if (alawoverride) {
|
||||
printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
|
||||
wc->span.deflaw = DAHDI_LAW_ALAW;
|
||||
@@ -2398,15 +2384,12 @@ 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;
|
||||
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
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;
|
||||
@@ -2694,9 +2677,7 @@ 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_device(wc->ddev);
|
||||
kfree(wc->ddev->location);
|
||||
dahdi_free_device(wc->ddev);
|
||||
dahdi_unregister(&wc->span);
|
||||
kfree(wc);
|
||||
return -EIO;
|
||||
|
||||
@@ -2727,14 +2708,10 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
|
||||
|
||||
static void wctdm_release(struct wctdm *wc)
|
||||
{
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
dahdi_unregister(&wc->span);
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
6
drivers/dahdi/wctdm24xxp/Makefile
Normal file
6
drivers/dahdi/wctdm24xxp/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@
|
||||
* \brief Default ringer debounce (in ms)
|
||||
*/
|
||||
#define DEFAULT_RING_DEBOUNCE 1024
|
||||
|
||||
#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */
|
||||
|
||||
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
|
||||
@@ -84,6 +85,7 @@
|
||||
|
||||
#define NUM_CAL_REGS 12
|
||||
|
||||
#define ISR_COMMANDS 2
|
||||
#define QRV_DEBOUNCETIME 20
|
||||
|
||||
#define VPM150M_HPI_CONTROL 0x00
|
||||
@@ -105,30 +107,10 @@ 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;
|
||||
@@ -164,26 +146,29 @@ struct wctdm_chan {
|
||||
};
|
||||
|
||||
struct fxo {
|
||||
enum ring_detector_state ring_state:4;
|
||||
enum battery_state battery_state:4;
|
||||
enum polarity_state polarity_state:4;
|
||||
u8 ring_polarity_change_count:4;
|
||||
u8 hook_ring_shadow;
|
||||
s8 line_voltage_status;
|
||||
int wasringing;
|
||||
int lastrdtx;
|
||||
int lastrdtx_count;
|
||||
int ringdebounce;
|
||||
int offhook;
|
||||
int battdebounce;
|
||||
int battalarm;
|
||||
enum battery_state battery;
|
||||
int lastpol;
|
||||
int polarity;
|
||||
int polaritydebounce;
|
||||
int neonmwi_state;
|
||||
int neonmwi_last_voltage;
|
||||
unsigned int neonmwi_debounce;
|
||||
unsigned int neonmwi_offcounter;
|
||||
unsigned long display_fxovoltage;
|
||||
unsigned long ringdebounce_timer;
|
||||
unsigned long battdebounce_timer;
|
||||
unsigned long poldebounce_timer;
|
||||
};
|
||||
|
||||
struct fxs {
|
||||
u8 oht_active:1;
|
||||
u8 off_hook:1;
|
||||
int oldrxhook;
|
||||
int debouncehook;
|
||||
int lastrxhook;
|
||||
int debounce;
|
||||
int ohttimer;
|
||||
int idletxhookstate; /* IDLE changing hook state */
|
||||
/* lasttxhook reflects the last value written to the proslic's reg
|
||||
* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last
|
||||
@@ -195,18 +180,13 @@ struct fxs {
|
||||
* voicebus ISR.
|
||||
*/
|
||||
int lasttxhook;
|
||||
u8 linefeed_control_shadow;
|
||||
u8 hook_state_shadow;
|
||||
int oppending_ms;
|
||||
int palarms;
|
||||
struct dahdi_vmwi_info vmwisetting;
|
||||
int vmwi_active_messages;
|
||||
int vmwi_linereverse;
|
||||
int reversepolarity; /* polarity reversal */
|
||||
struct calregs calregs;
|
||||
unsigned long check_alarm;
|
||||
unsigned long check_proslic;
|
||||
unsigned long oppending_timeout;
|
||||
unsigned long ohttimer;
|
||||
};
|
||||
|
||||
struct qrv {
|
||||
@@ -223,7 +203,6 @@ struct qrv {
|
||||
int radmode;
|
||||
signed short rxgain;
|
||||
signed short txgain;
|
||||
u8 isrshadow[3];
|
||||
};
|
||||
|
||||
enum module_type {
|
||||
@@ -236,7 +215,7 @@ enum module_type {
|
||||
};
|
||||
|
||||
struct wctdm_module {
|
||||
union modtypes {
|
||||
union {
|
||||
struct fxo fxo;
|
||||
struct fxs fxs;
|
||||
struct qrv qrv;
|
||||
@@ -248,6 +227,7 @@ struct wctdm_module {
|
||||
struct list_head active_cmds;
|
||||
u8 offsets[3];
|
||||
u8 subaddr;
|
||||
u8 isrshadow[ISR_COMMANDS];
|
||||
u8 card;
|
||||
|
||||
enum module_type type;
|
||||
@@ -262,7 +242,7 @@ struct wctdm {
|
||||
spinlock_t frame_list_lock;
|
||||
struct list_head frame_list;
|
||||
|
||||
unsigned long framecount;
|
||||
unsigned int intcount;
|
||||
unsigned char txident;
|
||||
unsigned char rxident;
|
||||
|
||||
@@ -297,7 +277,6 @@ struct wctdm {
|
||||
int not_ready; /* 0 when the entire card is ready to go */
|
||||
unsigned long checkflag; /* Internal state flags and task bits */
|
||||
int companding;
|
||||
struct dahdi_device *ddev;
|
||||
};
|
||||
|
||||
static inline bool is_initialized(struct wctdm *wc)
|
||||
|
||||
@@ -2150,9 +2150,7 @@ static int b400m_set_ntte(struct b400m_span *bspan, int te_mode, int term_on)
|
||||
int all_modes = 0, all_terms = 0;
|
||||
int i;
|
||||
|
||||
bspan->wspan->span.spantype = (te_mode > 0)
|
||||
? SPANTYPE_DIGITAL_BRI_TE
|
||||
: SPANTYPE_DIGITAL_BRI_NT;
|
||||
bspan->wspan->span.spantype = (te_mode > 0) ? "TE" : "NT";
|
||||
|
||||
bspan->te_mode = te_mode;
|
||||
bspan->term_on = term_on;
|
||||
|
||||
@@ -174,7 +174,6 @@ 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 */
|
||||
};
|
||||
@@ -341,12 +340,10 @@ static void t1xxp_release(struct t1 *wc)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
dahdi_unregister_device(wc->ddev);
|
||||
dahdi_unregister(&wc->span);
|
||||
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");
|
||||
}
|
||||
@@ -979,33 +976,27 @@ 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->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.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;
|
||||
if (wc->spantype == TYPE_E1) {
|
||||
if (unchannelized)
|
||||
wc->span.channels = 32;
|
||||
else
|
||||
wc->span.channels = 31;
|
||||
wc->span.deflaw = DAHDI_LAW_ALAW;
|
||||
wc->span.spantype = SPANTYPE_DIGITAL_E1;
|
||||
wc->span.spantype = "E1";
|
||||
wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
|
||||
} else {
|
||||
wc->span.channels = 24;
|
||||
wc->span.deflaw = DAHDI_LAW_MULAW;
|
||||
wc->span.spantype = SPANTYPE_DIGITAL_T1;
|
||||
wc->span.spantype = "T1";
|
||||
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
|
||||
}
|
||||
wc->span.chans = wc->chans;
|
||||
@@ -1020,8 +1011,7 @@ static int t1xxp_software_init(struct t1 *wc)
|
||||
wc->chans[x]->chanpos = x + 1;
|
||||
}
|
||||
wc->span.ops = &t1xxp_span_ops;
|
||||
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
|
||||
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
|
||||
if (dahdi_register(&wc->span, 0)) {
|
||||
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1128,10 +1118,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->ddev->irqmisses++;
|
||||
wc->span.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->ddev->irqmisses++;
|
||||
wc->span.irqmisses++;
|
||||
}
|
||||
for (y=0;y<DAHDI_CHUNKSIZE;y++) {
|
||||
for (x=0;x<wc->span.channels;x++) {
|
||||
|
||||
6
drivers/dahdi/wcte12xp/Makefile
Normal file
6
drivers/dahdi/wcte12xp/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
ifdef KBUILD_EXTMOD
|
||||
# We only get here on kernels 2.6.0-2.6.9 .
|
||||
# For newer kernels, Kbuild will be included directly by the kernel
|
||||
# build system.
|
||||
include $(src)/Kbuild
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -74,11 +74,8 @@
|
||||
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
|
||||
//TODO: make a separate macro
|
||||
|
||||
enum linemode {
|
||||
T1 = 1,
|
||||
E1,
|
||||
J1,
|
||||
};
|
||||
#define TYPE_T1 1
|
||||
#define TYPE_E1 2
|
||||
|
||||
struct command {
|
||||
struct list_head node;
|
||||
@@ -97,6 +94,7 @@ 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;
|
||||
@@ -118,7 +116,6 @@ 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 */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum bri_opcodes {
|
||||
XPROTO_NAME(BRI, SET_LED) = 0x33,
|
||||
XPROTO_NAME(BRI, SET_LED) = 0x33,
|
||||
};
|
||||
|
||||
#endif /* CARD_BRI_H */
|
||||
#endif /* CARD_BRI_H */
|
||||
|
||||
@@ -42,20 +42,25 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||
static bool echo_packet_is_valid(xpacket_t *pack);
|
||||
static void echo_packet_dump(const char *msg, xpacket_t *pack);
|
||||
|
||||
DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];);
|
||||
DEF_RPACKET_DATA(ECHO, SET,
|
||||
byte timeslots[ECHO_TIMESLOTS];
|
||||
);
|
||||
|
||||
DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;);
|
||||
DEF_RPACKET_DATA(ECHO, SET_REPLY,
|
||||
byte status;
|
||||
byte reserved;
|
||||
);
|
||||
|
||||
struct ECHO_priv_data {
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(ECHO);
|
||||
static xproto_table_t PROTO_TABLE(ECHO);
|
||||
|
||||
/*---------------- ECHO: Methods -------------------------------------------*/
|
||||
|
||||
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
const xproto_table_t *proto_table, byte subtype,
|
||||
int subunits, int subunit_ports, bool to_phone)
|
||||
{
|
||||
xpd_t *xpd = NULL;
|
||||
int channels = 0;
|
||||
@@ -65,9 +70,8 @@ static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||
return NULL;
|
||||
}
|
||||
XBUS_DBG(GENERAL, xbus, "\n");
|
||||
xpd =
|
||||
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct ECHO_priv_data), proto_table, channels);
|
||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||
sizeof(struct ECHO_priv_data), proto_table, channels);
|
||||
if (!xpd)
|
||||
return NULL;
|
||||
xpd->type_name = "ECHO";
|
||||
@@ -118,17 +122,19 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1003) < 5)
|
||||
notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
|
||||
notify_bad_xpd(__func__, xbus, addr,
|
||||
orig_xpd->xpdname);
|
||||
return -EPROTO;
|
||||
}
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
/* Update /proc info only if reply related to last reg read request */
|
||||
if (REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
REG_FIELD(info, regnum)
|
||||
&& REG_FIELD(&xpd->requested_reply, do_subreg) ==
|
||||
REG_FIELD(info, do_subreg)
|
||||
&& REG_FIELD(&xpd->requested_reply, subreg) ==
|
||||
REG_FIELD(info, subreg)) {
|
||||
if (
|
||||
REG_FIELD(&xpd->requested_reply, regnum) ==
|
||||
REG_FIELD(info, regnum) &&
|
||||
REG_FIELD(&xpd->requested_reply, do_subreg) ==
|
||||
REG_FIELD(info, do_subreg) &&
|
||||
REG_FIELD(&xpd->requested_reply, subreg) ==
|
||||
REG_FIELD(info, subreg)) {
|
||||
xpd->last_reply = *info;
|
||||
}
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
@@ -140,7 +146,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
static /* 0x39 */ HOSTCMD(ECHO, SET)
|
||||
{
|
||||
struct xbus_echo_state *es;
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
int ret;
|
||||
@@ -166,7 +172,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
|
||||
{
|
||||
int ts_number;
|
||||
int ts_mask;
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
|
||||
ts = xpd->xbus->echo_state.timeslots;
|
||||
/*
|
||||
@@ -192,7 +198,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
|
||||
ts[ts_number] &= ~ts_mask;
|
||||
}
|
||||
LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
|
||||
__func__, on, ts_number, ts_mask);
|
||||
__func__, on, ts_number, ts_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -201,7 +207,7 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
|
||||
int ts_number;
|
||||
int ts_mask;
|
||||
int is_on;
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
|
||||
ts = xpd->xbus->echo_state.timeslots;
|
||||
ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2; /* Which bit? */
|
||||
@@ -214,14 +220,14 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
|
||||
}
|
||||
#if 0
|
||||
LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
|
||||
is_on, ts_number, ts_mask);
|
||||
is_on, ts_number, ts_mask);
|
||||
#endif
|
||||
return is_on;
|
||||
}
|
||||
|
||||
static void ECHO_ec_dump(xbus_t *xbus)
|
||||
{
|
||||
__u8 *ts;
|
||||
byte *ts;
|
||||
int i;
|
||||
|
||||
ts = xbus->echo_state.timeslots;
|
||||
@@ -230,11 +236,12 @@ static void ECHO_ec_dump(xbus_t *xbus)
|
||||
"EC-DUMP[%03d]: "
|
||||
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
|
||||
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
|
||||
i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3],
|
||||
ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8],
|
||||
ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12],
|
||||
ts[i + 13], ts[i + 14], ts[i + 15]
|
||||
);
|
||||
i,
|
||||
ts[i+0], ts[i+1], ts[i+2], ts[i+3], ts[i+4], ts[i+5],
|
||||
ts[i+6], ts[i+7],
|
||||
ts[i+8], ts[i+9], ts[i+10], ts[i+11], ts[i+12],
|
||||
ts[i+13], ts[i+14], ts[i+15]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +255,7 @@ static int ECHO_ec_update(xbus_t *xbus)
|
||||
/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
|
||||
HANDLER_DEF(ECHO, SET_REPLY)
|
||||
{
|
||||
__u8 status;
|
||||
byte status;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
|
||||
@@ -256,26 +263,26 @@ HANDLER_DEF(ECHO, SET_REPLY)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xops echo_xops = {
|
||||
.card_new = ECHO_card_new,
|
||||
.card_init = ECHO_card_init,
|
||||
.card_remove = ECHO_card_remove,
|
||||
.card_tick = ECHO_card_tick,
|
||||
.card_register_reply = ECHO_card_register_reply,
|
||||
static const struct xops echo_xops = {
|
||||
.card_new = ECHO_card_new,
|
||||
.card_init = ECHO_card_init,
|
||||
.card_remove = ECHO_card_remove,
|
||||
.card_tick = ECHO_card_tick,
|
||||
.card_register_reply = ECHO_card_register_reply,
|
||||
};
|
||||
|
||||
static const struct echoops echoops = {
|
||||
.ec_set = ECHO_ec_set,
|
||||
.ec_get = ECHO_ec_get,
|
||||
.ec_update = ECHO_ec_update,
|
||||
.ec_dump = ECHO_ec_dump,
|
||||
static const struct echoops echoops = {
|
||||
.ec_set = ECHO_ec_set,
|
||||
.ec_get = ECHO_ec_get,
|
||||
.ec_update = ECHO_ec_update,
|
||||
.ec_dump = ECHO_ec_dump,
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(ECHO) = {
|
||||
.owner = THIS_MODULE,
|
||||
.entries = {
|
||||
/* Table Card Opcode */
|
||||
XENTRY( ECHO, ECHO, SET_REPLY ),
|
||||
/* Table Card Opcode */
|
||||
XENTRY(ECHO, ECHO, SET_REPLY),
|
||||
},
|
||||
.name = "ECHO",
|
||||
.ports_per_subunit = 1,
|
||||
@@ -288,7 +295,7 @@ static xproto_table_t PROTO_TABLE(ECHO) = {
|
||||
|
||||
static bool echo_packet_is_valid(xpacket_t *pack)
|
||||
{
|
||||
const xproto_entry_t *xe = NULL;
|
||||
const xproto_entry_t *xe = NULL;
|
||||
// DBG(GENERAL, "\n");
|
||||
xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
|
||||
return xe != NULL;
|
||||
@@ -302,14 +309,14 @@ static void echo_packet_dump(const char *msg, xpacket_t *pack)
|
||||
/*------------------------- sysfs stuff --------------------------------*/
|
||||
static int echo_xpd_probe(struct device *dev)
|
||||
{
|
||||
xpd_t *ec_xpd;
|
||||
int ret = 0;
|
||||
xpd_t *ec_xpd;
|
||||
int ret = 0;
|
||||
|
||||
ec_xpd = dev_to_xpd(dev);
|
||||
/* Is it our device? */
|
||||
if (ec_xpd->type != XPD_TYPE_ECHO) {
|
||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||
ec_xpd->type);
|
||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n",
|
||||
dev_name(dev), ec_xpd->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||
@@ -318,20 +325,23 @@ static int echo_xpd_probe(struct device *dev)
|
||||
|
||||
static int echo_xpd_remove(struct device *dev)
|
||||
{
|
||||
xpd_t *ec_xpd;
|
||||
xpd_t *ec_xpd;
|
||||
|
||||
ec_xpd = dev_to_xpd(dev);
|
||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xpd_driver echo_driver = {
|
||||
.type = XPD_TYPE_ECHO,
|
||||
.driver = {
|
||||
.name = "echo",
|
||||
.owner = THIS_MODULE,
|
||||
.probe = echo_xpd_probe,
|
||||
.remove = echo_xpd_remove}
|
||||
static struct xpd_driver echo_driver = {
|
||||
.type = XPD_TYPE_ECHO,
|
||||
.driver = {
|
||||
.name = "echo",
|
||||
#ifndef OLD_HOTPLUG_SUPPORT
|
||||
.owner = THIS_MODULE,
|
||||
#endif
|
||||
.probe = echo_xpd_probe,
|
||||
.remove = echo_xpd_remove
|
||||
}
|
||||
};
|
||||
|
||||
static int __init card_echo_startup(void)
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum echo_opcodes {
|
||||
XPROTO_NAME(ECHO, SET) = 0x39,
|
||||
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
|
||||
XPROTO_NAME(ECHO, SET) = 0x39,
|
||||
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
|
||||
};
|
||||
|
||||
#endif /* CARD_ECHO_H */
|
||||
#endif /* CARD_ECHO_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,16 +25,18 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum fxo_opcodes {
|
||||
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, /**/
|
||||
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
|
||||
/**/
|
||||
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, XPD_STATE) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
||||
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
||||
};
|
||||
|
||||
|
||||
DEF_RPACKET_DATA(FXO, SIG_CHANGED,
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
|
||||
#endif /* CARD_FXO_H */
|
||||
#endif /* CARD_FXO_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,15 +25,18 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum fxs_opcodes {
|
||||
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
||||
/**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
||||
/**/
|
||||
XPROTO_NAME(FXS, XPD_STATE) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
||||
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
||||
};
|
||||
|
||||
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
|
||||
#endif /* CARD_FXS_H */
|
||||
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
|
||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||
);
|
||||
|
||||
#endif /* CARD_FXS_H */
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kmod.h>
|
||||
#include "xdefs.h"
|
||||
#include "xpd.h"
|
||||
#include "xpp_dahdi.h"
|
||||
@@ -33,22 +32,21 @@
|
||||
|
||||
static const char rcsid[] = "$Id$";
|
||||
|
||||
DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644,
|
||||
"The directory of card initialization scripts");
|
||||
DEF_PARM(charp,initdir, "/usr/share/dahdi", 0644, "The directory of card initialization scripts");
|
||||
|
||||
#define CHIP_REGISTERS "chipregs"
|
||||
|
||||
extern int debug;
|
||||
extern int debug;
|
||||
|
||||
/*---------------- GLOBAL PROC handling -----------------------------------*/
|
||||
|
||||
static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
bool eoftx)
|
||||
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;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Zero length multibyte is legal and has special meaning for the
|
||||
@@ -67,210 +65,203 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
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__);
|
||||
PORT_ERR(xbus, unit, portno,
|
||||
"%s: failed sending xframe\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_hexbyte(const char *buf)
|
||||
{
|
||||
char *endp;
|
||||
unsigned val;
|
||||
char *endp;
|
||||
unsigned val;
|
||||
|
||||
val = simple_strtoul(buf, &endp, 16);
|
||||
if (*endp != '\0' || val > 0xFF)
|
||||
if(*endp != '\0' || val > 0xFF)
|
||||
return -EBADR;
|
||||
return (__u8)val;
|
||||
return (byte)val;
|
||||
}
|
||||
|
||||
static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||
{
|
||||
int argno;
|
||||
char num_args;
|
||||
int portno;
|
||||
bool writing;
|
||||
int op; /* [W]rite, [R]ead */
|
||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
|
||||
bool do_subreg = 0;
|
||||
int regnum;
|
||||
int subreg;
|
||||
int data_low;
|
||||
bool do_datah;
|
||||
int data_high;
|
||||
int ret = -EBADR;
|
||||
int argno;
|
||||
char num_args;
|
||||
int portno;
|
||||
bool writing;
|
||||
int op; /* [W]rite, [R]ead */
|
||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
|
||||
bool do_subreg = 0;
|
||||
int regnum;
|
||||
int subreg;
|
||||
int data_low;
|
||||
bool do_datah;
|
||||
int data_high;
|
||||
int ret = -EBADR;
|
||||
|
||||
num_args = 2; /* port + operation */
|
||||
if (argc < num_args) {
|
||||
num_args = 2; /* port + operation */
|
||||
if(argc < num_args) {
|
||||
XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
|
||||
XPD_ERR(xpd,
|
||||
"Any Command is composed of at least %d words "
|
||||
"(got only %d)\n",
|
||||
num_args, argc);
|
||||
"Any Command is composed of at least %d words (got only %d)\n",
|
||||
num_args, argc);
|
||||
goto out;
|
||||
}
|
||||
/* Process the arguments */
|
||||
argno = 0;
|
||||
if (strcmp(argv[argno], "*") == 0) {
|
||||
if(strcmp(argv[argno], "*") == 0) {
|
||||
portno = PORT_BROADCAST;
|
||||
//XPD_DBG(REGS, xpd, "Port broadcast\n");
|
||||
} else {
|
||||
portno = parse_hexbyte(argv[argno]);
|
||||
if (portno < 0 || portno >= 8) {
|
||||
if(portno < 0 || portno >= 8) {
|
||||
XPD_ERR(xpd, "Illegal port number '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
//XPD_DBG(REGS, xpd, "Port is %d\n", portno);
|
||||
}
|
||||
argno++;
|
||||
if (strlen(argv[argno]) != 2) {
|
||||
if(strlen(argv[argno]) != 2) {
|
||||
XPD_ERR(xpd, "Wrong operation codes '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
op = argv[argno][0];
|
||||
switch (op) {
|
||||
case 'W':
|
||||
writing = 1;
|
||||
num_args++; /* data low */
|
||||
//XPD_DBG(REGS, xpd, "WRITING\n");
|
||||
break;
|
||||
case 'R':
|
||||
writing = 0;
|
||||
//XPD_DBG(REGS, xpd, "READING\n");
|
||||
break;
|
||||
default:
|
||||
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
|
||||
goto out;
|
||||
switch(op) {
|
||||
case 'W':
|
||||
writing = 1;
|
||||
num_args++; /* data low */
|
||||
//XPD_DBG(REGS, xpd, "WRITING\n");
|
||||
break;
|
||||
case 'R':
|
||||
writing = 0;
|
||||
//XPD_DBG(REGS, xpd, "READING\n");
|
||||
break;
|
||||
default:
|
||||
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
|
||||
goto out;
|
||||
}
|
||||
addr_mode = argv[argno][1];
|
||||
switch (addr_mode) {
|
||||
case 'I':
|
||||
XPD_NOTICE(xpd,
|
||||
"'I' is deprecated in register commands. "
|
||||
"Use 'S' instead.\n");
|
||||
/* fall through */
|
||||
case 'S':
|
||||
do_subreg = 1;
|
||||
num_args += 2; /* register + subreg */
|
||||
//XPD_DBG(REGS, xpd, "SUBREG\n");
|
||||
break;
|
||||
case 'D':
|
||||
do_subreg = 0;
|
||||
num_args++; /* register */
|
||||
//XPD_DBG(REGS, xpd, "DIRECT\n");
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
if (op != 'W') {
|
||||
XPD_ERR(xpd,
|
||||
"Can use Multibyte (%c) only with op 'W'\n",
|
||||
addr_mode);
|
||||
switch(addr_mode) {
|
||||
case 'I':
|
||||
XPD_NOTICE(xpd, "'I' is deprecated in register commands. Use 'S' instead.\n");
|
||||
/* fall through */
|
||||
case 'S':
|
||||
do_subreg = 1;
|
||||
num_args += 2; /* register + subreg */
|
||||
//XPD_DBG(REGS, xpd, "SUBREG\n");
|
||||
break;
|
||||
case 'D':
|
||||
do_subreg = 0;
|
||||
num_args++; /* register */
|
||||
//XPD_DBG(REGS, xpd, "DIRECT\n");
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
if(op != 'W') {
|
||||
XPD_ERR(xpd,
|
||||
"Can use Multibyte (%c) only with op 'W'\n", addr_mode);
|
||||
goto out;
|
||||
}
|
||||
num_args--; /* No data low */
|
||||
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
|
||||
break;
|
||||
default:
|
||||
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
|
||||
goto out;
|
||||
}
|
||||
num_args--; /* No data low */
|
||||
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
|
||||
break;
|
||||
default:
|
||||
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
|
||||
goto out;
|
||||
}
|
||||
if (argv[argno][2] != '\0') {
|
||||
if(argv[argno][2] != '\0') {
|
||||
XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
if (argc < num_args) {
|
||||
if(argc < num_args) {
|
||||
XPD_ERR(xpd,
|
||||
"Command \"%s\" is composed of at least %d words "
|
||||
"(got only %d)\n",
|
||||
argv[argno], num_args, argc);
|
||||
"Command \"%s\" is composed of at least %d words (got only %d)\n",
|
||||
argv[argno], num_args, argc);
|
||||
goto out;
|
||||
}
|
||||
argno++;
|
||||
if (addr_mode == 'M' || addr_mode == 'm') {
|
||||
if (argno < argc) {
|
||||
if(addr_mode == 'M' || addr_mode == 'm') {
|
||||
if(argno < argc) {
|
||||
XPD_ERR(xpd,
|
||||
"Magic-Multibyte(%c) with %d extra arguments\n",
|
||||
addr_mode, argc - argno);
|
||||
"Magic-Multibyte(%c) with %d extra arguments\n",
|
||||
addr_mode, argc - argno);
|
||||
goto out;
|
||||
}
|
||||
ret =
|
||||
send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
||||
addr_mode == 'm');
|
||||
ret = send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
||||
addr_mode == 'm');
|
||||
goto out;
|
||||
}
|
||||
/* Normal (non-Magic) register commands */
|
||||
do_datah = 0;
|
||||
if (argno >= argc) {
|
||||
if(argno >= argc) {
|
||||
XPD_ERR(xpd, "Missing register number\n");
|
||||
goto out;
|
||||
}
|
||||
regnum = parse_hexbyte(argv[argno]);
|
||||
if (regnum < 0) {
|
||||
if(regnum < 0) {
|
||||
XPD_ERR(xpd, "Illegal register number '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
//XPD_DBG(REGS, xpd, "Register is %X\n", regnum);
|
||||
argno++;
|
||||
if (do_subreg) {
|
||||
if (argno >= argc) {
|
||||
if(do_subreg) {
|
||||
if(argno >= argc) {
|
||||
XPD_ERR(xpd, "Missing subregister number\n");
|
||||
goto out;
|
||||
}
|
||||
subreg = parse_hexbyte(argv[argno]);
|
||||
if (subreg < 0) {
|
||||
XPD_ERR(xpd, "Illegal subregister number '%s'\n",
|
||||
argv[argno]);
|
||||
if(subreg < 0) {
|
||||
XPD_ERR(xpd, "Illegal subregister number '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
//XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
|
||||
argno++;
|
||||
} else
|
||||
subreg = 0;
|
||||
if (writing) {
|
||||
if (argno >= argc) {
|
||||
if(writing) {
|
||||
if(argno >= argc) {
|
||||
XPD_ERR(xpd, "Missing data low number\n");
|
||||
goto out;
|
||||
}
|
||||
data_low = parse_hexbyte(argv[argno]);
|
||||
if (data_low < 0) {
|
||||
XPD_ERR(xpd, "Illegal data_low number '%s'\n",
|
||||
argv[argno]);
|
||||
if(data_low < 0) {
|
||||
XPD_ERR(xpd, "Illegal data_low number '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
//XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
|
||||
argno++;
|
||||
} else
|
||||
data_low = 0;
|
||||
if (argno < argc) {
|
||||
if(argno < argc) {
|
||||
do_datah = 1;
|
||||
if (!argv[argno]) {
|
||||
if(!argv[argno]) {
|
||||
XPD_ERR(xpd, "Missing data high number\n");
|
||||
goto out;
|
||||
}
|
||||
data_high = parse_hexbyte(argv[argno]);
|
||||
if (data_high < 0) {
|
||||
XPD_ERR(xpd, "Illegal data_high number '%s'\n",
|
||||
argv[argno]);
|
||||
if(data_high < 0) {
|
||||
XPD_ERR(xpd, "Illegal data_high number '%s'\n", argv[argno]);
|
||||
goto out;
|
||||
}
|
||||
//XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
|
||||
argno++;
|
||||
} else
|
||||
data_high = 0;
|
||||
if (argno < argc) {
|
||||
XPD_ERR(xpd, "Command contains an extra %d argument\n",
|
||||
argc - argno);
|
||||
if(argno < argc) {
|
||||
XPD_ERR(xpd,
|
||||
"Command contains an extra %d argument\n",
|
||||
argc - argno);
|
||||
goto out;
|
||||
}
|
||||
#if 0
|
||||
XPD_DBG(REGS, xpd,
|
||||
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
|
||||
"dataL=%d do_datah=%d dataH=%d\n",
|
||||
portno, /* portno */
|
||||
writing, /* writing */
|
||||
regnum, do_subreg, /* use subreg */
|
||||
subreg, /* subreg */
|
||||
data_low, do_datah, /* use data_high */
|
||||
data_high);
|
||||
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d dataL=%d do_datah=%d dataH=%d\n",
|
||||
portno, /* portno */
|
||||
writing, /* writing */
|
||||
regnum,
|
||||
do_subreg, /* use subreg */
|
||||
subreg, /* subreg */
|
||||
data_low,
|
||||
do_datah, /* use data_high*/
|
||||
data_high);
|
||||
#endif
|
||||
ret = xpp_register_request(xpd->xbus, xpd, portno,
|
||||
writing, regnum, do_subreg, subreg,
|
||||
@@ -279,38 +270,36 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_ARGS 10
|
||||
|
||||
int parse_chip_command(xpd_t *xpd, char *cmdline)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
int ret = -EBADR;
|
||||
__u8 buf[MAX_PROC_WRITE];
|
||||
char *str;
|
||||
char *p;
|
||||
char *argv[MAX_ARGS + 1];
|
||||
int argc;
|
||||
int i;
|
||||
xbus_t *xbus;
|
||||
int ret = -EBADR;
|
||||
byte buf[MAX_PROC_WRITE];
|
||||
char *str;
|
||||
char *p;
|
||||
static const int MAX_ARGS = 10;
|
||||
char *argv[MAX_ARGS + 1];
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
xbus = xpd->xbus;
|
||||
if (!XBUS_FLAGS(xbus, CONNECTED)) {
|
||||
if(!XBUS_FLAGS(xbus, CONNECTED)) {
|
||||
XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
strlcpy(buf, cmdline, MAX_PROC_WRITE); /* Save a copy */
|
||||
if (buf[0] == '#' || buf[0] == ';')
|
||||
if(buf[0] == '#' || buf[0] == ';')
|
||||
XPD_DBG(REGS, xpd, "Note: '%s'\n", buf);
|
||||
if ((p = strchr(buf, '#')) != NULL) /* Truncate comments */
|
||||
if((p = strchr(buf, '#')) != NULL) /* Truncate comments */
|
||||
*p = '\0';
|
||||
if ((p = strchr(buf, ';')) != NULL) /* Truncate comments */
|
||||
if((p = strchr(buf, ';')) != NULL) /* Truncate comments */
|
||||
*p = '\0';
|
||||
/* Trim leading whitespace */
|
||||
for (p = buf; *p && (*p == ' ' || *p == '\t'); p++)
|
||||
for(p = buf; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
|
||||
;
|
||||
str = p;
|
||||
for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) {
|
||||
if (*p != '\0') {
|
||||
for(i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS; ) {
|
||||
if(*p != '\0') {
|
||||
argv[i] = p;
|
||||
// XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
|
||||
i++;
|
||||
@@ -318,12 +307,11 @@ int parse_chip_command(xpd_t *xpd, char *cmdline)
|
||||
}
|
||||
argv[i] = NULL;
|
||||
argc = i;
|
||||
if (p) {
|
||||
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n",
|
||||
i, p);
|
||||
if(p) {
|
||||
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n", i, p);
|
||||
goto out;
|
||||
}
|
||||
if (argc)
|
||||
if(argc)
|
||||
ret = execute_chip_command(xpd, argc, argv);
|
||||
else
|
||||
ret = 0; /* empty command - no op */
|
||||
@@ -340,11 +328,11 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
|
||||
|
||||
/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
int ret = -ENODEV;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
|
||||
if (!xbus) {
|
||||
if(!xbus) {
|
||||
DBG(DEVICES, "NO XBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -354,35 +342,33 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
|
||||
RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION;
|
||||
RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0;
|
||||
XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION);
|
||||
if (xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
|
||||
if(xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
|
||||
ret = send_cmd_frame(xbus, xframe);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||
__u8 data_low, bool do_datah, __u8 data_high,
|
||||
bool should_reply)
|
||||
bool writing, byte regnum, bool do_subreg, byte subreg,
|
||||
byte data_low, bool do_datah, byte data_high, bool should_reply)
|
||||
{
|
||||
int ret = 0;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
int ret = 0;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
reg_cmd_t *reg_cmd;
|
||||
|
||||
if (!xbus) {
|
||||
if(!xbus) {
|
||||
DBG(REGS, "NO XBUS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
|
||||
xpd->xbus_idx);
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx);
|
||||
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
|
||||
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
|
||||
data_low, data_high);
|
||||
(writing)?'W':'R',
|
||||
(do_subreg)?'S':'D',
|
||||
regnum, subreg, data_low, data_high);
|
||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||
/* do not count the 'bytes' field */
|
||||
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
|
||||
reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field
|
||||
reg_cmd->is_multibyte = 0;
|
||||
if (portno == PORT_BROADCAST) {
|
||||
if(portno == PORT_BROADCAST) {
|
||||
reg_cmd->portnum = 0;
|
||||
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
|
||||
} else {
|
||||
@@ -398,15 +384,14 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
REG_FIELD(reg_cmd, do_datah) = do_datah;
|
||||
REG_FIELD(reg_cmd, data_low) = data_low;
|
||||
REG_FIELD(reg_cmd, data_high) = data_high;
|
||||
if (should_reply)
|
||||
if(should_reply)
|
||||
xpd->requested_reply = *reg_cmd;
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
|
||||
reg_cmd->portnum, reg_cmd);
|
||||
if(debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, reg_cmd->portnum, reg_cmd);
|
||||
dump_packet("REG_REQ", pack, 1);
|
||||
}
|
||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||
if (subreg)
|
||||
if(!xframe->usec_towait) { /* default processing time of SPI */
|
||||
if(subreg)
|
||||
xframe->usec_towait = 2000;
|
||||
else
|
||||
xframe->usec_towait = 1000;
|
||||
@@ -414,19 +399,18 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
ret = send_cmd_frame(xbus, xframe);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_register_request);
|
||||
|
||||
/*
|
||||
* The XPD parameter is totaly ignored by the driver and firmware as well.
|
||||
*/
|
||||
/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
const char *mode_name;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
const char *mode_name;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
if ((mode_name = sync_mode_name(mode)) == NULL) {
|
||||
if((mode_name = sync_mode_name(mode)) == NULL) {
|
||||
XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -443,8 +427,8 @@ EXPORT_SYMBOL(xpp_register_request);
|
||||
*/
|
||||
static int send_xbus_reset(xbus_t *xbus, uint8_t reset_mask)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
xframe_t *xframe;
|
||||
xpacket_t *pack;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, XBUS_RESET, 0);
|
||||
@@ -477,14 +461,14 @@ HANDLER_DEF(GLOBAL, NULL_REPLY)
|
||||
return 0;
|
||||
}
|
||||
|
||||
HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
{ /* 0x08 */
|
||||
struct xbus_workqueue *worker;
|
||||
__u8 rev;
|
||||
struct unit_descriptor *units;
|
||||
int count_units;
|
||||
int i;
|
||||
int ret = 0;
|
||||
HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
||||
{
|
||||
struct xbus_workqueue *worker;
|
||||
byte rev;
|
||||
struct unit_descriptor *units;
|
||||
int count_units;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
if (!xbus) {
|
||||
NOTICE("%s: xbus is gone!!!\n", __func__);
|
||||
@@ -492,31 +476,31 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
}
|
||||
rev = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, rev);
|
||||
units = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, unit_descriptor);
|
||||
count_units = XPACKET_LEN(pack) - ((__u8 *)units - (__u8 *)pack);
|
||||
count_units = XPACKET_LEN(pack) - ((byte *)units - (byte *)pack);
|
||||
count_units /= sizeof(*units);
|
||||
if (rev != XPP_PROTOCOL_VERSION) {
|
||||
if(rev != XPP_PROTOCOL_VERSION) {
|
||||
XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
|
||||
rev, XPP_PROTOCOL_VERSION);
|
||||
rev, XPP_PROTOCOL_VERSION);
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
}
|
||||
if (count_units > NUM_UNITS) {
|
||||
if(count_units > NUM_UNITS) {
|
||||
XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
|
||||
count_units, NUM_UNITS);
|
||||
count_units, NUM_UNITS);
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
}
|
||||
if (count_units <= 0) {
|
||||
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units);
|
||||
if(count_units <= 0) {
|
||||
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n",
|
||||
count_units);
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
}
|
||||
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
|
||||
if(!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
|
||||
ret = -EPROTO;
|
||||
goto proto_err;
|
||||
}
|
||||
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n",
|
||||
count_units, rev);
|
||||
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n", count_units, rev);
|
||||
if (xbus_check_unique(xbus))
|
||||
return -EBUSY;
|
||||
xbus->revision = rev;
|
||||
@@ -526,14 +510,12 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < count_units; i++) {
|
||||
struct unit_descriptor *this_unit = &units[i];
|
||||
struct card_desc_struct *card_desc;
|
||||
unsigned long flags;
|
||||
for(i = 0; i < count_units; i++) {
|
||||
struct unit_descriptor *this_unit = &units[i];
|
||||
struct card_desc_struct *card_desc;
|
||||
unsigned long flags;
|
||||
|
||||
if ((card_desc =
|
||||
KZALLOC(sizeof(struct card_desc_struct),
|
||||
GFP_ATOMIC)) == NULL) {
|
||||
if((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
|
||||
XBUS_ERR(xbus, "Card description allocation failed.\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
@@ -546,15 +528,16 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||
card_desc->numchips = this_unit->numchips;
|
||||
card_desc->ports_per_chip = this_unit->ports_per_chip;
|
||||
card_desc->port_dir = this_unit->port_dir;
|
||||
card_desc->ports =
|
||||
card_desc->numchips * card_desc->ports_per_chip;
|
||||
XBUS_INFO(xbus,
|
||||
" CARD %d type=%d.%d ports=%d (%dx%d), "
|
||||
"port-dir=0x%02X\n",
|
||||
card_desc->xpd_addr.unit, card_desc->type,
|
||||
card_desc->subtype, card_desc->ports,
|
||||
card_desc->numchips, card_desc->ports_per_chip,
|
||||
card_desc->port_dir);
|
||||
card_desc->ports = card_desc->numchips * card_desc->ports_per_chip;
|
||||
XBUS_INFO(xbus, " CARD %d type=%d.%d ports=%d (%dx%d), port-dir=0x%02X\n",
|
||||
card_desc->xpd_addr.unit,
|
||||
card_desc->type,
|
||||
card_desc->subtype,
|
||||
card_desc->ports,
|
||||
card_desc->numchips,
|
||||
card_desc->ports_per_chip,
|
||||
card_desc->port_dir
|
||||
);
|
||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||
worker->num_units++;
|
||||
XBUS_COUNTER(xbus, UNITS)++;
|
||||
@@ -575,23 +558,21 @@ out:
|
||||
|
||||
HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
||||
{
|
||||
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
|
||||
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
|
||||
|
||||
if (!xpd) {
|
||||
static int rate_limit;
|
||||
if(!xpd) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1003) < 5)
|
||||
notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
|
||||
if((rate_limit++ % 1003) < 5)
|
||||
notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), "");
|
||||
return -EPROTO;
|
||||
}
|
||||
if (debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
|
||||
reg);
|
||||
if(debug & DBG_REGS) {
|
||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum, reg);
|
||||
dump_packet("REG_REPLY", pack, 1);
|
||||
}
|
||||
if (!XMETHOD(card_register_reply, xpd)) {
|
||||
XPD_ERR(xpd,
|
||||
"REGISTER_REPLY: missing card_register_reply()\n");
|
||||
if (! XMETHOD(card_register_reply, xpd)) {
|
||||
XPD_ERR(xpd, "REGISTER_REPLY: without card_register_reply() method\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return CALL_XMETHOD(card_register_reply, xpd, reg);
|
||||
@@ -599,12 +580,12 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
||||
|
||||
HANDLER_DEF(GLOBAL, SYNC_REPLY)
|
||||
{
|
||||
__u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
|
||||
__u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
|
||||
const char *mode_name;
|
||||
byte mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
|
||||
byte drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
|
||||
const char *mode_name;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
if ((mode_name = sync_mode_name(mode)) == NULL) {
|
||||
if((mode_name = sync_mode_name(mode)) == NULL) {
|
||||
XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -618,26 +599,24 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY)
|
||||
|
||||
HANDLER_DEF(GLOBAL, ERROR_CODE)
|
||||
{
|
||||
char tmp_name[TMP_NAME_LEN];
|
||||
static long rate_limit;
|
||||
__u8 category_code;
|
||||
__u8 errorbits;
|
||||
char tmp_name[TMP_NAME_LEN];
|
||||
static long rate_limit;
|
||||
byte category_code;
|
||||
byte errorbits;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
if ((rate_limit++ % 5003) > 200)
|
||||
if((rate_limit++ % 5003) > 200)
|
||||
return 0;
|
||||
category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code);
|
||||
errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
|
||||
if (!xpd) {
|
||||
if(!xpd) {
|
||||
snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
|
||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
||||
} else {
|
||||
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname,
|
||||
xpd->xpdname);
|
||||
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname);
|
||||
}
|
||||
NOTICE
|
||||
("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
|
||||
tmp_name, cmd->name, category_code, errorbits, rate_limit);
|
||||
NOTICE("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
|
||||
tmp_name, cmd->name, category_code, errorbits, rate_limit);
|
||||
dump_packet("FIRMWARE: ", pack, 1);
|
||||
/*
|
||||
* FIXME: Should implement an error recovery plan
|
||||
@@ -645,14 +624,15 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
xproto_table_t PROTO_TABLE(GLOBAL) = {
|
||||
.entries = {
|
||||
/* Prototable Card Opcode */
|
||||
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
|
||||
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
|
||||
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
|
||||
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
|
||||
XENTRY( GLOBAL, GLOBAL, SYNC_REPLY ),
|
||||
XENTRY( GLOBAL, GLOBAL, ERROR_CODE ),
|
||||
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
|
||||
XENTRY( GLOBAL, GLOBAL, ERROR_CODE ),
|
||||
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
|
||||
},
|
||||
.name = "GLOBAL",
|
||||
.packet_is_valid = global_packet_is_valid,
|
||||
@@ -661,7 +641,7 @@ xproto_table_t PROTO_TABLE(GLOBAL) = {
|
||||
|
||||
static bool global_packet_is_valid(xpacket_t *pack)
|
||||
{
|
||||
const xproto_entry_t *xe;
|
||||
const xproto_entry_t *xe;
|
||||
|
||||
//DBG(GENERAL, "\n");
|
||||
xe = xproto_global_entry(XPACKET_OP(pack));
|
||||
@@ -675,37 +655,28 @@ static void global_packet_dump(const char *msg, xpacket_t *pack)
|
||||
|
||||
#define MAX_PATH_STR 128
|
||||
|
||||
#ifndef UMH_WAIT_PROC
|
||||
/*
|
||||
* - UMH_WAIT_PROC was introduced as enum in 2.6.23
|
||||
* with a value of 1
|
||||
* - It was changed to a macro (and it's value was modified) in 3.3.0
|
||||
*/
|
||||
#define UMH_WAIT_PROC 1
|
||||
#endif
|
||||
|
||||
int run_initialize_registers(xpd_t *xpd)
|
||||
{
|
||||
int ret;
|
||||
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];
|
||||
char directionstr[MAX_ENV_STR];
|
||||
char revstr[MAX_ENV_STR];
|
||||
char connectorstr[MAX_ENV_STR];
|
||||
char xbuslabel[MAX_ENV_STR];
|
||||
char init_card[MAX_PATH_STR];
|
||||
__u8 direction_mask;
|
||||
int i;
|
||||
char *argv[] = {
|
||||
int ret;
|
||||
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];
|
||||
char directionstr[MAX_ENV_STR];
|
||||
char revstr[MAX_ENV_STR];
|
||||
char connectorstr[MAX_ENV_STR];
|
||||
char xbuslabel[MAX_ENV_STR];
|
||||
char init_card[MAX_PATH_STR];
|
||||
byte direction_mask;
|
||||
int i;
|
||||
char *argv[] = {
|
||||
init_card,
|
||||
NULL
|
||||
};
|
||||
char *envp[] = {
|
||||
char *envp[] = {
|
||||
busstr,
|
||||
busnumstr,
|
||||
modelstr,
|
||||
@@ -721,82 +692,74 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
|
||||
BUG_ON(!xpd);
|
||||
xbus = xpd->xbus;
|
||||
if (!initdir || !initdir[0]) {
|
||||
if(!initdir || !initdir[0]) {
|
||||
XPD_NOTICE(xpd, "Missing initdir parameter\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
|
||||
if(!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
direction_mask = 0;
|
||||
for (i = 0; i < xpd->subunits; i++) {
|
||||
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
|
||||
for(i = 0; i < xpd->subunits; i++) {
|
||||
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
|
||||
|
||||
if (!su) {
|
||||
XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n",
|
||||
if(!su) {
|
||||
XPD_ERR(xpd,
|
||||
"Have %d subunits, but not subunit #%d\n",
|
||||
xpd->subunits, i);
|
||||
continue;
|
||||
}
|
||||
direction_mask |=
|
||||
(PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
|
||||
direction_mask |= (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
|
||||
}
|
||||
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(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);
|
||||
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
|
||||
direction_mask);
|
||||
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d", direction_mask);
|
||||
snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
|
||||
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s",
|
||||
xbus->connector);
|
||||
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->connector);
|
||||
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
|
||||
if (snprintf
|
||||
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
|
||||
xbus->revision) > MAX_PATH_STR) {
|
||||
XPD_NOTICE(xpd,
|
||||
"Cannot initialize. pathname is longer "
|
||||
"than %d characters.\n",
|
||||
MAX_PATH_STR);
|
||||
if(snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d",
|
||||
initdir, xpd->type, xbus->revision) > MAX_PATH_STR) {
|
||||
XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR);
|
||||
ret = -E2BIG;
|
||||
goto err;
|
||||
}
|
||||
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
||||
XBUS_ERR(xbus,
|
||||
"Skipped register initialization. In state %s.\n",
|
||||
xbus_statename(XBUS_STATE(xbus)));
|
||||
if(!XBUS_IS(xbus, RECVD_DESC)) {
|
||||
XBUS_ERR(xbus, "Skipped register initialization. In state %s.\n",
|
||||
xbus_statename(XBUS_STATE(xbus)));
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
|
||||
init_card, xpd->type, xbus->revision);
|
||||
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
|
||||
init_card, xpd->type, xbus->revision);
|
||||
ret = call_usermodehelper(init_card, argv, envp, 1);
|
||||
/*
|
||||
* Carefully report results
|
||||
*/
|
||||
if (ret == 0)
|
||||
if(ret == 0)
|
||||
XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
|
||||
else if (ret < 0) {
|
||||
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card,
|
||||
ret);
|
||||
else if(ret < 0) {
|
||||
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ret);
|
||||
} else {
|
||||
__u8 exitval = ((unsigned)ret >> 8) & 0xFF;
|
||||
__u8 sigval = ret & 0xFF;
|
||||
byte exitval = ((unsigned)ret >> 8) & 0xFF;
|
||||
byte sigval = ret & 0xFF;
|
||||
|
||||
if (!exitval) {
|
||||
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card,
|
||||
sigval);
|
||||
if(!exitval) {
|
||||
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, sigval);
|
||||
} else {
|
||||
XPD_ERR(xpd, "'%s' aborted with exitval %d\n",
|
||||
init_card, exitval);
|
||||
XPD_ERR(xpd, "'%s' aborted with exitval %d\n", init_card, exitval);
|
||||
}
|
||||
ret = -EINVAL;
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sync_mode_name);
|
||||
EXPORT_SYMBOL(run_initialize_registers);
|
||||
EXPORT_SYMBOL(xpp_register_request);
|
||||
|
||||
@@ -26,45 +26,75 @@
|
||||
#include "xbus-pcm.h"
|
||||
|
||||
enum global_opcodes {
|
||||
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
|
||||
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
|
||||
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
|
||||
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
|
||||
/**/ XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
|
||||
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
|
||||
/**/ XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
|
||||
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
|
||||
/**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
|
||||
XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23,
|
||||
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
|
||||
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
|
||||
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
|
||||
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
|
||||
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
|
||||
/**/
|
||||
XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
|
||||
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
|
||||
/**/
|
||||
XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
|
||||
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
|
||||
/**/
|
||||
XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
|
||||
XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23,
|
||||
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
|
||||
};
|
||||
|
||||
struct unit_descriptor {
|
||||
struct xpd_addr addr;
|
||||
__u8 subtype:4;
|
||||
__u8 type:4;
|
||||
__u8 numchips;
|
||||
__u8 ports_per_chip;
|
||||
__u8 port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
|
||||
__u8 reserved[2];
|
||||
struct xpd_addr ec_addr;
|
||||
struct xpd_addr addr;
|
||||
byte subtype:4;
|
||||
byte type:4;
|
||||
byte numchips;
|
||||
byte ports_per_chip;
|
||||
byte port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
|
||||
byte reserved[2];
|
||||
struct xpd_addr ec_addr;
|
||||
};
|
||||
|
||||
#define NUM_UNITS 6
|
||||
|
||||
DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
|
||||
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST, __u8 rev; __u8 reserved;);
|
||||
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION, __u8 rev; __u8 reserved[3];
|
||||
struct unit_descriptor unit_descriptor[NUM_UNITS];);
|
||||
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, reg_cmd_t reg_cmd;);
|
||||
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
|
||||
DEF_RPACKET_DATA(GLOBAL, PCM_READ, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
|
||||
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, __u8 sync_mode; __u8 drift;);
|
||||
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, __u8 sync_mode; __u8 drift;);
|
||||
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, reg_cmd_t regcmd;);
|
||||
DEF_RPACKET_DATA(GLOBAL, XBUS_RESET, __u8 mask;);
|
||||
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
|
||||
__u8 bad_packet[0];);
|
||||
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST,
|
||||
byte rev;
|
||||
byte reserved;
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION,
|
||||
byte rev;
|
||||
byte reserved[3];
|
||||
struct unit_descriptor unit_descriptor[NUM_UNITS];
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST,
|
||||
reg_cmd_t reg_cmd;
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE,
|
||||
xpp_line_t lines;
|
||||
byte pcm[PCM_CHUNKSIZE];
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, PCM_READ,
|
||||
xpp_line_t lines;
|
||||
byte pcm[PCM_CHUNKSIZE];
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE,
|
||||
byte sync_mode;
|
||||
byte drift;
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY,
|
||||
byte sync_mode;
|
||||
byte drift;
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY,
|
||||
reg_cmd_t regcmd;
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, XBUS_RESET,
|
||||
byte mask;
|
||||
);
|
||||
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE,
|
||||
byte category_code;
|
||||
byte errorbits;
|
||||
byte bad_packet[0];
|
||||
);
|
||||
|
||||
/* 0x07 */ DECLARE_CMD(GLOBAL, AB_REQUEST);
|
||||
/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift);
|
||||
@@ -72,14 +102,13 @@ DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
|
||||
/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS);
|
||||
|
||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||
__u8 data_low, bool do_datah, __u8 data_high,
|
||||
bool should_reply);
|
||||
bool writing, byte regnum, bool do_subreg, byte subreg,
|
||||
byte data_low, bool do_datah, byte data_high, bool should_reply);
|
||||
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||
bool eoftx, __u8 *buf, unsigned len);
|
||||
bool eoftx, byte *buf, unsigned len);
|
||||
extern xproto_table_t PROTO_TABLE(GLOBAL);
|
||||
int run_initialize_registers(xpd_t *xpd);
|
||||
int parse_chip_command(xpd_t *xpd, char *cmdline);
|
||||
extern charp initdir;
|
||||
|
||||
#endif /* CARD_GLOBAL_H */
|
||||
#endif /* CARD_GLOBAL_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,8 @@
|
||||
#include "xpd.h"
|
||||
|
||||
enum pri_opcodes {
|
||||
XPROTO_NAME(PRI, SET_LED) = 0x33,
|
||||
XPROTO_NAME(PRI, SET_LED) = 0x33,
|
||||
};
|
||||
|
||||
#endif /* CARD_PRI_H */
|
||||
|
||||
#endif /* CARD_PRI_H */
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
# warning "This module is tested only with 2.6 kernels"
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
@@ -30,48 +35,57 @@
|
||||
static const char rcsid[] = "$Id$";
|
||||
|
||||
#define P_(x) [ x ] = { .value = x, .name = #x, }
|
||||
static struct {
|
||||
static struct {
|
||||
int value;
|
||||
char *name;
|
||||
} poll_names[] = {
|
||||
P_(POLLIN), P_(POLLPRI), P_(POLLOUT), P_(POLLERR), P_(POLLHUP),
|
||||
P_(POLLNVAL), P_(POLLRDNORM), P_(POLLRDBAND), P_(POLLWRNORM),
|
||||
P_(POLLWRBAND), P_(POLLMSG), P_(POLLREMOVE)
|
||||
P_(POLLIN),
|
||||
P_(POLLPRI),
|
||||
P_(POLLOUT),
|
||||
P_(POLLERR),
|
||||
P_(POLLHUP),
|
||||
P_(POLLNVAL),
|
||||
P_(POLLRDNORM),
|
||||
P_(POLLRDBAND),
|
||||
P_(POLLWRNORM),
|
||||
P_(POLLWRBAND),
|
||||
P_(POLLMSG),
|
||||
P_(POLLREMOVE)
|
||||
};
|
||||
|
||||
#undef P_
|
||||
|
||||
void dump_poll(int debug, const char *msg, int poll)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(poll_names); i++) {
|
||||
if (poll & poll_names[i].value)
|
||||
for(i = 0; i < ARRAY_SIZE(poll_names); i++) {
|
||||
if(poll & poll_names[i].value)
|
||||
DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dump_poll);
|
||||
|
||||
void alarm2str(int alarm, char *buf, int buflen)
|
||||
{
|
||||
char *p = buf;
|
||||
int left = buflen;
|
||||
int i;
|
||||
int n;
|
||||
char *p = buf;
|
||||
int left = buflen;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
if (!alarm) {
|
||||
if(!alarm) {
|
||||
snprintf(buf, buflen, "NONE");
|
||||
return;
|
||||
}
|
||||
memset(buf, 0, buflen);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (left && (alarm & BIT(i))) {
|
||||
for(i = 0; i < 8; i++) {
|
||||
if(left && (alarm & BIT(i))) {
|
||||
n = snprintf(p, left, "%s,", alarmbit2str(i));
|
||||
p += n;
|
||||
left -= n;
|
||||
}
|
||||
}
|
||||
if (p > buf) /* kill last comma */
|
||||
if(p > buf) /* kill last comma */
|
||||
*(p - 1) = '\0';
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dump_poll);
|
||||
EXPORT_SYMBOL(alarm2str);
|
||||
|
||||
@@ -26,76 +26,55 @@
|
||||
|
||||
/* Debugging Macros */
|
||||
|
||||
#define PRINTK(level, category, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: " fmt, \
|
||||
#level, category, THIS_MODULE->name, ## __VA_ARGS__)
|
||||
#define PRINTK(level, category, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, THIS_MODULE->name, ## __VA_ARGS__)
|
||||
|
||||
#define XBUS_PRINTK(level, category, xbus, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \
|
||||
#define XBUS_PRINTK(level, category, xbus, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \
|
||||
category, THIS_MODULE->name, (xbus)->busname, ## __VA_ARGS__)
|
||||
|
||||
#define XPD_PRINTK(level, category, xpd, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \
|
||||
category, THIS_MODULE->name, \
|
||||
(xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__)
|
||||
#define XPD_PRINTK(level, category, xpd, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \
|
||||
category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__)
|
||||
|
||||
#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \
|
||||
category, THIS_MODULE->name, \
|
||||
(xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__)
|
||||
#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \
|
||||
category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__)
|
||||
|
||||
#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \
|
||||
category, THIS_MODULE->name, \
|
||||
(xbus)->busname, (unit), (port), ## __VA_ARGS__)
|
||||
#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \
|
||||
category, THIS_MODULE->name, (xbus)->busname, (unit), (port), ## __VA_ARGS__)
|
||||
|
||||
#define DBG(bits, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && \
|
||||
PRINTK(DEBUG, "-" #bits, "%s: " fmt, \
|
||||
__func__, ## __VA_ARGS__)))
|
||||
#define DBG(bits, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && PRINTK(DEBUG, "-" #bits, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
|
||||
#define INFO(fmt, ...) PRINTK(INFO, "", fmt, ## __VA_ARGS__)
|
||||
#define NOTICE(fmt, ...) PRINTK(NOTICE, "", fmt, ## __VA_ARGS__)
|
||||
#define WARNING(fmt, ...) PRINTK(WARNING, "", fmt, ## __VA_ARGS__)
|
||||
#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__)
|
||||
|
||||
#define XBUS_DBG(bits, xbus, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, \
|
||||
xbus, "%s: " fmt, __func__, ## __VA_ARGS__)))
|
||||
#define XBUS_INFO(xbus, fmt, ...) \
|
||||
XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__)
|
||||
#define XBUS_NOTICE(xbus, fmt, ...) \
|
||||
XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__)
|
||||
#define XBUS_ERR(xbus, fmt, ...) \
|
||||
XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__)
|
||||
#define XBUS_DBG(bits, xbus, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, xbus, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
|
||||
#define XBUS_INFO(xbus, fmt, ...) XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__)
|
||||
#define XBUS_NOTICE(xbus, fmt, ...) XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__)
|
||||
#define XBUS_ERR(xbus, fmt, ...) XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__)
|
||||
|
||||
#define XPD_DBG(bits, xpd, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, \
|
||||
xpd, "%s: " fmt, __func__, ## __VA_ARGS__)))
|
||||
#define XPD_INFO(xpd, fmt, ...) \
|
||||
XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_NOTICE(xpd, fmt, ...) \
|
||||
XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_WARNING(xpd, fmt, ...) \
|
||||
XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_ERR(xpd, fmt, ...) \
|
||||
XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_DBG(bits, xpd, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, xpd, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
|
||||
#define XPD_INFO(xpd, fmt, ...) XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_NOTICE(xpd, fmt, ...) XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_WARNING(xpd, fmt, ...) XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__)
|
||||
#define XPD_ERR(xpd, fmt, ...) XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__)
|
||||
|
||||
#define LINE_DBG(bits, xpd, pos, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, \
|
||||
xpd, pos, "%s: " fmt, __func__, ## __VA_ARGS__)))
|
||||
#define LINE_NOTICE(xpd, pos, fmt, ...) \
|
||||
LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__)
|
||||
#define LINE_ERR(xpd, pos, fmt, ...) \
|
||||
LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__)
|
||||
#define LINE_DBG(bits, xpd, pos, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, xpd, pos, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
|
||||
#define LINE_NOTICE(xpd, pos, fmt, ...) LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__)
|
||||
#define LINE_ERR(xpd, pos, fmt, ...) LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__)
|
||||
|
||||
#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && \
|
||||
PORT_PRINTK(DEBUG, "-" #bits, \
|
||||
xbus, unit, port, "%s: " fmt, __func__, ## __VA_ARGS__)))
|
||||
#define PORT_NOTICE(xbus, unit, port, fmt, ...) \
|
||||
PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__)
|
||||
#define PORT_ERR(xbus, unit, port, fmt, ...) \
|
||||
PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__)
|
||||
#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \
|
||||
((void)((debug & (DBG_ ## bits)) && PORT_PRINTK(DEBUG, "-" #bits, \
|
||||
xbus, unit, port, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
|
||||
#define PORT_NOTICE(xbus, unit, port, fmt, ...) PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__)
|
||||
#define PORT_ERR(xbus, unit, port, fmt, ...) PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Bits for debug
|
||||
@@ -115,98 +94,63 @@ void dump_poll(int debug, const char *msg, int poll);
|
||||
|
||||
static inline char *rxsig2str(enum dahdi_rxsig sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case DAHDI_RXSIG_ONHOOK:
|
||||
return "ONHOOK";
|
||||
case DAHDI_RXSIG_OFFHOOK:
|
||||
return "OFFHOOK";
|
||||
case DAHDI_RXSIG_START:
|
||||
return "START";
|
||||
case DAHDI_RXSIG_RING:
|
||||
return "RING";
|
||||
case DAHDI_RXSIG_INITIAL:
|
||||
return "INITIAL";
|
||||
switch(sig) {
|
||||
case DAHDI_RXSIG_ONHOOK: return "ONHOOK";
|
||||
case DAHDI_RXSIG_OFFHOOK: return "OFFHOOK";
|
||||
case DAHDI_RXSIG_START: return "START";
|
||||
case DAHDI_RXSIG_RING: return "RING";
|
||||
case DAHDI_RXSIG_INITIAL: return "INITIAL";
|
||||
}
|
||||
return "Unknown rxsig";
|
||||
}
|
||||
|
||||
static inline char *txsig2str(enum dahdi_txsig sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case DAHDI_TXSIG_ONHOOK:
|
||||
return "TXSIG_ONHOOK";
|
||||
case DAHDI_TXSIG_OFFHOOK:
|
||||
return "TXSIG_OFFHOOK";
|
||||
case DAHDI_TXSIG_START:
|
||||
return "TXSIG_START";
|
||||
case DAHDI_TXSIG_KEWL:
|
||||
return "TXSIG_KEWL"; /* Drop battery if possible */
|
||||
case DAHDI_TXSIG_TOTAL:
|
||||
break;
|
||||
switch(sig) {
|
||||
case DAHDI_TXSIG_ONHOOK: return "TXSIG_ONHOOK";
|
||||
case DAHDI_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK";
|
||||
case DAHDI_TXSIG_START: return "TXSIG_START";
|
||||
case DAHDI_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */
|
||||
case DAHDI_TXSIG_TOTAL: break;
|
||||
}
|
||||
return "Unknown txsig";
|
||||
}
|
||||
|
||||
static inline char *event2str(int event)
|
||||
{
|
||||
switch (event) {
|
||||
case DAHDI_EVENT_NONE:
|
||||
return "NONE";
|
||||
case DAHDI_EVENT_ONHOOK:
|
||||
return "ONHOOK";
|
||||
case DAHDI_EVENT_RINGOFFHOOK:
|
||||
return "RINGOFFHOOK";
|
||||
case DAHDI_EVENT_WINKFLASH:
|
||||
return "WINKFLASH";
|
||||
case DAHDI_EVENT_ALARM:
|
||||
return "ALARM";
|
||||
case DAHDI_EVENT_NOALARM:
|
||||
return "NOALARM";
|
||||
case DAHDI_EVENT_ABORT:
|
||||
return "ABORT";
|
||||
case DAHDI_EVENT_OVERRUN:
|
||||
return "OVERRUN";
|
||||
case DAHDI_EVENT_BADFCS:
|
||||
return "BADFCS";
|
||||
case DAHDI_EVENT_DIALCOMPLETE:
|
||||
return "DIALCOMPLETE";
|
||||
case DAHDI_EVENT_RINGERON:
|
||||
return "RINGERON";
|
||||
case DAHDI_EVENT_RINGEROFF:
|
||||
return "RINGEROFF";
|
||||
case DAHDI_EVENT_HOOKCOMPLETE:
|
||||
return "HOOKCOMPLETE";
|
||||
case DAHDI_EVENT_BITSCHANGED:
|
||||
return "BITSCHANGED";
|
||||
case DAHDI_EVENT_PULSE_START:
|
||||
return "PULSE_START";
|
||||
case DAHDI_EVENT_TIMER_EXPIRED:
|
||||
return "TIMER_EXPIRED";
|
||||
case DAHDI_EVENT_TIMER_PING:
|
||||
return "TIMER_PING";
|
||||
case DAHDI_EVENT_POLARITY:
|
||||
return "POLARITY";
|
||||
switch(event) {
|
||||
case DAHDI_EVENT_NONE: return "NONE";
|
||||
case DAHDI_EVENT_ONHOOK: return "ONHOOK";
|
||||
case DAHDI_EVENT_RINGOFFHOOK: return "RINGOFFHOOK";
|
||||
case DAHDI_EVENT_WINKFLASH: return "WINKFLASH";
|
||||
case DAHDI_EVENT_ALARM: return "ALARM";
|
||||
case DAHDI_EVENT_NOALARM: return "NOALARM";
|
||||
case DAHDI_EVENT_ABORT: return "ABORT";
|
||||
case DAHDI_EVENT_OVERRUN: return "OVERRUN";
|
||||
case DAHDI_EVENT_BADFCS: return "BADFCS";
|
||||
case DAHDI_EVENT_DIALCOMPLETE: return "DIALCOMPLETE";
|
||||
case DAHDI_EVENT_RINGERON: return "RINGERON";
|
||||
case DAHDI_EVENT_RINGEROFF: return "RINGEROFF";
|
||||
case DAHDI_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE";
|
||||
case DAHDI_EVENT_BITSCHANGED: return "BITSCHANGED";
|
||||
case DAHDI_EVENT_PULSE_START: return "PULSE_START";
|
||||
case DAHDI_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED";
|
||||
case DAHDI_EVENT_TIMER_PING: return "TIMER_PING";
|
||||
case DAHDI_EVENT_POLARITY: return "POLARITY";
|
||||
}
|
||||
return "Unknown event";
|
||||
}
|
||||
|
||||
static inline char *hookstate2str(int hookstate)
|
||||
{
|
||||
switch (hookstate) {
|
||||
case DAHDI_ONHOOK:
|
||||
return "DAHDI_ONHOOK";
|
||||
case DAHDI_START:
|
||||
return "DAHDI_START";
|
||||
case DAHDI_OFFHOOK:
|
||||
return "DAHDI_OFFHOOK";
|
||||
case DAHDI_WINK:
|
||||
return "DAHDI_WINK";
|
||||
case DAHDI_FLASH:
|
||||
return "DAHDI_FLASH";
|
||||
case DAHDI_RING:
|
||||
return "DAHDI_RING";
|
||||
case DAHDI_RINGOFF:
|
||||
return "DAHDI_RINGOFF";
|
||||
switch(hookstate) {
|
||||
case DAHDI_ONHOOK: return "DAHDI_ONHOOK";
|
||||
case DAHDI_START: return "DAHDI_START";
|
||||
case DAHDI_OFFHOOK: return "DAHDI_OFFHOOK";
|
||||
case DAHDI_WINK: return "DAHDI_WINK";
|
||||
case DAHDI_FLASH: return "DAHDI_FLASH";
|
||||
case DAHDI_RING: return "DAHDI_RING";
|
||||
case DAHDI_RINGOFF: return "DAHDI_RINGOFF";
|
||||
}
|
||||
return "Unknown hookstate";
|
||||
}
|
||||
@@ -215,42 +159,25 @@ static inline char *hookstate2str(int hookstate)
|
||||
static inline char *sig2str(int sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case DAHDI_SIG_FXSLS:
|
||||
return "FXSLS";
|
||||
case DAHDI_SIG_FXSKS:
|
||||
return "FXSKS";
|
||||
case DAHDI_SIG_FXSGS:
|
||||
return "FXSGS";
|
||||
case DAHDI_SIG_FXOLS:
|
||||
return "FXOLS";
|
||||
case DAHDI_SIG_FXOKS:
|
||||
return "FXOKS";
|
||||
case DAHDI_SIG_FXOGS:
|
||||
return "FXOGS";
|
||||
case DAHDI_SIG_EM:
|
||||
return "E&M";
|
||||
case DAHDI_SIG_EM_E1:
|
||||
return "E&M-E1";
|
||||
case DAHDI_SIG_CLEAR:
|
||||
return "Clear";
|
||||
case DAHDI_SIG_HDLCRAW:
|
||||
return "HDLCRAW";
|
||||
case DAHDI_SIG_HDLCFCS:
|
||||
return "HDLCFCS";
|
||||
case DAHDI_SIG_HDLCNET:
|
||||
return "HDLCNET";
|
||||
case DAHDI_SIG_SLAVE:
|
||||
return "Slave";
|
||||
case DAHDI_SIG_CAS:
|
||||
return "CAS";
|
||||
case DAHDI_SIG_DACS:
|
||||
return "DACS";
|
||||
case DAHDI_SIG_DACS_RBS:
|
||||
return "DACS+RBS";
|
||||
case DAHDI_SIG_SF:
|
||||
return "SF (ToneOnly)";
|
||||
case DAHDI_SIG_NONE:
|
||||
break;
|
||||
case DAHDI_SIG_FXSLS: return "FXSLS";
|
||||
case DAHDI_SIG_FXSKS: return "FXSKS";
|
||||
case DAHDI_SIG_FXSGS: return "FXSGS";
|
||||
case DAHDI_SIG_FXOLS: return "FXOLS";
|
||||
case DAHDI_SIG_FXOKS: return "FXOKS";
|
||||
case DAHDI_SIG_FXOGS: return "FXOGS";
|
||||
case DAHDI_SIG_EM: return "E&M";
|
||||
case DAHDI_SIG_EM_E1: return "E&M-E1";
|
||||
case DAHDI_SIG_CLEAR: return "Clear";
|
||||
case DAHDI_SIG_HDLCRAW: return "HDLCRAW";
|
||||
case DAHDI_SIG_HDLCFCS: return "HDLCFCS";
|
||||
case DAHDI_SIG_HDLCNET: return "HDLCNET";
|
||||
case DAHDI_SIG_SLAVE: return "Slave";
|
||||
case DAHDI_SIG_CAS: return "CAS";
|
||||
case DAHDI_SIG_DACS: return "DACS";
|
||||
case DAHDI_SIG_DACS_RBS: return "DACS+RBS";
|
||||
case DAHDI_SIG_SF: return "SF (ToneOnly)";
|
||||
case DAHDI_SIG_NONE:
|
||||
break;
|
||||
}
|
||||
return "Unconfigured";
|
||||
}
|
||||
@@ -258,25 +185,18 @@ static inline char *sig2str(int sig)
|
||||
static inline char *alarmbit2str(int alarmbit)
|
||||
{
|
||||
/* from dahdi/kernel.h */
|
||||
switch (1 << alarmbit) {
|
||||
case DAHDI_ALARM_NONE:
|
||||
return "NONE";
|
||||
case DAHDI_ALARM_RECOVER:
|
||||
return "RECOVER";
|
||||
case DAHDI_ALARM_LOOPBACK:
|
||||
return "LOOPBACK";
|
||||
case DAHDI_ALARM_YELLOW:
|
||||
return "YELLOW";
|
||||
case DAHDI_ALARM_RED:
|
||||
return "RED";
|
||||
case DAHDI_ALARM_BLUE:
|
||||
return "BLUE";
|
||||
case DAHDI_ALARM_NOTOPEN:
|
||||
return "NOTOPEN";
|
||||
switch(1 << alarmbit) {
|
||||
case DAHDI_ALARM_NONE: return "NONE";
|
||||
case DAHDI_ALARM_RECOVER: return "RECOVER";
|
||||
case DAHDI_ALARM_LOOPBACK: return "LOOPBACK";
|
||||
case DAHDI_ALARM_YELLOW: return "YELLOW";
|
||||
case DAHDI_ALARM_RED: return "RED";
|
||||
case DAHDI_ALARM_BLUE: return "BLUE";
|
||||
case DAHDI_ALARM_NOTOPEN: return "NOTOPEN";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
void alarm2str(int alarm, char *buf, int buflen);
|
||||
|
||||
#endif /* DAHDI_DEBUG_H */
|
||||
#endif /* DAHDI_DEBUG_H */
|
||||
|
||||
@@ -51,7 +51,7 @@ BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
|
||||
use XppConfig $init_dir;
|
||||
my $unit_id;
|
||||
my %opts;
|
||||
my $eeprom_release_201 = 0;
|
||||
my $vbat_48 = 0;
|
||||
|
||||
getopts('o:', \%opts);
|
||||
|
||||
@@ -94,7 +94,7 @@ if (-t STDERR) {
|
||||
}
|
||||
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
|
||||
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
|
||||
$eeprom_release_201 = 1;
|
||||
$vbat_48 = 1;
|
||||
}
|
||||
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
|
||||
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
|
||||
@@ -292,8 +292,8 @@ sub init_indirect_registers() {
|
||||
}
|
||||
|
||||
sub init_early_direct_regs() {
|
||||
my $lbv = ($eeprom_release_201) ? "20" : "10";
|
||||
my $vcm = ($eeprom_release_201) ? "02" : "03";
|
||||
my $lbv = ($vbat_48) ? "20" : "10";
|
||||
my $vcm = ($vbat_48) ? "02" : "03";
|
||||
|
||||
return write_to_slic_file("#
|
||||
* WD 08 00 # Audio Path Loopback Control
|
||||
|
||||
@@ -7,9 +7,7 @@ static int mmap_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
|
||||
}
|
||||
|
||||
static int mmap_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
static int mmap_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
||||
{
|
||||
envp[0] = buffer;
|
||||
envp[1] = NULL;
|
||||
@@ -35,6 +33,8 @@ static struct device mmap_bus = {
|
||||
.release = mmap_bus_release,
|
||||
};
|
||||
|
||||
|
||||
|
||||
int register_mmap_device(struct mmap_device *dev)
|
||||
{
|
||||
dev->dev.bus = &mmap_bus_type;
|
||||
@@ -43,12 +43,12 @@ int register_mmap_device(struct mmap_device *dev)
|
||||
strncpy(dev->dev.bus_id, dev->name, BUS_ID_SIZE);
|
||||
return device_register(&dev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(register_mmap_device);
|
||||
|
||||
void unregister_mmap_device(struct mmap_device *dev)
|
||||
{
|
||||
device_unregister(&dev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(register_mmap_device);
|
||||
EXPORT_SYMBOL(unregister_mmap_device);
|
||||
|
||||
int register_mmap_driver(struct mmap_driver *driver)
|
||||
@@ -56,12 +56,12 @@ int register_mmap_driver(struct mmap_driver *driver)
|
||||
driver->driver.bus = &mmap_bus_type;
|
||||
return driver_register(&driver->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(register_mmap_driver);
|
||||
|
||||
void unregister_mmap_driver(struct mmap_driver *driver)
|
||||
{
|
||||
driver_unregister(&driver->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(register_mmap_driver);
|
||||
EXPORT_SYMBOL(unregister_mmap_driver);
|
||||
|
||||
int register_mmap_bus(void)
|
||||
@@ -78,13 +78,13 @@ bus_reg:
|
||||
bus_type_reg:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(register_mmap_bus);
|
||||
|
||||
void unregister_mmap_bus(void)
|
||||
{
|
||||
device_unregister(&mmap_bus);
|
||||
bus_unregister(&mmap_bus_type);
|
||||
}
|
||||
EXPORT_SYMBOL(register_mmap_bus);
|
||||
EXPORT_SYMBOL(unregister_mmap_bus);
|
||||
|
||||
MODULE_AUTHOR("Alexander Landau <landau.alex@gmail.com>");
|
||||
|
||||
@@ -19,13 +19,11 @@
|
||||
#include "xframe_queue.h"
|
||||
|
||||
/* Check at compile time that sizeof(xframe_t) is a multiple of 4 */
|
||||
typedef char
|
||||
sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) ==
|
||||
0) * 2 - 1];
|
||||
typedef char sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) == 0) * 2 - 1];
|
||||
|
||||
#define ssync() __builtin_bfin_ssync()
|
||||
|
||||
//#define AB_IN_BUF PF5
|
||||
//#define AB_IN_BUF PF5
|
||||
/* firmware pins */
|
||||
#define DATA PG8
|
||||
#define NCONFIG PG9
|
||||
@@ -35,13 +33,13 @@ typedef char
|
||||
|
||||
#ifdef DEBUG_VIA_GPIO
|
||||
/*
|
||||
* For debugging we can use the following two pins.
|
||||
* For debugging we can use the following two pins.
|
||||
* These two pins are not used *after initialization*
|
||||
*/
|
||||
#define DEBUG_GPIO1 CONF_DONE
|
||||
#define DEBUG_GPIO2 NSTATUS
|
||||
|
||||
static int rx_intr_counter;
|
||||
static int rx_intr_counter;
|
||||
#endif
|
||||
|
||||
#define FPGA_RX_IRQ IRQ_PF7
|
||||
@@ -51,15 +49,9 @@ static int rx_intr_counter;
|
||||
#define END_OF_FRAME 0x0001
|
||||
#define GET_LEN 0x0002
|
||||
#define START_RD_BURST 0x0008
|
||||
/* stand alone Astribank without USB (Asterisk BlackFin Mode) */
|
||||
#define AS_BF_MODE 0x0010
|
||||
/*
|
||||
* all data between Astribank and USB routed
|
||||
* thru BF(EchoCanceler BlackFin Mode)
|
||||
*/
|
||||
#define EC_BF_MODE 0x0020
|
||||
/* Astribank worke with USB only (no BlackFin Mode) */
|
||||
#define NO_BF_MODE 0x0040
|
||||
#define AS_BF_MODE 0x0010 //stand alone Astribank without USB (Asterisk BlackFin Mode)
|
||||
#define EC_BF_MODE 0x0020 //all data between Astribank and USB routed thru BF(EchoCanceler BlackFin Mode)
|
||||
#define NO_BF_MODE 0x0040 //Astribank worke with USB only (no BlackFin Mode)
|
||||
#define SET_XA_DIR 0x0080
|
||||
#define GET_XPD_STS 0x0100
|
||||
#define GET_CHECKSUM 0x0200
|
||||
@@ -88,8 +80,9 @@ static void print_buffer(const char *msg, const char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
printk(KERN_ERR "%s", msg);
|
||||
for (i = 0; i < len; i++)
|
||||
for (i = 0; i < len; i++) {
|
||||
printk("%02X ", (unsigned char)buf[i]);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
@@ -103,8 +96,7 @@ static void update_counter(struct counter *c, struct timeval *tv1)
|
||||
c->intr_min = diff;
|
||||
if (c->intr_max < diff)
|
||||
c->intr_max = diff;
|
||||
c->intr_avg =
|
||||
(c->intr_avg * c->intr_count + diff) / (c->intr_count + 1);
|
||||
c->intr_avg = (c->intr_avg*c->intr_count + diff) / (c->intr_count+1);
|
||||
c->intr_count++;
|
||||
}
|
||||
|
||||
@@ -113,7 +105,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
|
||||
unsigned short rxcnt;
|
||||
xbus_t *xbus;
|
||||
xframe_t *xframe;
|
||||
__u8 *buf;
|
||||
byte *buf;
|
||||
bool in_use = 0;
|
||||
struct timeval tv1;
|
||||
|
||||
@@ -123,7 +115,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
|
||||
|
||||
xbus = xbus_num(global_xbus->num);
|
||||
BUG_ON(!xbus);
|
||||
if (!XBUS_GET(xbus)) {
|
||||
if(!XBUS_GET(xbus)) {
|
||||
if (printk_ratelimit())
|
||||
XBUS_ERR(xbus, "Dropping packet. Is shutting down.\n");
|
||||
goto out;
|
||||
@@ -137,7 +129,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
|
||||
NOTICE("Got %d bytes\n", rxcnt);
|
||||
goto out;
|
||||
}
|
||||
if (rxcnt >= XFRAME_DATASIZE) {
|
||||
if(rxcnt >= XFRAME_DATASIZE) {
|
||||
if (printk_ratelimit())
|
||||
ERR("Bad rxcnt=%d\n", rxcnt);
|
||||
goto out;
|
||||
@@ -161,22 +153,18 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
|
||||
outw(START_RD_BURST, FPGA_BASE_ADDR + 4);
|
||||
insw((unsigned long)FPGA_BASE_ADDR, buf, rxcnt / 2);
|
||||
#if 0
|
||||
for (count = 0; count < rxcnt; count += 2) {
|
||||
for (count = 0; count < rxcnt; count+=2) {
|
||||
unsigned short v = inw(FPGA_BASE_ADDR);
|
||||
buf[count] = v & 0xFF;
|
||||
buf[count + 1] = v >> 8;
|
||||
buf[count+1] = v >> 8;
|
||||
}
|
||||
#endif
|
||||
if (rxcnt & 1)
|
||||
buf[rxcnt - 1] = inw(FPGA_BASE_ADDR);
|
||||
/*
|
||||
* Sanity check: length of first packet in frame
|
||||
* should be no more than the frame length
|
||||
*/
|
||||
if (((buf[0] | (buf[1] << 8)) & 0x3FF) > rxcnt) {
|
||||
if (rxcnt & 1)
|
||||
buf[rxcnt-1] = inw(FPGA_BASE_ADDR);
|
||||
/* Sanity check: length of first packet in frame should be no more than the frame length */
|
||||
if (((buf[0] | (buf[1]<<8)) & 0x3FF) > rxcnt) {
|
||||
if (printk_ratelimit()) {
|
||||
ERR("Packet len=%d, frame len=%d\n",
|
||||
(buf[0] | (buf[1] << 8)) & 0x3FF, rxcnt);
|
||||
ERR("Packet len=%d, frame len=%d\n", (buf[0] | (buf[1]<<8)) & 0x3FF, rxcnt);
|
||||
print_buffer("16 bytes of packet: ", buf, 16);
|
||||
}
|
||||
goto free;
|
||||
@@ -211,7 +199,7 @@ static void send_buffer(unsigned char *buf, unsigned long len)
|
||||
print_buffer("Sent: ", buf, len);
|
||||
outsw((unsigned long)FPGA_BASE_ADDR, buf, len / 2);
|
||||
if (len & 1)
|
||||
outw((unsigned short)buf[len - 1], FPGA_BASE_ADDR);
|
||||
outw((unsigned short)buf[len-1], FPGA_BASE_ADDR);
|
||||
outw(END_OF_FRAME, FPGA_BASE_ADDR + 4);
|
||||
}
|
||||
|
||||
@@ -270,10 +258,7 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
|
||||
if (pcm && pcm_in_pool_count >= 1) {
|
||||
static int rate_limit;
|
||||
if ((rate_limit++ % 1000) == 0)
|
||||
XBUS_ERR(xbus,
|
||||
"Dropped PCM xframe "
|
||||
"(pcm_in_pool_count=%d).\n",
|
||||
pcm_in_pool_count);
|
||||
XBUS_ERR(xbus, "Dropped PCM xframe (pcm_in_pool_count=%d).\n", pcm_in_pool_count);
|
||||
FREE_SEND_XFRAME(xbus, xframe);
|
||||
pcm_dropped++;
|
||||
} else {
|
||||
@@ -281,9 +266,7 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
|
||||
static int rate_limit;
|
||||
spin_unlock_irqrestore(&tx_ready_lock, flags);
|
||||
if ((rate_limit++ % 1000) == 0)
|
||||
XBUS_ERR(xbus,
|
||||
"Dropped xframe. "
|
||||
"Cannot enqueue.\n");
|
||||
XBUS_ERR(xbus, "Dropped xframe. Cannot enqueue.\n");
|
||||
FREE_SEND_XFRAME(xbus, xframe);
|
||||
return -E2BIG;
|
||||
}
|
||||
@@ -301,12 +284,10 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
||||
if (!xframe) {
|
||||
static int rate_limit;
|
||||
if ((rate_limit++ % 1000) < 5)
|
||||
XBUS_ERR(xbus, "frame allocation failed (%d)\n",
|
||||
rate_limit);
|
||||
XBUS_ERR(xbus, "frame allocation failed (%d)\n", rate_limit);
|
||||
return NULL;
|
||||
}
|
||||
xframe_init(xbus, xframe, ((__u8 *)xframe) + sizeof(xframe_t),
|
||||
XFRAME_DATASIZE, xbus);
|
||||
xframe_init(xbus, xframe, ((byte*)xframe) + sizeof(xframe_t), XFRAME_DATASIZE, xbus);
|
||||
return xframe;
|
||||
}
|
||||
|
||||
@@ -335,26 +316,28 @@ static struct xbus_ops xmmap_ops = {
|
||||
|
||||
static int fill_proc_queue(char *p, struct xframe_queue *q)
|
||||
{
|
||||
int len;
|
||||
int len;
|
||||
|
||||
len = sprintf(p,
|
||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d "
|
||||
"worst_lag %02ld.%ld ms\n",
|
||||
q->name, q->steady_state_count, q->count, q->max_count,
|
||||
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
|
||||
q->worst_lag_usec % 1000);
|
||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
||||
q->name,
|
||||
q->steady_state_count,
|
||||
q->count,
|
||||
q->max_count,
|
||||
q->worst_count,
|
||||
q->overflows,
|
||||
q->worst_lag_usec / 1000,
|
||||
q->worst_lag_usec % 1000);
|
||||
xframe_queue_clearstats(q);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int fill_proc_counter(char *p, struct counter *c)
|
||||
{
|
||||
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min,
|
||||
c->intr_max, c->intr_avg, c->intr_count);
|
||||
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min, c->intr_max, c->intr_avg, c->intr_count);
|
||||
}
|
||||
|
||||
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
len += fill_proc_queue(page + len, &txpool);
|
||||
@@ -364,7 +347,7 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
|
||||
len += fill_proc_counter(page + len, &rx_counter);
|
||||
len += sprintf(page + len, "\ntx_counter:\n");
|
||||
len += fill_proc_counter(page + len, &tx_counter);
|
||||
if (len <= off + count) {
|
||||
if (len <= off+count) {
|
||||
*eof = 1;
|
||||
tx_counter.intr_min = rx_counter.intr_min = INT_MAX;
|
||||
tx_counter.intr_max = rx_counter.intr_max = 0;
|
||||
@@ -380,15 +363,14 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
|
||||
return len;
|
||||
}
|
||||
|
||||
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
|
||||
{
|
||||
int i = 0;
|
||||
char *txchunk, *p, *endp;
|
||||
|
||||
if (count >= XFRAME_DATASIZE * 3 + 10)
|
||||
if (count >= XFRAME_DATASIZE*3+10)
|
||||
return -EINVAL;
|
||||
p = txchunk = kmalloc(count + 1, GFP_KERNEL);
|
||||
p = txchunk = kmalloc(count+1, GFP_KERNEL);
|
||||
if (copy_from_user(txchunk, buffer, count)) {
|
||||
count = -EFAULT;
|
||||
goto out;
|
||||
@@ -397,15 +379,13 @@ static int xpp_mmap_proc_write(struct file *file, const char __user *buffer,
|
||||
|
||||
while (*p) {
|
||||
unsigned long value;
|
||||
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
|
||||
p++;
|
||||
if (*p == '\0')
|
||||
break;
|
||||
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++;
|
||||
if (*p == '\0') break;
|
||||
value = simple_strtoul(p, &endp, 16);
|
||||
if (endp == p || value > 0xFF) {
|
||||
INFO("%s: Bad input\n", __func__);
|
||||
count = -EINVAL;
|
||||
goto out;
|
||||
INFO("%s: Bad input\n", __FUNCTION__);
|
||||
count = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
p = endp;
|
||||
txchunk[i++] = (char)value;
|
||||
@@ -419,8 +399,8 @@ out:
|
||||
static struct mmap_driver astribank_driver = {
|
||||
.module = THIS_MODULE,
|
||||
.driver = {
|
||||
.name = "xpp_mmap",
|
||||
},
|
||||
.name = "xpp_mmap",
|
||||
},
|
||||
};
|
||||
|
||||
static struct mmap_device astribank_dev = {
|
||||
@@ -428,52 +408,42 @@ static struct mmap_device astribank_dev = {
|
||||
.driver = &astribank_driver,
|
||||
};
|
||||
|
||||
static int __init xpp_mmap_load_fpga(u8 * data, size_t size)
|
||||
static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
/* set data, nconfig and dclk to port out */
|
||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK);
|
||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK); //set data, nconfig and dclk to port out
|
||||
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DATA | NCONFIG | DCLK));
|
||||
/* set conf_done and nstatus to port in */
|
||||
bfin_write_PORTGIO_DIR(
|
||||
bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS));
|
||||
bfin_write_PORTGIO_INEN(
|
||||
bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
|
||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS));//set conf_done and nstatus to port in
|
||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
|
||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() | CONF_DONE | NSTATUS);
|
||||
|
||||
/* reset fpga during configuration holds nCONFIG low */
|
||||
bfin_write_PORTGIO_CLEAR(NCONFIG);
|
||||
udelay(40); /* Tcfg ~40us delay */
|
||||
/* transition nCONFIG to high - reset end. */
|
||||
bfin_write_PORTGIO_SET(NCONFIG);
|
||||
udelay(40); /* Tcf2ck ~40us delay */
|
||||
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
|
||||
udelay(40); //Tcfg ~40us delay
|
||||
bfin_write_PORTGIO_SET(NCONFIG); //transition nCONFIG to high - reset end.
|
||||
udelay(40); //Tcf2ck ~40us delay
|
||||
if (!(bfin_read_PORTGIO() & NSTATUS))
|
||||
return -EIO; /* report reset faill - Tcf2st1 pass */
|
||||
return -EIO; //report reset faill - Tcf2st1 pass
|
||||
|
||||
#if 0
|
||||
if (!(bfin_read_PORTGIO() & CONF_DONE))
|
||||
return -EIO;
|
||||
#endif
|
||||
bfin_write_PORTGIO_CLEAR(DCLK);
|
||||
for (i = 0; i < size; i++) { /* loop EP2OUT buffer data to FPGA */
|
||||
for (i=0; i<size; i++) { // loop EP2OUT buffer data to FPGA
|
||||
int j;
|
||||
u8 __u8 = data[i];
|
||||
/*
|
||||
* Send the configuration data through the DATA0 pin
|
||||
* one bit at a time.
|
||||
*/
|
||||
for (j = 0; j < 8; j++)
|
||||
u8 byte = data[i];
|
||||
for (j=0; j<8; j++) //send the configuration data through the DATA0 pin one bit at a time.
|
||||
{
|
||||
if (__u8 & 1)
|
||||
if (byte & 1)
|
||||
bfin_write_PORTGIO_SET(DATA);
|
||||
else
|
||||
bfin_write_PORTGIO_CLEAR(DATA);
|
||||
__u8 >>= 1;
|
||||
byte >>= 1;
|
||||
bfin_write_PORTGIO_SET(DCLK);
|
||||
bfin_write_PORTGIO_CLEAR(DCLK);
|
||||
}
|
||||
if (!(bfin_read_PORTGIO() & NSTATUS))
|
||||
return -EIO; /* check the nSTATUS */
|
||||
return -EIO; //check the nSTATUS
|
||||
}
|
||||
bfin_write_PORTGIO_CLEAR(DATA);
|
||||
udelay(1);
|
||||
@@ -485,29 +455,20 @@ static int __init xpp_mmap_load_fpga(u8 * data, size_t size)
|
||||
* some pins that were used only during initialization
|
||||
* to be used for debugging from now on.
|
||||
*/
|
||||
/* set to port out */
|
||||
bfin_write_PORTGIO_DIR(
|
||||
bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2);
|
||||
bfin_write_PORTG_FER(bfin_read_PORTG_FER() &
|
||||
~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() &
|
||||
~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2); //set to port out
|
||||
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
||||
#endif
|
||||
udelay(40); /* tCD2UM - CONF_DONE high to user mode */
|
||||
udelay(40); //tCD2UM - CONF_DONE high to user mode
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit xpp_mmap_unload_fpga(void)
|
||||
{
|
||||
/* reset fpga during configuration holds nCONFIG low */
|
||||
bfin_write_PORTGIO_CLEAR(NCONFIG);
|
||||
udelay(40); /* Tcfg ~40us delay */
|
||||
/* disable output pin */
|
||||
bfin_write_PORTGIO_DIR(
|
||||
bfin_read_PORTGIO_DIR() & ~(DATA | NCONFIG | DCLK));
|
||||
/* disable input buffer */
|
||||
bfin_write_PORTGIO_INEN(
|
||||
bfin_read_PORTGIO_INEN() & ~(CONF_DONE | NSTATUS));
|
||||
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
|
||||
udelay(40); //Tcfg ~40us delay
|
||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~( DATA | NCONFIG | DCLK)); //disable output pin
|
||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~( CONF_DONE | NSTATUS));//disable input buffer
|
||||
INFO("FPGA Firmware unloaded\n");
|
||||
}
|
||||
|
||||
@@ -515,8 +476,7 @@ static int __init xpp_mmap_load_firmware(void)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
if ((ret =
|
||||
request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
|
||||
if ((ret = request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
|
||||
return ret;
|
||||
xpp_mmap_load_fpga(fw->data, fw->size);
|
||||
release_firmware(fw);
|
||||
@@ -538,33 +498,29 @@ static int __init xpp_mmap_init(void)
|
||||
ERR("xpp_mmap_load_firmware() failed, errno=%d\n", ret);
|
||||
goto fail_fw;
|
||||
}
|
||||
|
||||
if ((ret =
|
||||
request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING,
|
||||
"xpp_mmap_rx", NULL)) < 0) {
|
||||
|
||||
if ((ret = request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_rx", NULL)) < 0) {
|
||||
ERR("Unable to attach to RX interrupt %d\n", FPGA_RX_IRQ);
|
||||
goto fail_irq_rx;
|
||||
}
|
||||
if ((ret =
|
||||
request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING,
|
||||
"xpp_mmap_tx", NULL)) < 0) {
|
||||
if ((ret = request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_tx", NULL)) < 0) {
|
||||
ERR("Unable to attach to TX interrupt %d\n", FPGA_TX_IRQ);
|
||||
goto fail_irq_tx;
|
||||
}
|
||||
if (!request_region((resource_size_t) FPGA_BASE_ADDR, 8, "xpp_mmap")) {
|
||||
if (!request_region((resource_size_t)FPGA_BASE_ADDR, 8, "xpp_mmap")) {
|
||||
ERR("Unable to request memory region at %p\n", FPGA_BASE_ADDR);
|
||||
goto fail_region;
|
||||
}
|
||||
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
|
||||
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
|
||||
|
||||
xframe_cache =
|
||||
kmem_cache_create("xframe_cache",
|
||||
sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||
NULL,
|
||||
xframe_cache = kmem_cache_create("xframe_cache",
|
||||
sizeof(xframe_t) + XFRAME_DATASIZE,
|
||||
0, 0,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
|
||||
NULL,
|
||||
#endif
|
||||
NULL);
|
||||
if (!xframe_cache) {
|
||||
NULL);
|
||||
if(!xframe_cache) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_cache;
|
||||
}
|
||||
@@ -576,11 +532,9 @@ static int __init xpp_mmap_init(void)
|
||||
}
|
||||
strncpy(global_xbus->connector, "mmap", XBUS_DESCLEN);
|
||||
strncpy(global_xbus->label, "mmap:0", LABEL_SIZE);
|
||||
|
||||
|
||||
xframe_queue_init(&txpool, 10, 200, "mmap_txpool", global_xbus);
|
||||
if (!
|
||||
(proc_entry =
|
||||
create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
|
||||
if (!(proc_entry = create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
|
||||
ERR("create_proc_entry() failed\n");
|
||||
ret = -EINVAL;
|
||||
goto fail_proc;
|
||||
@@ -598,7 +552,7 @@ fail_proc:
|
||||
fail_xbus:
|
||||
kmem_cache_destroy(xframe_cache);
|
||||
fail_cache:
|
||||
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
|
||||
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
|
||||
fail_region:
|
||||
free_irq(FPGA_TX_IRQ, NULL);
|
||||
fail_irq_tx:
|
||||
@@ -625,7 +579,7 @@ static void __exit xpp_mmap_exit(void)
|
||||
xbus_disconnect(xbus);
|
||||
kmem_cache_destroy(xframe_cache);
|
||||
|
||||
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
|
||||
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
|
||||
free_irq(FPGA_RX_IRQ, NULL);
|
||||
free_irq(FPGA_TX_IRQ, NULL);
|
||||
|
||||
|
||||
@@ -20,26 +20,31 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
# warning "This module is tested only with 2.6 kernels"
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/parport.h>
|
||||
#include "parport_debug.h"
|
||||
|
||||
static struct parport *debug_sync_parport;
|
||||
static int parport_toggles[8]; /* 8 bit flip-flop */
|
||||
static struct parport *debug_sync_parport = NULL;
|
||||
static int parport_toggles[8]; /* 8 bit flip-flop */
|
||||
|
||||
void flip_parport_bit(unsigned char bitnum)
|
||||
{
|
||||
static unsigned char last_value;
|
||||
static unsigned char last_value;
|
||||
DEFINE_SPINLOCK(lock);
|
||||
unsigned long flags;
|
||||
unsigned char mask;
|
||||
unsigned char value;
|
||||
unsigned long flags;
|
||||
unsigned char mask;
|
||||
unsigned char value;
|
||||
|
||||
if (!debug_sync_parport) {
|
||||
if (printk_ratelimit()) {
|
||||
if(!debug_sync_parport) {
|
||||
if(printk_ratelimit()) {
|
||||
printk(KERN_NOTICE "%s: no debug parallel port\n",
|
||||
THIS_MODULE->name);
|
||||
THIS_MODULE->name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -47,7 +52,7 @@ void flip_parport_bit(unsigned char bitnum)
|
||||
mask = 1 << bitnum;
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
value = last_value & ~mask;
|
||||
if (parport_toggles[bitnum] % 2) /* square wave */
|
||||
if(parport_toggles[bitnum] % 2) /* square wave */
|
||||
value |= mask;
|
||||
last_value = value;
|
||||
parport_toggles[bitnum]++;
|
||||
@@ -58,11 +63,10 @@ EXPORT_SYMBOL(flip_parport_bit);
|
||||
|
||||
static void parport_attach(struct parport *port)
|
||||
{
|
||||
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name,
|
||||
port->name);
|
||||
if (debug_sync_parport) {
|
||||
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, port->name);
|
||||
if(debug_sync_parport) {
|
||||
printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n",
|
||||
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
||||
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
||||
return;
|
||||
}
|
||||
parport_get_port(port);
|
||||
@@ -72,16 +76,16 @@ static void parport_attach(struct parport *port)
|
||||
static void parport_detach(struct parport *port)
|
||||
{
|
||||
printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name);
|
||||
if (debug_sync_parport != port) {
|
||||
if(debug_sync_parport != port) {
|
||||
printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n",
|
||||
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
||||
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
||||
return;
|
||||
}
|
||||
parport_put_port(debug_sync_parport);
|
||||
debug_sync_parport = NULL;
|
||||
}
|
||||
|
||||
static struct parport_driver debug_parport_driver = {
|
||||
static struct parport_driver debug_parport_driver = {
|
||||
.name = "parport_debug",
|
||||
.attach = parport_attach,
|
||||
.detach = parport_detach,
|
||||
@@ -89,7 +93,7 @@ static struct parport_driver debug_parport_driver = {
|
||||
|
||||
int __init parallel_dbg_init(void)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
ret = parport_register_driver(&debug_parport_driver);
|
||||
return ret;
|
||||
|
||||
@@ -28,4 +28,4 @@ void flip_parport_bit(unsigned char bitnum);
|
||||
#define flip_parport_bit(bitnum)
|
||||
#endif
|
||||
|
||||
#endif /* PARPORT_DEBUG_H */
|
||||
#endif /* PARPORT_DEBUG_H */
|
||||
|
||||
@@ -3,35 +3,30 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (sizeof(fxo_modes) / sizeof(struct fxo_mode)); i++) {
|
||||
if (fxo_modes[i].name == NULL)
|
||||
break;
|
||||
int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20;
|
||||
char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = "";
|
||||
|
||||
|
||||
for (i=0; i<(sizeof(fxo_modes)/sizeof(struct fxo_mode)); i++) {
|
||||
if (fxo_modes[i].name == NULL) break;
|
||||
int reg16=0, reg26=0, reg30=0, reg31=0x20;
|
||||
char ring_osc[BUFSIZ]="", ring_x[BUFSIZ] = "";
|
||||
|
||||
reg16 |= (fxo_modes[i].ohs << 6);
|
||||
reg16 |= (fxo_modes[i].rz << 1);
|
||||
reg16 |= (fxo_modes[i].rt);
|
||||
|
||||
|
||||
reg26 |= (fxo_modes[i].dcv << 6);
|
||||
reg26 |= (fxo_modes[i].mini << 4);
|
||||
reg26 |= (fxo_modes[i].ilim << 1);
|
||||
|
||||
|
||||
reg30 = (fxo_modes[i].acim);
|
||||
|
||||
|
||||
reg31 |= (fxo_modes[i].ohs2 << 3);
|
||||
|
||||
if (fxo_modes[i].ring_osc)
|
||||
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X",
|
||||
fxo_modes[i].ring_osc);
|
||||
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X", fxo_modes[i].ring_osc);
|
||||
if (fxo_modes[i].ring_x)
|
||||
snprintf(ring_x, BUFSIZ, "ring_x=%04X",
|
||||
fxo_modes[i].ring_x);
|
||||
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\t"
|
||||
"reg31=%02X\t%s\t%s\n",
|
||||
fxo_modes[i].name, reg16, reg26, reg30, reg31,
|
||||
ring_osc, ring_x);
|
||||
snprintf(ring_x, BUFSIZ, "ring_x=%04X", fxo_modes[i].ring_x);
|
||||
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\treg31=%02X\t%s\t%s\n",
|
||||
fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc, ring_x);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,10 +39,10 @@ struct xbus_workqueue;
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct xbus_ops {
|
||||
int (*xframe_send_pcm) (xbus_t *xbus, xframe_t *xframe);
|
||||
int (*xframe_send_cmd) (xbus_t *xbus, xframe_t *xframe);
|
||||
xframe_t *(*alloc_xframe) (xbus_t *xbus, gfp_t gfp_flags);
|
||||
void (*free_xframe) (xbus_t *xbus, xframe_t *xframe);
|
||||
int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe);
|
||||
int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe);
|
||||
xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags);
|
||||
void (*free_xframe)(xbus_t *xbus, xframe_t *xframe);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -67,11 +67,19 @@ enum {
|
||||
|
||||
/* yucky, make an instance so we can size it... */
|
||||
static struct xbus_counters {
|
||||
char *name;
|
||||
char *name;
|
||||
} xbus_counters[] = {
|
||||
C_(UNITS), C_(TX_XFRAME_PCM), C_(RX_XFRAME_PCM), C_(TX_PACK_PCM),
|
||||
C_(RX_PACK_PCM), C_(TX_BYTES), C_(RX_BYTES),
|
||||
C_(TX_PCM_FRAG), C_(RX_CMD), C_(TX_CMD),};
|
||||
C_(UNITS),
|
||||
C_(TX_XFRAME_PCM),
|
||||
C_(RX_XFRAME_PCM),
|
||||
C_(TX_PACK_PCM),
|
||||
C_(RX_PACK_PCM),
|
||||
C_(TX_BYTES),
|
||||
C_(RX_BYTES),
|
||||
C_(TX_PCM_FRAG),
|
||||
C_(RX_CMD),
|
||||
C_(TX_CMD),
|
||||
};
|
||||
|
||||
#undef C_
|
||||
|
||||
@@ -91,17 +99,17 @@ enum xbus_state {
|
||||
const char *xbus_statename(enum xbus_state st);
|
||||
|
||||
struct xbus_transport {
|
||||
struct xbus_ops *ops;
|
||||
void *priv;
|
||||
struct device *transport_device;
|
||||
ushort max_send_size;
|
||||
enum xbus_state xbus_state;
|
||||
unsigned long transport_flags;
|
||||
spinlock_t state_lock;
|
||||
atomic_t transport_refcount;
|
||||
wait_queue_head_t transport_unused;
|
||||
spinlock_t lock;
|
||||
char model_string[MAX_ENV_STR];
|
||||
struct xbus_ops *ops;
|
||||
void *priv;
|
||||
struct device *transport_device;
|
||||
ushort max_send_size;
|
||||
enum xbus_state xbus_state;
|
||||
unsigned long transport_flags;
|
||||
spinlock_t state_lock;
|
||||
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)
|
||||
@@ -110,8 +118,7 @@ struct xbus_transport {
|
||||
#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL)
|
||||
|
||||
#define XBUS_FLAG_CONNECTED 0
|
||||
#define XBUS_FLAGS(xbus, flg) \
|
||||
test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
|
||||
#define XBUS_FLAGS(xbus, flg) test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
|
||||
|
||||
struct xbus_ops *transportops_get(xbus_t *xbus);
|
||||
void transportops_put(xbus_t *xbus);
|
||||
@@ -120,39 +127,35 @@ void transportops_put(xbus_t *xbus);
|
||||
* Encapsulate all poll related data of a single xbus.
|
||||
*/
|
||||
struct xbus_workqueue {
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct xpds_init_work;
|
||||
bool xpds_init_done;
|
||||
struct list_head card_list;
|
||||
int num_units;
|
||||
int num_units_initialized;
|
||||
wait_queue_head_t wait_for_xpd_initialization;
|
||||
spinlock_t worker_lock;
|
||||
struct semaphore running_initialization;
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct xpds_init_work;
|
||||
bool xpds_init_done;
|
||||
struct list_head card_list;
|
||||
int num_units;
|
||||
int num_units_initialized;
|
||||
wait_queue_head_t wait_for_xpd_initialization;
|
||||
spinlock_t worker_lock;
|
||||
struct semaphore running_initialization;
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocate/Free an xframe from pools of empty xframes.
|
||||
* Calls to {get, put}_xframe are wrapped in
|
||||
* Calls to {get,put}_xframe are wrapped in
|
||||
* the macros bellow, so we take/return it
|
||||
* to the correct pool.
|
||||
*/
|
||||
xframe_t *get_xframe(struct xframe_queue *q);
|
||||
void put_xframe(struct xframe_queue *q, xframe_t *xframe);
|
||||
|
||||
#define ALLOC_SEND_XFRAME(xbus) \
|
||||
get_xframe(&(xbus)->send_pool)
|
||||
#define ALLOC_RECV_XFRAME(xbus) \
|
||||
get_xframe(&(xbus)->receive_pool)
|
||||
#define FREE_SEND_XFRAME(xbus, xframe) \
|
||||
put_xframe(&(xbus)->send_pool, (xframe))
|
||||
#define FREE_RECV_XFRAME(xbus, xframe) \
|
||||
put_xframe(&(xbus)->receive_pool, (xframe))
|
||||
#define ALLOC_SEND_XFRAME(xbus) get_xframe(&(xbus)->send_pool)
|
||||
#define ALLOC_RECV_XFRAME(xbus) get_xframe(&(xbus)->receive_pool)
|
||||
#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe))
|
||||
#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe))
|
||||
|
||||
xbus_t *xbus_num(uint num);
|
||||
xbus_t *get_xbus(const char *msg, uint num);
|
||||
void put_xbus(const char *msg, xbus_t *xbus);
|
||||
int refcount_xbus(xbus_t *xbus);
|
||||
xbus_t *xbus_num(uint num);
|
||||
xbus_t *get_xbus(const char *msg, uint num);
|
||||
void put_xbus(const char *msg, xbus_t *xbus);
|
||||
int refcount_xbus(xbus_t *xbus);
|
||||
|
||||
/*
|
||||
* Echo canceller related data
|
||||
@@ -160,17 +163,17 @@ int refcount_xbus(xbus_t *xbus);
|
||||
#define ECHO_TIMESLOTS 128
|
||||
|
||||
struct echoops {
|
||||
int (*ec_set) (xpd_t *xpd, int pos, bool on);
|
||||
int (*ec_get) (xpd_t *xpd, int pos);
|
||||
int (*ec_update) (xbus_t *xbus);
|
||||
void (*ec_dump) (xbus_t *xbus);
|
||||
int (*ec_set)(xpd_t *xpd, int pos, bool on);
|
||||
int (*ec_get)(xpd_t *xpd, int pos);
|
||||
int (*ec_update)(xbus_t *xbus);
|
||||
void (*ec_dump)(xbus_t *xbus);
|
||||
};
|
||||
|
||||
struct xbus_echo_state {
|
||||
const struct echoops *echoops;
|
||||
__u8 timeslots[ECHO_TIMESLOTS];
|
||||
int xpd_idx;
|
||||
struct device_attribute *da[MAX_XPDS];
|
||||
const struct echoops *echoops;
|
||||
byte timeslots[ECHO_TIMESLOTS];
|
||||
int xpd_idx;
|
||||
struct device_attribute *da[MAX_XPDS];
|
||||
};
|
||||
#define ECHOOPS(xbus) ((xbus)->echo_state.echoops)
|
||||
#define EC_METHOD(name, xbus) (ECHOOPS(xbus)->name)
|
||||
@@ -180,128 +183,125 @@ struct xbus_echo_state {
|
||||
* An xbus is a transport layer for Xorcom Protocol commands
|
||||
*/
|
||||
struct xbus {
|
||||
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
|
||||
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
|
||||
|
||||
/* low-level bus drivers set these 2 fields */
|
||||
char connector[XBUS_DESCLEN];
|
||||
char label[LABEL_SIZE];
|
||||
__u8 revision; /* Protocol revision */
|
||||
struct xbus_transport transport;
|
||||
struct dahdi_device *ddev;
|
||||
char connector[XBUS_DESCLEN];
|
||||
char label[LABEL_SIZE];
|
||||
byte revision; /* Protocol revision */
|
||||
struct xbus_transport transport;
|
||||
|
||||
int num;
|
||||
struct xpd *xpds[MAX_XPDS];
|
||||
struct xbus_echo_state echo_state;
|
||||
int num;
|
||||
struct xpd *xpds[MAX_XPDS];
|
||||
struct xbus_echo_state echo_state;
|
||||
|
||||
int command_tick_counter;
|
||||
int usec_nosend; /* Firmware flow control */
|
||||
struct xframe_queue command_queue;
|
||||
wait_queue_head_t command_queue_empty;
|
||||
int command_tick_counter;
|
||||
int usec_nosend; /* Firmware flow control */
|
||||
struct xframe_queue command_queue;
|
||||
wait_queue_head_t command_queue_empty;
|
||||
|
||||
struct xframe_queue send_pool; /* empty xframes for send */
|
||||
struct xframe_queue receive_pool; /* empty xframes for receive */
|
||||
struct xframe_queue send_pool; /* empty xframes for send */
|
||||
struct xframe_queue receive_pool; /* empty xframes for receive */
|
||||
|
||||
/* tasklet processing */
|
||||
struct xframe_queue receive_queue;
|
||||
struct tasklet_struct receive_tasklet;
|
||||
int cpu_rcv_intr[NR_CPUS];
|
||||
int cpu_rcv_tasklet[NR_CPUS];
|
||||
struct xframe_queue receive_queue;
|
||||
struct tasklet_struct receive_tasklet;
|
||||
int cpu_rcv_intr[NR_CPUS];
|
||||
int cpu_rcv_tasklet[NR_CPUS];
|
||||
|
||||
struct quirks {
|
||||
unsigned int has_fxo:1;
|
||||
unsigned int has_digital_span:1;
|
||||
} quirks;
|
||||
bool self_ticking;
|
||||
enum sync_mode sync_mode;
|
||||
} quirks;
|
||||
bool self_ticking;
|
||||
enum sync_mode sync_mode;
|
||||
/* Managed by low-level drivers: */
|
||||
enum sync_mode sync_mode_default;
|
||||
struct timer_list command_timer;
|
||||
unsigned int xbus_frag_count;
|
||||
struct xframe_queue pcm_tospan;
|
||||
enum sync_mode sync_mode_default;
|
||||
struct timer_list command_timer;
|
||||
unsigned int xbus_frag_count;
|
||||
struct xframe_queue pcm_tospan;
|
||||
|
||||
struct xpp_ticker ticker; /* for tick rate */
|
||||
struct xpp_drift drift; /* for tick offset */
|
||||
struct xpp_ticker ticker; /* for tick rate */
|
||||
struct xpp_drift drift; /* for tick offset */
|
||||
|
||||
atomic_t pcm_rx_counter;
|
||||
unsigned int global_counter;
|
||||
atomic_t pcm_rx_counter;
|
||||
unsigned int global_counter;
|
||||
|
||||
/* Device-Model */
|
||||
struct device astribank;
|
||||
struct device astribank;
|
||||
#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
|
||||
struct kref kref;
|
||||
struct kref kref;
|
||||
#define kref_to_xbus(k) container_of(k, struct xbus, kref)
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t lock;
|
||||
|
||||
/* PCM metrics */
|
||||
struct timeval last_tx_sync;
|
||||
struct timeval last_rx_sync;
|
||||
unsigned long max_tx_sync;
|
||||
unsigned long min_tx_sync;
|
||||
unsigned long max_rx_sync;
|
||||
unsigned long min_rx_sync;
|
||||
unsigned long max_rx_process; /* packet processing time (usec) */
|
||||
struct timeval last_tx_sync;
|
||||
struct timeval last_rx_sync;
|
||||
unsigned long max_tx_sync;
|
||||
unsigned long min_tx_sync;
|
||||
unsigned long max_rx_sync;
|
||||
unsigned long min_rx_sync;
|
||||
unsigned long max_rx_process; /* packet processing time (usec) */
|
||||
#ifdef SAMPLE_TICKS
|
||||
#define SAMPLE_SIZE 1000
|
||||
int sample_ticks[SAMPLE_SIZE];
|
||||
bool sample_running;
|
||||
int sample_pos;
|
||||
int sample_ticks[SAMPLE_SIZE];
|
||||
bool sample_running;
|
||||
int sample_pos;
|
||||
#endif
|
||||
|
||||
struct xbus_workqueue worker;
|
||||
struct xbus_workqueue worker;
|
||||
|
||||
/*
|
||||
* Sync adjustment
|
||||
*/
|
||||
int sync_adjustment;
|
||||
int sync_adjustment_offset;
|
||||
long pll_updated_at;
|
||||
int sync_adjustment;
|
||||
int sync_adjustment_offset;
|
||||
long pll_updated_at;
|
||||
|
||||
atomic_t num_xpds;
|
||||
atomic_t num_xpds;
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_xbus_dir;
|
||||
struct proc_dir_entry *proc_xbus_summary;
|
||||
struct proc_dir_entry *proc_xbus_dir;
|
||||
struct proc_dir_entry *proc_xbus_summary;
|
||||
#ifdef PROTOCOL_DEBUG
|
||||
struct proc_dir_entry *proc_xbus_command;
|
||||
struct proc_dir_entry *proc_xbus_command;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* statistics */
|
||||
int counters[XBUS_COUNTER_MAX];
|
||||
int counters[XBUS_COUNTER_MAX];
|
||||
};
|
||||
#endif
|
||||
|
||||
#define XFRAME_MAGIC 123456L
|
||||
|
||||
struct xframe {
|
||||
unsigned long xframe_magic;
|
||||
struct list_head frame_list;
|
||||
atomic_t frame_len;
|
||||
xbus_t *xbus;
|
||||
struct timeval tv_created;
|
||||
struct timeval tv_queued;
|
||||
struct timeval tv_submitted;
|
||||
struct timeval tv_received;
|
||||
unsigned long xframe_magic;
|
||||
struct list_head frame_list;
|
||||
atomic_t frame_len;
|
||||
xbus_t *xbus;
|
||||
struct timeval tv_created;
|
||||
struct timeval tv_queued;
|
||||
struct timeval tv_submitted;
|
||||
struct timeval tv_received;
|
||||
/* filled by transport layer */
|
||||
size_t frame_maxlen;
|
||||
__u8 *packets; /* max XFRAME_DATASIZE */
|
||||
__u8 *first_free;
|
||||
int usec_towait; /* prevent overflowing AB */
|
||||
void *priv;
|
||||
size_t frame_maxlen;
|
||||
byte *packets; /* max XFRAME_DATASIZE */
|
||||
byte *first_free;
|
||||
int usec_towait; /* prevent overflowing AB */
|
||||
void *priv;
|
||||
};
|
||||
|
||||
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
|
||||
void *priv);
|
||||
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv);
|
||||
|
||||
#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len)
|
||||
|
||||
int xbus_core_init(void); /* Initializer */
|
||||
void xbus_core_shutdown(void); /* Terminator */
|
||||
int xbus_core_init(void); /* Initializer */
|
||||
void xbus_core_shutdown(void); /* Terminator */
|
||||
|
||||
/* Frame handling */
|
||||
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe,
|
||||
int debug);
|
||||
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug);
|
||||
int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
|
||||
|
||||
/*
|
||||
@@ -315,45 +315,54 @@ xpacket_t *xframe_next_packet(xframe_t *xframe, int len);
|
||||
/*
|
||||
* Map: unit+subunit <--> index in xbus->xpds[]
|
||||
*/
|
||||
#define XPD_IDX(unit, subunit) ((unit) * MAX_SUBUNIT + (subunit))
|
||||
#define XPD_IDX(unit,subunit) ((unit) * MAX_SUBUNIT + (subunit))
|
||||
#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
|
||||
#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
|
||||
|
||||
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
|
||||
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
|
||||
int xbus_check_unique(xbus_t *xbus);
|
||||
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
|
||||
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
|
||||
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
|
||||
struct device *transport_device, void *priv);
|
||||
void xbus_free(xbus_t *xbus);
|
||||
int xbus_connect(xbus_t *xbus);
|
||||
int xbus_activate(xbus_t *xbus);
|
||||
void xbus_deactivate(xbus_t *xbus);
|
||||
void xbus_disconnect(xbus_t *xbus);
|
||||
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
|
||||
int xbus_process_worker(xbus_t *xbus);
|
||||
int waitfor_xpds(xbus_t *xbus, char *buf);
|
||||
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
|
||||
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
|
||||
int xbus_check_unique(xbus_t *xbus);
|
||||
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
|
||||
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
|
||||
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv);
|
||||
void xbus_free(xbus_t *xbus);
|
||||
int xbus_connect(xbus_t *xbus);
|
||||
int xbus_activate(xbus_t *xbus);
|
||||
void xbus_deactivate(xbus_t *xbus);
|
||||
void xbus_disconnect(xbus_t *xbus);
|
||||
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
|
||||
int xbus_process_worker(xbus_t *xbus);
|
||||
int waitfor_xpds(xbus_t *xbus, char *buf);
|
||||
|
||||
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
|
||||
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
|
||||
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
|
||||
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
|
||||
|
||||
/* sysfs */
|
||||
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 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);
|
||||
void xbus_sysfs_transport_remove(xbus_t *xbus);
|
||||
int xbus_sysfs_create(xbus_t *xbus);
|
||||
void xbus_sysfs_remove(xbus_t *xbus);
|
||||
|
||||
int xpp_driver_init(void);
|
||||
void xpp_driver_exit(void);
|
||||
int xbus_sysfs_transport_create(xbus_t *xbus);
|
||||
void xbus_sysfs_transport_remove(xbus_t *xbus);
|
||||
int xbus_sysfs_create(xbus_t *xbus);
|
||||
void xbus_sysfs_remove(xbus_t *xbus);
|
||||
#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
|
||||
|
||||
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
|
||||
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
|
||||
|
||||
#endif /* XBUS_CORE_H */
|
||||
|
||||
#endif /* XBUS_CORE_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,10 +33,10 @@
|
||||
#ifdef __KERNEL__
|
||||
|
||||
enum sync_mode {
|
||||
SYNC_MODE_NONE = 0x00,
|
||||
SYNC_MODE_AB = 0x01, /* Astribank sync */
|
||||
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
|
||||
SYNC_MODE_QUERY = 0x80,
|
||||
SYNC_MODE_NONE = 0x00,
|
||||
SYNC_MODE_AB = 0x01, /* Astribank sync */
|
||||
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
|
||||
SYNC_MODE_QUERY = 0x80,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -46,7 +46,7 @@ enum sync_mode {
|
||||
* time representations.
|
||||
*/
|
||||
struct xpp_timestamp {
|
||||
struct timeval tv;
|
||||
struct timeval tv;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -58,12 +58,12 @@ struct xpp_timestamp {
|
||||
* from other dahdi devices).
|
||||
*/
|
||||
struct xpp_ticker { /* for rate calculation */
|
||||
int count;
|
||||
int cycle;
|
||||
struct xpp_timestamp first_sample;
|
||||
struct xpp_timestamp last_sample;
|
||||
int tick_period; /* usec/tick */
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
int cycle;
|
||||
struct xpp_timestamp first_sample;
|
||||
struct xpp_timestamp last_sample;
|
||||
int tick_period; /* usec/tick */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -71,65 +71,66 @@ struct xpp_ticker { /* for rate calculation */
|
||||
* xbus ticker to a reference ticker.
|
||||
*/
|
||||
struct xpp_drift {
|
||||
int delta_tick; /* from ref_ticker */
|
||||
int lost_ticks; /* occurances */
|
||||
int lost_tick_count;
|
||||
int sync_inaccuracy;
|
||||
struct xpp_timestamp last_lost_tick;
|
||||
long delta_sum;
|
||||
int offset_prev;
|
||||
int offset_range;
|
||||
int offset_min;
|
||||
int offset_max;
|
||||
int min_speed;
|
||||
int max_speed;
|
||||
spinlock_t lock;
|
||||
int delta_tick; /* from ref_ticker */
|
||||
int lost_ticks; /* occurances */
|
||||
int lost_tick_count;
|
||||
int sync_inaccuracy;
|
||||
struct xpp_timestamp last_lost_tick;
|
||||
long delta_sum;
|
||||
int offset_prev;
|
||||
int offset_range;
|
||||
int offset_min;
|
||||
int offset_max;
|
||||
int min_speed;
|
||||
int max_speed;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
void xpp_drift_init(xbus_t *xbus);
|
||||
|
||||
static inline long usec_diff(const struct timeval *tv1,
|
||||
const struct timeval *tv2)
|
||||
static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
long diff_sec;
|
||||
long diff_usec;
|
||||
long diff_sec;
|
||||
long diff_usec;
|
||||
|
||||
diff_sec = tv1->tv_sec - tv2->tv_sec;
|
||||
diff_usec = tv1->tv_usec - tv2->tv_usec;
|
||||
return diff_sec * 1000000 + diff_usec;
|
||||
}
|
||||
|
||||
int xbus_pcm_init(void *top);
|
||||
void xbus_pcm_shutdown(void);
|
||||
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
|
||||
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
|
||||
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
|
||||
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
|
||||
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
|
||||
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
|
||||
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
|
||||
int generic_timing_priority(xpd_t *xpd);
|
||||
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
|
||||
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
|
||||
void fill_beep(u_char *buf, int num, int duration);
|
||||
const char *sync_mode_name(enum sync_mode mode);
|
||||
void xbus_set_command_timer(xbus_t *xbus, bool on);
|
||||
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
|
||||
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
|
||||
int xbus_command_queue_tick(xbus_t *xbus);
|
||||
void xbus_reset_counters(xbus_t *xbus);
|
||||
void elect_syncer(const char *msg);
|
||||
int exec_sync_command(const char *buf, size_t count);
|
||||
int fill_sync_string(char *buf, size_t count);
|
||||
|
||||
int xbus_pcm_init(void *top);
|
||||
void xbus_pcm_shutdown(void);
|
||||
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
|
||||
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
|
||||
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
|
||||
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
|
||||
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
|
||||
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
|
||||
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
|
||||
int generic_timing_priority(xpd_t *xpd);
|
||||
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
|
||||
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
|
||||
void fill_beep(u_char *buf, int num, int duration);
|
||||
const char *sync_mode_name(enum sync_mode mode);
|
||||
void xbus_set_command_timer(xbus_t *xbus, bool on);
|
||||
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
|
||||
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
|
||||
int xbus_command_queue_tick(xbus_t *xbus);
|
||||
void xbus_reset_counters(xbus_t *xbus);
|
||||
void elect_syncer(const char *msg);
|
||||
int exec_sync_command(const char *buf, size_t count);
|
||||
int fill_sync_string(char *buf, size_t count);
|
||||
#ifdef DAHDI_SYNC_TICK
|
||||
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
|
||||
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_PCMTX
|
||||
extern int pcmtx;
|
||||
extern int pcmtx_chan;
|
||||
extern int pcmtx;
|
||||
extern int pcmtx_chan;
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* XBUS_PCM_H */
|
||||
|
||||
#endif /* XBUS_PCM_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,21 +34,18 @@
|
||||
/* This is to enable user-space programs to include this. */
|
||||
|
||||
#include <stdint.h>
|
||||
typedef uint8_t __u8;
|
||||
typedef uint8_t __u8;
|
||||
typedef uint32_t __u32;
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define DBG(fmt, ...) printf("DBG: %s: " fmt, __func__, ## __VA_ARGS__)
|
||||
#define DBG(fmt, ...) printf("DBG: %s: " fmt, __FUNCTION__, ## __VA_ARGS__)
|
||||
#define INFO(fmt, ...) printf("INFO: " fmt, ## __VA_ARGS__)
|
||||
#define NOTICE(fmt, ...) printf("NOTICE: " fmt, ## __VA_ARGS__)
|
||||
#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__)
|
||||
#define __user
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next;
|
||||
struct list_head *prev;
|
||||
};
|
||||
struct list_head { struct list_head *next; struct list_head *prev; };
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,15 +53,15 @@ struct list_head {
|
||||
|
||||
#define ALL_LINES ((lineno_t)-1)
|
||||
|
||||
#ifndef BIT /* added in 2.6.24 */
|
||||
#ifndef BIT /* added in 2.6.24 */
|
||||
#define BIT(i) (1UL << (i))
|
||||
#endif
|
||||
#define BIT_SET(x, i) ((x) |= BIT(i))
|
||||
#define BIT_CLR(x, i) ((x) &= ~BIT(i))
|
||||
#define IS_SET(x, i) (((x) & BIT(i)) != 0)
|
||||
#define BIT_SET(x,i) ((x) |= BIT(i))
|
||||
#define BIT_CLR(x,i) ((x) &= ~BIT(i))
|
||||
#define IS_SET(x,i) (((x) & BIT(i)) != 0)
|
||||
#define BITMASK(i) (((u64)1 << (i)) - 1)
|
||||
|
||||
#define MAX_PROC_WRITE 100 /* Longest write allowed to our /proc files */
|
||||
#define MAX_PROC_WRITE 100 /* Largest buffer we allow writing our /proc files */
|
||||
#define CHANNELS_PERXPD 32 /* Depends on xpp_line_t and protocol fields */
|
||||
|
||||
#define MAX_SPANNAME 20 /* From dahdi/kernel.h */
|
||||
@@ -80,8 +77,7 @@ struct list_head {
|
||||
#define UNIT_BITS 3 /* Bit for Astribank unit number */
|
||||
#define SUBUNIT_BITS 3 /* Bit for Astribank subunit number */
|
||||
|
||||
/* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
|
||||
#define MAX_UNIT (1 << UNIT_BITS)
|
||||
#define MAX_UNIT (1 << UNIT_BITS) /* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
|
||||
#define MAX_SUBUNIT (1 << SUBUNIT_BITS) /* 8 port BRI */
|
||||
|
||||
/*
|
||||
@@ -99,70 +95,74 @@ struct list_head {
|
||||
|
||||
#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
|
||||
|
||||
#define CHAN_BITS 5 /* 0-31 for E1 */
|
||||
#define CHAN_BITS 5 /* 0-31 for E1 */
|
||||
|
||||
typedef char *charp;
|
||||
typedef char *charp;
|
||||
typedef unsigned char byte;
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* Kernel versions... */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
|
||||
#define KMEM_CACHE_T kmem_cache_t
|
||||
#else
|
||||
#else
|
||||
#define KMEM_CACHE_T struct kmem_cache
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define KZALLOC(size, gfp) my_kzalloc(size, gfp)
|
||||
#define KZFREE(p) \
|
||||
do { \
|
||||
memset((p), 0, sizeof(*(p))); \
|
||||
kfree(p); \
|
||||
} while (0);
|
||||
#define KZFREE(p) do { \
|
||||
memset((p), 0, sizeof(*(p))); \
|
||||
kfree(p); \
|
||||
} while(0);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
ssize_t name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count)
|
||||
/*
|
||||
* 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,10)
|
||||
#define OLD_HOTPLUG_SUPPORT_269// for way 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)
|
||||
#else
|
||||
#define DEVICE_ATTR_READER(name, dev, buf) \
|
||||
#define DEVICE_ATTR_READER(name,dev,buf) \
|
||||
ssize_t name(struct device *dev, char *buf)
|
||||
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
|
||||
#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
|
||||
ssize_t name(struct device *dev, const char *buf, size_t count)
|
||||
#endif
|
||||
#define DRIVER_ATTR_READER(name, drv, buf) \
|
||||
#define DRIVER_ATTR_READER(name,drv,buf) \
|
||||
ssize_t name(struct device_driver *drv, char * buf)
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
|
||||
#define SET_PROC_DIRENTRY_OWNER(p) \
|
||||
do { \
|
||||
(p)->owner = THIS_MODULE; \
|
||||
} while (0);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
|
||||
#define SET_PROC_DIRENTRY_OWNER(p) do { (p)->owner = THIS_MODULE; } while(0);
|
||||
#else
|
||||
#define SET_PROC_DIRENTRY_OWNER(p) do { } while (0);
|
||||
#define SET_PROC_DIRENTRY_OWNER(p) do { } while(0);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
/* Also don't define this for later RHEL >= 5.2 . hex_asc is from the
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
/* Also don't define this for later RHEL >= 5.2 . hex_asc is from the
|
||||
* same linux-2.6-net-infrastructure-updates-to-mac80211-iwl4965.patch
|
||||
* as is the bool typedef. */
|
||||
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 18) || !defined(hex_asc)
|
||||
typedef int bool;
|
||||
#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,18) || ! defined(hex_asc)
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
typedef int bool;
|
||||
typedef int bool;
|
||||
#endif
|
||||
typedef struct xbus xbus_t;
|
||||
typedef struct xpd xpd_t;
|
||||
typedef struct xframe xframe_t;
|
||||
typedef struct xpacket xpacket_t;
|
||||
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
|
||||
typedef __u8 lineno_t;
|
||||
typedef __u8 xportno_t;
|
||||
typedef struct xbus xbus_t;
|
||||
typedef struct xpd xpd_t;
|
||||
typedef struct xframe xframe_t;
|
||||
typedef struct xpacket xpacket_t;
|
||||
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
|
||||
typedef byte lineno_t;
|
||||
typedef byte xportno_t;
|
||||
|
||||
#define PORT_BROADCAST 255
|
||||
|
||||
#endif /* XDEFS_H */
|
||||
#endif /* XDEFS_H */
|
||||
|
||||
@@ -7,9 +7,7 @@ extern int debug;
|
||||
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags);
|
||||
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe);
|
||||
|
||||
void xframe_queue_init(struct xframe_queue *q,
|
||||
unsigned int steady_state_count, unsigned int max_count,
|
||||
const char *name, void *priv)
|
||||
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv)
|
||||
{
|
||||
memset(q, 0, sizeof(*q));
|
||||
spin_lock_init(&q->lock);
|
||||
@@ -19,60 +17,61 @@ void xframe_queue_init(struct xframe_queue *q,
|
||||
q->name = name;
|
||||
q->priv = priv;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_queue_init);
|
||||
|
||||
void xframe_queue_clearstats(struct xframe_queue *q)
|
||||
{
|
||||
q->worst_count = 0;
|
||||
//q->overflows = 0; /* Never clear overflows */
|
||||
//q->overflows = 0; /* Never clear overflows */
|
||||
q->worst_lag_usec = 0L;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_queue_clearstats);
|
||||
|
||||
static void __xframe_dump_queue(struct xframe_queue *q)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
int i = 0;
|
||||
char prefix[30];
|
||||
struct timeval now;
|
||||
xframe_t *xframe;
|
||||
int i = 0;
|
||||
char prefix[30];
|
||||
struct timeval now;
|
||||
|
||||
do_gettimeofday(&now);
|
||||
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
|
||||
THIS_MODULE->name, q->name);
|
||||
THIS_MODULE->name,
|
||||
q->name);
|
||||
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
|
||||
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
|
||||
long usec = usec_diff(&now, &xframe->tv_queued);
|
||||
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
|
||||
long usec = usec_diff(&now, &xframe->tv_queued);
|
||||
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
|
||||
i++, usec / 1000, usec % 1000);
|
||||
i++, usec / 1000, usec % 1000);
|
||||
dump_packet(prefix, pack, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
||||
{
|
||||
int ret = 1;
|
||||
static int overflow_cnt;
|
||||
int ret = 1;
|
||||
static int overflow_cnt = 0;
|
||||
|
||||
if (unlikely(q->disabled)) {
|
||||
if(unlikely(q->disabled)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if (q->count >= q->max_count) {
|
||||
if(q->count >= q->max_count) {
|
||||
q->overflows++;
|
||||
if ((overflow_cnt++ % 1000) < 5) {
|
||||
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d "
|
||||
"worst %3d, overflows %3d "
|
||||
"worst_lag %02ld.%ld ms\n",
|
||||
q->name, q->steady_state_count, q->count,
|
||||
q->max_count, q->worst_count, q->overflows,
|
||||
q->worst_lag_usec / 1000,
|
||||
q->worst_lag_usec % 1000);
|
||||
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
||||
q->name,
|
||||
q->steady_state_count,
|
||||
q->count,
|
||||
q->max_count,
|
||||
q->worst_count,
|
||||
q->overflows,
|
||||
q->worst_lag_usec / 1000,
|
||||
q->worst_lag_usec % 1000);
|
||||
__xframe_dump_queue(q);
|
||||
}
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if (++q->count > q->worst_count)
|
||||
if(++q->count > q->worst_count)
|
||||
q->worst_count = q->count;
|
||||
list_add_tail(&xframe->frame_list, &q->head);
|
||||
do_gettimeofday(&xframe->tv_queued);
|
||||
@@ -82,36 +81,33 @@ out:
|
||||
|
||||
bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&q->lock, flags);
|
||||
ret = __xframe_enqueue(q, xframe);
|
||||
spin_unlock_irqrestore(&q->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_enqueue);
|
||||
|
||||
static xframe_t *__xframe_dequeue(struct xframe_queue *q)
|
||||
{
|
||||
xframe_t *frm = NULL;
|
||||
struct list_head *h;
|
||||
struct timeval now;
|
||||
unsigned long usec_lag;
|
||||
xframe_t *frm = NULL;
|
||||
struct list_head *h;
|
||||
struct timeval now;
|
||||
unsigned long usec_lag;
|
||||
|
||||
if (list_empty(&q->head))
|
||||
if(list_empty(&q->head))
|
||||
goto out;
|
||||
h = q->head.next;
|
||||
list_del_init(h);
|
||||
--q->count;
|
||||
frm = list_entry(h, xframe_t, frame_list);
|
||||
do_gettimeofday(&now);
|
||||
usec_lag =
|
||||
(now.tv_sec - frm->tv_queued.tv_sec) * 1000 * 1000 + (now.tv_usec -
|
||||
frm->
|
||||
tv_queued.
|
||||
tv_usec);
|
||||
if (q->worst_lag_usec < usec_lag)
|
||||
usec_lag =
|
||||
(now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 +
|
||||
(now.tv_usec - frm->tv_queued.tv_usec);
|
||||
if(q->worst_lag_usec < usec_lag)
|
||||
q->worst_lag_usec = usec_lag;
|
||||
out:
|
||||
return frm;
|
||||
@@ -119,68 +115,59 @@ out:
|
||||
|
||||
xframe_t *xframe_dequeue(struct xframe_queue *q)
|
||||
{
|
||||
unsigned long flags;
|
||||
xframe_t *frm;
|
||||
unsigned long flags;
|
||||
xframe_t *frm;
|
||||
|
||||
spin_lock_irqsave(&q->lock, flags);
|
||||
frm = __xframe_dequeue(q);
|
||||
spin_unlock_irqrestore(&q->lock, flags);
|
||||
return frm;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_dequeue);
|
||||
|
||||
void xframe_queue_disable(struct xframe_queue *q, bool disabled)
|
||||
{
|
||||
q->disabled = disabled;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_queue_disable);
|
||||
|
||||
void xframe_queue_clear(struct xframe_queue *q)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
xbus_t *xbus = q->priv;
|
||||
int i = 0;
|
||||
xframe_t *xframe;
|
||||
xbus_t *xbus = q->priv;
|
||||
int i = 0;
|
||||
|
||||
xframe_queue_disable(q, 1);
|
||||
while ((xframe = xframe_dequeue(q)) != NULL) {
|
||||
while((xframe = xframe_dequeue(q)) != NULL) {
|
||||
transport_free_xframe(xbus, xframe);
|
||||
i++;
|
||||
}
|
||||
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n",
|
||||
q->name, i);
|
||||
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n", q->name, i);
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_queue_clear);
|
||||
|
||||
uint xframe_queue_count(struct xframe_queue *q)
|
||||
{
|
||||
return q->count;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_queue_count);
|
||||
|
||||
/*------------------------- Frame Alloc/Dealloc --------------------*/
|
||||
|
||||
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
||||
{
|
||||
struct xbus_ops *ops;
|
||||
xframe_t *xframe;
|
||||
unsigned long flags;
|
||||
struct xbus_ops *ops;
|
||||
xframe_t *xframe;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
ops = transportops_get(xbus);
|
||||
if (unlikely(!ops)) {
|
||||
if(unlikely(!ops)) {
|
||||
XBUS_ERR(xbus, "Missing transport\n");
|
||||
return NULL;
|
||||
}
|
||||
spin_lock_irqsave(&xbus->transport.lock, flags);
|
||||
#if 0
|
||||
XBUS_INFO(xbus, "%s (transport_refcount=%d)\n",
|
||||
__func__, atomic_read(&xbus->transport.transport_refcount));
|
||||
#endif
|
||||
//XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
|
||||
xframe = ops->alloc_xframe(xbus, gfp_flags);
|
||||
if (!xframe) {
|
||||
if(!xframe) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 3001) == 0)
|
||||
if((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus,
|
||||
"Failed xframe allocation from transport (%d)\n",
|
||||
rate_limit);
|
||||
@@ -193,17 +180,14 @@ static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
||||
|
||||
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
|
||||
{
|
||||
struct xbus_ops *ops;
|
||||
unsigned long flags;
|
||||
struct xbus_ops *ops;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(!xbus);
|
||||
ops = xbus->transport.ops;
|
||||
BUG_ON(!ops);
|
||||
spin_lock_irqsave(&xbus->transport.lock, flags);
|
||||
#if 0
|
||||
XBUS_INFO(xbus, "%s (transport_refcount=%d)\n",
|
||||
__func__, atomic_read(&xbus->transport.transport_refcount));
|
||||
#endif
|
||||
//XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
|
||||
ops->free_xframe(xbus, xframe);
|
||||
transportops_put(xbus);
|
||||
spin_unlock_irqrestore(&xbus->transport.lock, flags);
|
||||
@@ -211,48 +195,45 @@ static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
|
||||
|
||||
static bool xframe_queue_adjust(struct xframe_queue *q)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
xframe_t *xframe;
|
||||
int delta;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
xbus_t *xbus;
|
||||
xframe_t *xframe;
|
||||
int delta;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(!q);
|
||||
xbus = q->priv;
|
||||
BUG_ON(!xbus);
|
||||
spin_lock_irqsave(&q->lock, flags);
|
||||
delta = q->count - q->steady_state_count;
|
||||
if (delta < -XFRAME_QUEUE_MARGIN) {
|
||||
if(delta < -XFRAME_QUEUE_MARGIN) {
|
||||
/* Increase pool by one frame */
|
||||
//XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta);
|
||||
xframe = transport_alloc_xframe(xbus, GFP_ATOMIC);
|
||||
if (!xframe) {
|
||||
if(!xframe) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s: failed frame allocation\n",
|
||||
q->name);
|
||||
if((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name);
|
||||
goto out;
|
||||
}
|
||||
if (!__xframe_enqueue(q, xframe)) {
|
||||
if(!__xframe_enqueue(q, xframe)) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s: failed enqueueing frame\n",
|
||||
q->name);
|
||||
if((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name);
|
||||
transport_free_xframe(xbus, xframe);
|
||||
goto out;
|
||||
}
|
||||
} else if (delta > XFRAME_QUEUE_MARGIN) {
|
||||
} else if(delta > XFRAME_QUEUE_MARGIN) {
|
||||
/* Decrease pool by one frame */
|
||||
//XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta);
|
||||
xframe = __xframe_dequeue(q);
|
||||
if (!xframe) {
|
||||
if(!xframe) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s: failed dequeueing frame\n",
|
||||
q->name);
|
||||
if((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name);
|
||||
goto out;
|
||||
}
|
||||
transport_free_xframe(xbus, xframe);
|
||||
@@ -265,20 +246,19 @@ out:
|
||||
|
||||
xframe_t *get_xframe(struct xframe_queue *q)
|
||||
{
|
||||
xframe_t *xframe;
|
||||
xbus_t *xbus;
|
||||
xframe_t *xframe;
|
||||
xbus_t *xbus;
|
||||
|
||||
BUG_ON(!q);
|
||||
xbus = (xbus_t *)q->priv;
|
||||
BUG_ON(!xbus);
|
||||
xframe_queue_adjust(q);
|
||||
xframe = xframe_dequeue(q);
|
||||
if (!xframe) {
|
||||
if(!xframe) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name,
|
||||
rate_limit);
|
||||
if((rate_limit++ % 3001) == 0)
|
||||
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit);
|
||||
return NULL;
|
||||
}
|
||||
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
||||
@@ -293,25 +273,34 @@ xframe_t *get_xframe(struct xframe_queue *q)
|
||||
*
|
||||
* memset(xframe->packets, 0, xframe->frame_maxlen);
|
||||
*/
|
||||
//XBUS_INFO(xbus, "%s\n", __func__);
|
||||
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
|
||||
return xframe;
|
||||
}
|
||||
EXPORT_SYMBOL(get_xframe);
|
||||
|
||||
void put_xframe(struct xframe_queue *q, xframe_t *xframe)
|
||||
{
|
||||
xbus_t *xbus;
|
||||
xbus_t *xbus;
|
||||
|
||||
BUG_ON(!q);
|
||||
xbus = (xbus_t *)q->priv;
|
||||
BUG_ON(!xbus);
|
||||
//XBUS_INFO(xbus, "%s\n", __func__);
|
||||
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
|
||||
BUG_ON(!TRANSPORT_EXIST(xbus));
|
||||
if (unlikely(!xframe_enqueue(q, xframe))) {
|
||||
if(unlikely(!xframe_enqueue(q, xframe))) {
|
||||
XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name);
|
||||
transport_free_xframe(xbus, xframe);
|
||||
return;
|
||||
}
|
||||
xframe_queue_adjust(q);
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(xframe_queue_init);
|
||||
EXPORT_SYMBOL(xframe_queue_clearstats);
|
||||
EXPORT_SYMBOL(xframe_enqueue);
|
||||
EXPORT_SYMBOL(xframe_dequeue);
|
||||
EXPORT_SYMBOL(xframe_queue_disable);
|
||||
EXPORT_SYMBOL(xframe_queue_clear);
|
||||
EXPORT_SYMBOL(xframe_queue_count);
|
||||
EXPORT_SYMBOL(get_xframe);
|
||||
EXPORT_SYMBOL(put_xframe);
|
||||
|
||||
@@ -8,22 +8,23 @@
|
||||
#define XFRAME_QUEUE_MARGIN 10
|
||||
|
||||
struct xframe_queue {
|
||||
struct list_head head;
|
||||
bool disabled;
|
||||
unsigned int count;
|
||||
unsigned int max_count;
|
||||
unsigned int steady_state_count;
|
||||
spinlock_t lock;
|
||||
const char *name;
|
||||
void *priv;
|
||||
struct list_head head;
|
||||
bool disabled;
|
||||
unsigned int count;
|
||||
unsigned int max_count;
|
||||
unsigned int steady_state_count;
|
||||
spinlock_t lock;
|
||||
const char *name;
|
||||
void *priv;
|
||||
/* statistics */
|
||||
unsigned int worst_count;
|
||||
unsigned int overflows;
|
||||
unsigned long worst_lag_usec; /* since xframe creation */
|
||||
unsigned int worst_count;
|
||||
unsigned int overflows;
|
||||
unsigned long worst_lag_usec; /* since xframe creation */
|
||||
};
|
||||
|
||||
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
|
||||
unsigned int max_count, const char *name, void *priv);
|
||||
void xframe_queue_init(struct xframe_queue *q,
|
||||
unsigned int steady_state_count, unsigned int max_count,
|
||||
const char *name, void *priv);
|
||||
__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe);
|
||||
__must_check xframe_t *xframe_dequeue(struct xframe_queue *q);
|
||||
void xframe_queue_clearstats(struct xframe_queue *q);
|
||||
@@ -31,4 +32,4 @@ void xframe_queue_disable(struct xframe_queue *q, bool disabled);
|
||||
void xframe_queue_clear(struct xframe_queue *q);
|
||||
uint xframe_queue_count(struct xframe_queue *q);
|
||||
|
||||
#endif /* XFRAME_QUEUE_ */
|
||||
#endif /* XFRAME_QUEUE_ */
|
||||
|
||||
@@ -31,17 +31,23 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/atomic.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
||||
#include <linux/semaphore.h>
|
||||
#else
|
||||
#include <asm/semaphore.h>
|
||||
#endif
|
||||
#include <linux/moduleparam.h>
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#include <dahdi/kernel.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#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)
|
||||
typedef unsigned gfp_t; /* Added in 2.6.14 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
|
||||
/*
|
||||
@@ -49,9 +55,9 @@
|
||||
* bool is now defined as a proper boolean type (gcc _Bool)
|
||||
* but the command line parsing framework handles it as int.
|
||||
*/
|
||||
#define DEF_PARM_BOOL(name, init, perm, desc) \
|
||||
int name = init; \
|
||||
module_param(name, bool, perm); \
|
||||
#define DEF_PARM_BOOL(name,init,perm,desc) \
|
||||
int name = init; \
|
||||
module_param(name, bool, perm); \
|
||||
MODULE_PARM_DESC(name, desc " [default " #init "]")
|
||||
#else
|
||||
#define DEF_PARM_BOOL(name, init, perm, desc) \
|
||||
@@ -60,31 +66,43 @@
|
||||
MODULE_PARM_DESC(name, desc " [default " #init "]")
|
||||
#endif
|
||||
|
||||
#define DEF_PARM(type, name, init, perm, desc) \
|
||||
type name = init; \
|
||||
module_param(name, type, perm); \
|
||||
#define DEF_PARM(type,name,init,perm,desc) \
|
||||
type name = init; \
|
||||
module_param(name, type, perm); \
|
||||
MODULE_PARM_DESC(name, desc " [default " #init "]")
|
||||
|
||||
#define DEF_ARRAY(type, name, count, init, desc) \
|
||||
unsigned int name ## _num_values; \
|
||||
type name[count] = {[0 ... ((count)-1)] = init}; \
|
||||
module_param_array(name, type, &name ## _num_values, 0644); \
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
|
||||
/*
|
||||
* Old 2.6 kernels had module_param_array() macro that receive the counter
|
||||
* by value.
|
||||
*/
|
||||
#define DEF_ARRAY(type,name,count,init,desc) \
|
||||
unsigned int name ## _num_values; \
|
||||
type name[count] = { [0 ... ((count)-1)] = (init) }; \
|
||||
module_param_array(name, type, name ## _num_values, 0644); \
|
||||
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
|
||||
#endif // __KERNEL__
|
||||
#else
|
||||
#define DEF_ARRAY(type,name,count,init,desc) \
|
||||
unsigned int name ## _num_values; \
|
||||
type name[count] = {[0 ... ((count)-1)] = init}; \
|
||||
module_param_array(name, type, &name ## _num_values, 0644); \
|
||||
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
|
||||
#endif
|
||||
#endif // __KERNEL__
|
||||
|
||||
#define CARD_DESC_MAGIC 0xca9dde5c
|
||||
|
||||
struct card_desc_struct {
|
||||
struct list_head card_list;
|
||||
u32 magic;
|
||||
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
|
||||
__u8 subtype;
|
||||
struct xpd_addr xpd_addr;
|
||||
__u8 numchips;
|
||||
__u8 ports_per_chip;
|
||||
__u8 ports;
|
||||
__u8 port_dir;
|
||||
struct xpd_addr ec_addr; /* echo canceler address */
|
||||
struct card_desc_struct {
|
||||
struct list_head card_list;
|
||||
u32 magic;
|
||||
byte type; /* LSB: 1 - to_phone, 0 - to_line */
|
||||
byte subtype;
|
||||
struct xpd_addr xpd_addr;
|
||||
byte numchips;
|
||||
byte ports_per_chip;
|
||||
byte ports;
|
||||
byte port_dir;
|
||||
struct xpd_addr ec_addr; /* echo canceler address */
|
||||
};
|
||||
|
||||
typedef enum xpd_direction {
|
||||
@@ -109,9 +127,12 @@ enum {
|
||||
|
||||
/* yucky, make an instance so we can size it... */
|
||||
static struct xpd_counters {
|
||||
char *name;
|
||||
char *name;
|
||||
} xpd_counters[] = {
|
||||
C_(PCM_READ), C_(PCM_WRITE), C_(RECV_ERRORS),};
|
||||
C_(PCM_READ),
|
||||
C_(PCM_WRITE),
|
||||
C_(RECV_ERRORS),
|
||||
};
|
||||
|
||||
#undef C_
|
||||
|
||||
@@ -124,43 +145,43 @@ enum xpd_state {
|
||||
XPD_STATE_NOHW,
|
||||
};
|
||||
|
||||
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
|
||||
const char *xpd_statename(enum xpd_state st);
|
||||
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
|
||||
const char *xpd_statename(enum xpd_state st);
|
||||
|
||||
#define PHONEDEV(xpd) ((xpd)->phonedev)
|
||||
#define IS_PHONEDEV(xpd) (PHONEDEV(xpd).phoneops)
|
||||
|
||||
struct phonedev {
|
||||
const struct phoneops *phoneops; /* Card level operations */
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan *chans[32];
|
||||
#define XPD_CHAN(xpd, chan) (PHONEDEV(xpd).chans[(chan)])
|
||||
const struct phoneops *phoneops; /* Card level operations */
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan *chans[32];
|
||||
#define XPD_CHAN(xpd,chan) (PHONEDEV(xpd).chans[(chan)])
|
||||
struct dahdi_echocan_state *ec[32];
|
||||
|
||||
int channels;
|
||||
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
|
||||
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
|
||||
xpp_line_t offhook_state; /* chip state: 0 - ONHOOK, 1 - OFHOOK */
|
||||
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
|
||||
int channels;
|
||||
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
|
||||
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
|
||||
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
|
||||
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
|
||||
/* Voice Mail Waiting Indication: */
|
||||
unsigned int msg_waiting[CHANNELS_PERXPD];
|
||||
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
|
||||
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
|
||||
xpp_line_t digital_signalling; /* BRI signalling channels */
|
||||
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
|
||||
unsigned int msg_waiting[CHANNELS_PERXPD];
|
||||
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
|
||||
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
|
||||
xpp_line_t digital_signalling; /* BRI signalling channels */
|
||||
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
|
||||
|
||||
/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
|
||||
spinlock_t lock_recompute_pcm;
|
||||
spinlock_t lock_recompute_pcm;
|
||||
/* maintained by card drivers */
|
||||
uint pcm_len; /* allocation length of PCM packet (dynamic) */
|
||||
xpp_line_t wanted_pcm_mask;
|
||||
xpp_line_t silence_pcm; /* inject silence during next tick */
|
||||
xpp_line_t mute_dtmf;
|
||||
uint pcm_len; /* allocation length of PCM packet (dynamic) */
|
||||
xpp_line_t wanted_pcm_mask;
|
||||
xpp_line_t silence_pcm; /* inject silence during next tick */
|
||||
xpp_line_t mute_dtmf;
|
||||
|
||||
bool ringing[CHANNELS_PERXPD];
|
||||
bool ringing[CHANNELS_PERXPD];
|
||||
|
||||
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
|
||||
atomic_t open_counter; /* Number of open channels */
|
||||
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
|
||||
atomic_t open_counter; /* Number of open channels */
|
||||
|
||||
/* Echo cancelation */
|
||||
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
||||
@@ -172,52 +193,51 @@ struct phonedev {
|
||||
*/
|
||||
struct xpd {
|
||||
char xpdname[XPD_NAMELEN];
|
||||
struct phonedev phonedev;
|
||||
struct phonedev phonedev;
|
||||
|
||||
const struct xops *xops;
|
||||
xpd_type_t type;
|
||||
const char *type_name;
|
||||
__u8 subtype;
|
||||
int subunits; /* all siblings */
|
||||
enum xpd_state xpd_state;
|
||||
struct device xpd_dev;
|
||||
const struct xops *xops;
|
||||
xpd_type_t type;
|
||||
const char *type_name;
|
||||
byte subtype;
|
||||
int subunits; /* all siblings */
|
||||
enum xpd_state xpd_state;
|
||||
struct device xpd_dev;
|
||||
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
|
||||
struct kref kref;
|
||||
struct kref kref;
|
||||
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
|
||||
|
||||
xbus_t *xbus; /* The XBUS we are connected to */
|
||||
struct device *echocancel;
|
||||
xbus_t *xbus; /* The XBUS we are connected to */
|
||||
struct device *echocancel;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t lock;
|
||||
|
||||
int flags;
|
||||
unsigned long blink_mode; /* bitmask of blinking ports */
|
||||
int flags;
|
||||
unsigned long blink_mode; /* bitmask of blinking ports */
|
||||
#define DEFAULT_LED_PERIOD (1000/8) /* in tick */
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_xpd_dir;
|
||||
struct proc_dir_entry *proc_xpd_summary;
|
||||
struct proc_dir_entry *proc_xpd_dir;
|
||||
struct proc_dir_entry *proc_xpd_summary;
|
||||
#endif
|
||||
|
||||
int counters[XPD_COUNTER_MAX];
|
||||
int counters[XPD_COUNTER_MAX];
|
||||
|
||||
const xproto_table_t *xproto; /* Card level protocol table */
|
||||
void *priv; /* Card level private data */
|
||||
bool card_present;
|
||||
reg_cmd_t requested_reply;
|
||||
reg_cmd_t last_reply;
|
||||
const xproto_table_t *xproto; /* Card level protocol table */
|
||||
void *priv; /* Card level private data */
|
||||
bool card_present;
|
||||
reg_cmd_t requested_reply;
|
||||
reg_cmd_t last_reply;
|
||||
|
||||
unsigned long last_response; /* in jiffies */
|
||||
unsigned xbus_idx; /* index in xbus->xpds[] */
|
||||
struct xpd_addr addr;
|
||||
unsigned long last_response; /* in jiffies */
|
||||
unsigned xbus_idx; /* index in xbus->xpds[] */
|
||||
struct xpd_addr addr;
|
||||
struct list_head xpd_list;
|
||||
unsigned int timer_count;
|
||||
unsigned int timer_count;
|
||||
};
|
||||
|
||||
#define for_each_line(xpd, i) \
|
||||
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
||||
#define for_each_line(xpd,i) for((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
||||
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
|
||||
#define TICK_TOLERANCE 500 /* usec */
|
||||
#define TICK_TOLERANCE 500 /* usec */
|
||||
|
||||
#ifdef DEBUG_SYNC_PARPORT
|
||||
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
|
||||
@@ -227,28 +247,27 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
|
||||
|
||||
static inline void *my_kzalloc(size_t size, gfp_t flags)
|
||||
{
|
||||
void *p;
|
||||
void *p;
|
||||
|
||||
p = kmalloc(size, flags);
|
||||
if (p)
|
||||
if(p)
|
||||
memset(p, 0, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
struct xpd_driver {
|
||||
xpd_type_t type;
|
||||
xpd_type_t type;
|
||||
|
||||
struct device_driver driver;
|
||||
#define driver_to_xpd_driver(driver) \
|
||||
container_of(driver, struct xpd_driver, driver)
|
||||
struct device_driver driver;
|
||||
#define driver_to_xpd_driver(driver) container_of(driver, struct xpd_driver, driver)
|
||||
};
|
||||
|
||||
int xpd_driver_register(struct device_driver *driver);
|
||||
void xpd_driver_unregister(struct device_driver *driver);
|
||||
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
|
||||
void put_xpd(const char *msg, xpd_t *xpd);
|
||||
int refcount_xpd(xpd_t *xpd);
|
||||
int xpd_driver_register(struct device_driver *driver);
|
||||
void xpd_driver_unregister(struct device_driver *driver);
|
||||
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
|
||||
void put_xpd(const char *msg, xpd_t *xpd);
|
||||
int refcount_xpd(xpd_t *xpd);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* XPD_H */
|
||||
#endif /* XPD_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,24 +25,21 @@
|
||||
#include "xpd.h"
|
||||
#include "xproto.h"
|
||||
|
||||
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, __u8 type, __u8 subtype, int subunits,
|
||||
int subunit_ports, __u8 port_dir);
|
||||
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);
|
||||
int dahdi_register_xpd(xpd_t *xpd);
|
||||
int dahdi_unregister_xpd(xpd_t *xpd);
|
||||
void xbus_request_removal(xbus_t *xbus);
|
||||
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);
|
||||
void update_xpd_status(xpd_t *xpd, int alarm_flag);
|
||||
const char *xpp_echocan_name(const struct dahdi_chan *chan);
|
||||
int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||
struct dahdi_echocanparam *p,
|
||||
struct dahdi_echocan_state **ec);
|
||||
int xpp_echocan_create(struct dahdi_chan *chan,
|
||||
struct dahdi_echocanparams *ecp,
|
||||
struct dahdi_echocanparam *p,
|
||||
struct dahdi_echocan_state **ec);
|
||||
void hookstate_changed(xpd_t *xpd, int pos, bool good);
|
||||
int xpp_open(struct dahdi_chan *chan);
|
||||
int xpp_close(struct dahdi_chan *chan);
|
||||
@@ -50,20 +47,19 @@ int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg);
|
||||
int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig);
|
||||
int xpp_maint(struct dahdi_span *span, int cmd);
|
||||
int xpp_watchdog(struct dahdi_span *span, int cause);
|
||||
void xpp_span_assigned(struct dahdi_span *span);
|
||||
void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd);
|
||||
int total_registered_spans(void);
|
||||
void oht_pcm(xpd_t *xpd, int pos, bool pass);
|
||||
void mark_offhook(xpd_t *xpd, int pos, bool to_offhook);
|
||||
#define IS_OFFHOOK(xpd, pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
|
||||
#define IS_OFFHOOK(xpd,pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
|
||||
void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
extern struct proc_dir_entry *xpp_proc_toplevel;
|
||||
extern struct proc_dir_entry *xpp_proc_toplevel;
|
||||
#endif
|
||||
|
||||
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
|
||||
|
||||
#endif /* XPP_DAHDI_H */
|
||||
#endif /* XPP_DAHDI_H */
|
||||
|
||||
@@ -43,10 +43,11 @@ show_debug() {
|
||||
list=''
|
||||
for n in $dbg_names
|
||||
do
|
||||
if [ $(( val & (1 << j) )) -ne 0 ]; then
|
||||
if (( val & (1 << j) ))
|
||||
then
|
||||
list="$list $n"
|
||||
fi
|
||||
j=$((j+1))
|
||||
let j++
|
||||
done
|
||||
if [ "$list" = "" ]; then
|
||||
list=' NONE'
|
||||
@@ -66,19 +67,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
|
||||
j=$((j+1))
|
||||
let j++
|
||||
done
|
||||
if [ "$found" -eq 0 ]; then
|
||||
echo >&2 "$0: Unknown debug flag '$wanted'"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@
|
||||
|
||||
static const char rcsid[] = "$Id$";
|
||||
|
||||
extern int debug;
|
||||
extern int debug;
|
||||
|
||||
static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
|
||||
|
||||
@@ -40,15 +40,12 @@ static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
|
||||
|
||||
bool valid_xpd_addr(const struct xpd_addr *addr)
|
||||
{
|
||||
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0)
|
||||
&& ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
|
||||
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
|
||||
}
|
||||
EXPORT_SYMBOL(valid_xpd_addr);
|
||||
|
||||
/*------ General Protocol Management ----------------------------*/
|
||||
/*---------------- General Protocol Management ----------------------------*/
|
||||
|
||||
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
|
||||
__u8 opcode)
|
||||
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode)
|
||||
{
|
||||
const xproto_entry_t *xe;
|
||||
|
||||
@@ -56,9 +53,8 @@ const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
|
||||
xe = &table->entries[opcode];
|
||||
return (xe->handler != NULL) ? xe : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(xproto_card_entry);
|
||||
|
||||
const xproto_entry_t *xproto_global_entry(__u8 opcode)
|
||||
const xproto_entry_t *xproto_global_entry(byte opcode)
|
||||
{
|
||||
const xproto_entry_t *xe;
|
||||
|
||||
@@ -66,16 +62,15 @@ const xproto_entry_t *xproto_global_entry(__u8 opcode)
|
||||
//DBG(GENERAL, "opcode=0x%X xe=%p\n", opcode, xe);
|
||||
return xe;
|
||||
}
|
||||
EXPORT_SYMBOL(xproto_global_entry);
|
||||
|
||||
xproto_handler_t xproto_global_handler(__u8 opcode)
|
||||
xproto_handler_t xproto_global_handler(byte opcode)
|
||||
{
|
||||
return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode);
|
||||
}
|
||||
|
||||
static const xproto_table_t *xproto_table(xpd_type_t cardtype)
|
||||
{
|
||||
if (cardtype >= XPD_TYPE_NOMODULE)
|
||||
if(cardtype >= XPD_TYPE_NOMODULE)
|
||||
return NULL;
|
||||
return xprotocol_tables[cardtype];
|
||||
}
|
||||
@@ -90,28 +85,26 @@ const xproto_table_t *xproto_get(xpd_type_t cardtype)
|
||||
{
|
||||
const xproto_table_t *xtable;
|
||||
|
||||
if (cardtype >= XPD_TYPE_NOMODULE)
|
||||
if(cardtype >= XPD_TYPE_NOMODULE)
|
||||
return NULL;
|
||||
xtable = xprotocol_tables[cardtype];
|
||||
if (!xtable) { /* Try to load the relevant module */
|
||||
if(!xtable) { /* Try to load the relevant module */
|
||||
int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype);
|
||||
if (ret != 0) {
|
||||
NOTICE("%s: Failed to load module for type=%d. "
|
||||
"exit status=%d.\n",
|
||||
__func__, cardtype, ret);
|
||||
if(ret != 0) {
|
||||
NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n",
|
||||
__FUNCTION__, cardtype, ret);
|
||||
/* Drop through: we may be lucky... */
|
||||
}
|
||||
xtable = xprotocol_tables[cardtype];
|
||||
}
|
||||
if (xtable) {
|
||||
if(xtable) {
|
||||
BUG_ON(!xtable->owner);
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
DBG(GENERAL, MODULE_REFCOUNT_FORMAT, xtable->name,
|
||||
module_refcount(xtable->owner));
|
||||
#endif
|
||||
if (!try_module_get(xtable->owner)) {
|
||||
ERR("%s: try_module_get for %s failed.\n", __func__,
|
||||
xtable->name);
|
||||
if(!try_module_get(xtable->owner)) {
|
||||
ERR("%s: try_module_get for %s failed.\n", __FUNCTION__, xtable->name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -129,8 +122,7 @@ void xproto_put(const xproto_table_t *xtable)
|
||||
module_put(xtable->owner);
|
||||
}
|
||||
|
||||
xproto_handler_t xproto_card_handler(const xproto_table_t *table,
|
||||
__u8 opcode)
|
||||
xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
|
||||
{
|
||||
const xproto_entry_t *xe;
|
||||
|
||||
@@ -139,89 +131,78 @@ xproto_handler_t xproto_card_handler(const xproto_table_t *table,
|
||||
return xe->handler;
|
||||
}
|
||||
|
||||
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
|
||||
const struct xpd_addr addr, const char *msg)
|
||||
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg)
|
||||
{
|
||||
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", funcname,
|
||||
addr.unit, addr.subunit, msg);
|
||||
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n",
|
||||
funcname, addr.unit, addr.subunit, msg);
|
||||
}
|
||||
EXPORT_SYMBOL(notify_bad_xpd);
|
||||
|
||||
static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
||||
{
|
||||
__u8 op;
|
||||
const xproto_entry_t *xe;
|
||||
xproto_handler_t handler;
|
||||
xproto_table_t *table;
|
||||
xpd_t *xpd;
|
||||
int ret = -EPROTO;
|
||||
byte op;
|
||||
const xproto_entry_t *xe;
|
||||
xproto_handler_t handler;
|
||||
xproto_table_t *table;
|
||||
xpd_t *xpd;
|
||||
int ret = -EPROTO;
|
||||
|
||||
BUG_ON(!pack);
|
||||
if (!valid_xpd_addr(&XPACKET_ADDR(pack))) {
|
||||
if (printk_ratelimit()) {
|
||||
if(!valid_xpd_addr(&XPACKET_ADDR(pack))) {
|
||||
if(printk_ratelimit()) {
|
||||
XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n",
|
||||
__func__, XPACKET_ADDR_UNIT(pack),
|
||||
XPACKET_ADDR_SUBUNIT(pack));
|
||||
dump_packet("packet_process -- bad address", pack,
|
||||
debug);
|
||||
__FUNCTION__,
|
||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
||||
dump_packet("packet_process -- bad address", pack, debug);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
op = XPACKET_OP(pack);
|
||||
xpd =
|
||||
xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack),
|
||||
XPACKET_ADDR_SUBUNIT(pack));
|
||||
xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
||||
/* XPD may be NULL (e.g: during bus polling */
|
||||
xe = xproto_global_entry(op);
|
||||
/*-------- Validations -----------*/
|
||||
if (!xe) {
|
||||
if(!xe) {
|
||||
const xproto_table_t *xtable;
|
||||
|
||||
if (!xpd) {
|
||||
if (printk_ratelimit()) {
|
||||
XBUS_NOTICE(xbus,
|
||||
"%s: from %d%d opcode=0x%02X: "
|
||||
"no such global command.\n",
|
||||
__func__, XPACKET_ADDR_UNIT(pack),
|
||||
XPACKET_ADDR_SUBUNIT(pack), op);
|
||||
dump_packet
|
||||
("packet_process -- no such global command",
|
||||
pack, 1);
|
||||
|
||||
if(!xpd) {
|
||||
if(printk_ratelimit()) {
|
||||
XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n",
|
||||
__FUNCTION__,
|
||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op);
|
||||
dump_packet("packet_process -- no such global command", pack, 1);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
xtable = xproto_table(xpd->type);
|
||||
if (!xtable) {
|
||||
if (printk_ratelimit())
|
||||
XPD_ERR(xpd,
|
||||
"%s: no protocol table (type=%d)\n",
|
||||
__func__, xpd->type);
|
||||
if(!xtable) {
|
||||
if(printk_ratelimit())
|
||||
XPD_ERR(xpd, "%s: no protocol table (type=%d)\n",
|
||||
__FUNCTION__,
|
||||
xpd->type);
|
||||
goto out;
|
||||
}
|
||||
xe = xproto_card_entry(xtable, op);
|
||||
if (!xe) {
|
||||
if (printk_ratelimit()) {
|
||||
XPD_NOTICE(xpd,
|
||||
"%s: bad command (type=%d,opcode=0x%x)\n",
|
||||
__func__, xpd->type, op);
|
||||
dump_packet("packet_process -- bad command",
|
||||
pack, 1);
|
||||
if(!xe) {
|
||||
if(printk_ratelimit()) {
|
||||
XPD_NOTICE(xpd, "%s: bad command (type=%d,opcode=0x%x)\n",
|
||||
__FUNCTION__,
|
||||
xpd->type, op);
|
||||
dump_packet("packet_process -- bad command", pack, 1);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
table = xe->table;
|
||||
BUG_ON(!table);
|
||||
if (!table->packet_is_valid(pack)) {
|
||||
if (printk_ratelimit()) {
|
||||
if(!table->packet_is_valid(pack)) {
|
||||
if(printk_ratelimit()) {
|
||||
ERR("xpp: %s: wrong size %d for opcode=0x%02X\n",
|
||||
__func__, XPACKET_LEN(pack), op);
|
||||
dump_packet("packet_process -- wrong size", pack,
|
||||
debug);
|
||||
__FUNCTION__, XPACKET_LEN(pack), op);
|
||||
dump_packet("packet_process -- wrong size", pack, debug);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
ret = 0; /* All well */
|
||||
ret = 0; /* All well */
|
||||
handler = xe->handler;
|
||||
BUG_ON(!handler);
|
||||
XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack);
|
||||
@@ -232,13 +213,13 @@ out:
|
||||
|
||||
static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
||||
{
|
||||
__u8 *xframe_end;
|
||||
xpacket_t *pack;
|
||||
__u8 *p;
|
||||
int len;
|
||||
int ret;
|
||||
byte *xframe_end;
|
||||
xpacket_t *pack;
|
||||
byte *p;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
if (debug & DBG_COMMANDS)
|
||||
if(debug & DBG_COMMANDS)
|
||||
dump_xframe("RX-CMD", xbus, xframe, DBG_ANY);
|
||||
p = xframe->packets;
|
||||
xframe_end = p + XFRAME_LEN(xframe);
|
||||
@@ -246,34 +227,31 @@ static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
||||
pack = (xpacket_t *)p;
|
||||
len = XPACKET_LEN(pack);
|
||||
/* Sanity checks */
|
||||
if (unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL, PCM_READ))) {
|
||||
static int rate_limit;
|
||||
if(unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL,PCM_READ))) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1003) == 0) {
|
||||
XBUS_DBG(GENERAL, xbus,
|
||||
"A PCM packet within a Non-PCM xframe\n");
|
||||
dump_xframe("In Non-PCM xframe",
|
||||
xbus, xframe, debug);
|
||||
if((rate_limit++ % 1003) == 0) {
|
||||
XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n");
|
||||
dump_xframe("In Non-PCM xframe", xbus, xframe, debug);
|
||||
}
|
||||
ret = -EPROTO;
|
||||
goto out;
|
||||
}
|
||||
p += len;
|
||||
if (p > xframe_end || len < RPACKET_HEADERSIZE) {
|
||||
static int rate_limit;
|
||||
if(p > xframe_end || len < RPACKET_HEADERSIZE) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1003) == 0) {
|
||||
XBUS_NOTICE(xbus, "Invalid packet length %d\n",
|
||||
len);
|
||||
if((rate_limit++ % 1003) == 0) {
|
||||
XBUS_NOTICE(xbus, "Invalid packet length %d\n", len);
|
||||
dump_xframe("BAD LENGTH", xbus, xframe, debug);
|
||||
}
|
||||
ret = -EPROTO;
|
||||
goto out;
|
||||
}
|
||||
ret = packet_process(xbus, pack);
|
||||
if (unlikely(ret < 0))
|
||||
if(unlikely(ret < 0))
|
||||
break;
|
||||
} while (p < xframe_end);
|
||||
} while(p < xframe_end);
|
||||
out:
|
||||
FREE_RECV_XFRAME(xbus, xframe);
|
||||
return ret;
|
||||
@@ -281,22 +259,22 @@ out:
|
||||
|
||||
int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
||||
{
|
||||
int ret = 0;
|
||||
struct timeval now;
|
||||
struct timeval tv_received;
|
||||
int usec;
|
||||
int ret = 0;
|
||||
struct timeval now;
|
||||
struct timeval tv_received;
|
||||
int usec;
|
||||
|
||||
if (XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
|
||||
static int rate_limit;
|
||||
if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
|
||||
static int rate_limit;
|
||||
|
||||
if ((rate_limit++ % 1003) == 0) {
|
||||
if((rate_limit++ % 1003) == 0) {
|
||||
XBUS_NOTICE(xbus, "short xframe\n");
|
||||
dump_xframe("short xframe", xbus, xframe, debug);
|
||||
}
|
||||
FREE_RECV_XFRAME(xbus, xframe);
|
||||
return -EPROTO;
|
||||
}
|
||||
if (!XBUS_FLAGS(xbus, CONNECTED)) {
|
||||
if(!XBUS_FLAGS(xbus, CONNECTED)) {
|
||||
XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -304,8 +282,8 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
||||
/*
|
||||
* We want to check that xframes do not mix PCM and other commands
|
||||
*/
|
||||
if (XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
|
||||
if (!XBUS_IS(xbus, READY))
|
||||
if(XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
|
||||
if(!XBUS_IS(xbus, READY))
|
||||
FREE_RECV_XFRAME(xbus, xframe);
|
||||
else
|
||||
xframe_receive_pcm(xbus, xframe);
|
||||
@@ -315,48 +293,47 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
||||
}
|
||||
/* Calculate total processing time */
|
||||
do_gettimeofday(&now);
|
||||
usec =
|
||||
(now.tv_sec - tv_received.tv_sec) * 1000000 + now.tv_usec -
|
||||
tv_received.tv_usec;
|
||||
if (usec > xbus->max_rx_process)
|
||||
usec = (now.tv_sec - tv_received.tv_sec) * 1000000 +
|
||||
now.tv_usec - tv_received.tv_usec;
|
||||
if(usec > xbus->max_rx_process)
|
||||
xbus->max_rx_process = usec;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xframe_receive);
|
||||
|
||||
#define VERBOSE_DEBUG 1
|
||||
#define ERR_REPORT_LIMIT 20
|
||||
|
||||
void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
||||
{
|
||||
__u8 op = XPACKET_OP(packet);
|
||||
__u8 *addr = (__u8 *)&XPACKET_ADDR(packet);
|
||||
byte op = XPACKET_OP(packet);
|
||||
byte *addr = (byte *)&XPACKET_ADDR(packet);
|
||||
|
||||
if (!debug)
|
||||
if(!debug)
|
||||
return;
|
||||
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", msg,
|
||||
XPACKET_ADDR_UNIT(packet), XPACKET_ADDR_SUBUNIT(packet),
|
||||
(XPACKET_ADDR_SYNC(packet)) ? '+' : ' ', *addr, op,
|
||||
XPACKET_LEN(packet));
|
||||
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d",
|
||||
msg,
|
||||
XPACKET_ADDR_UNIT(packet),
|
||||
XPACKET_ADDR_SUBUNIT(packet),
|
||||
(XPACKET_ADDR_SYNC(packet))?'+':' ',
|
||||
*addr,
|
||||
op,
|
||||
XPACKET_LEN(packet));
|
||||
#if VERBOSE_DEBUG
|
||||
{
|
||||
int i;
|
||||
__u8 *p = (__u8 *)packet;
|
||||
byte *p = (byte *)packet;
|
||||
|
||||
printk(" BYTES: ");
|
||||
for (i = 0; i < XPACKET_LEN(packet); i++) {
|
||||
static int limiter;
|
||||
for(i = 0; i < XPACKET_LEN(packet); i++) {
|
||||
static int limiter = 0;
|
||||
|
||||
if (i >= sizeof(xpacket_t)) {
|
||||
if (limiter < ERR_REPORT_LIMIT) {
|
||||
ERR("%s: length overflow "
|
||||
"i=%d > sizeof(xpacket_t)=%lu\n",
|
||||
__func__, i + 1,
|
||||
(long)sizeof(xpacket_t));
|
||||
} else if (limiter == ERR_REPORT_LIMIT) {
|
||||
ERR("%s: error packet #%d... "
|
||||
"squelsh reports.\n",
|
||||
__func__, limiter);
|
||||
if(i >= sizeof(xpacket_t)) {
|
||||
if(limiter < ERR_REPORT_LIMIT) {
|
||||
ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n",
|
||||
__FUNCTION__, i+1, (long)sizeof(xpacket_t));
|
||||
} else if(limiter == ERR_REPORT_LIMIT) {
|
||||
ERR("%s: error packet #%d... squelsh reports.\n",
|
||||
__FUNCTION__, limiter);
|
||||
}
|
||||
limiter++;
|
||||
break;
|
||||
@@ -368,121 +345,112 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
||||
#endif
|
||||
printk("\n");
|
||||
}
|
||||
EXPORT_SYMBOL(dump_packet);
|
||||
|
||||
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
||||
__u8 unit, xportno_t port, const reg_cmd_t *regcmd)
|
||||
byte unit, xportno_t port, const reg_cmd_t *regcmd)
|
||||
{
|
||||
char action;
|
||||
char modifier;
|
||||
char port_buf[MAX_PROC_WRITE];
|
||||
char reg_buf[MAX_PROC_WRITE];
|
||||
char data_buf[MAX_PROC_WRITE];
|
||||
char action;
|
||||
char modifier;
|
||||
char port_buf[MAX_PROC_WRITE];
|
||||
char reg_buf[MAX_PROC_WRITE];
|
||||
char data_buf[MAX_PROC_WRITE];
|
||||
|
||||
/* The size byte is not included */
|
||||
if (regcmd->bytes > sizeof(*regcmd) - 1) {
|
||||
PORT_NOTICE(xbus, unit, port,
|
||||
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
|
||||
msg, regcmd->bytes);
|
||||
if(regcmd->bytes > sizeof(*regcmd) - 1) { /* The size byte is not included */
|
||||
PORT_NOTICE(xbus, unit, port, "%s: %s: Too long: regcmd->bytes = %d\n",
|
||||
__FUNCTION__, msg, regcmd->bytes);
|
||||
return;
|
||||
}
|
||||
if (regcmd->is_multibyte) {
|
||||
char buf[MAX_PROC_WRITE + 1];
|
||||
int i;
|
||||
int n = 0;
|
||||
size_t len = regcmd->bytes;
|
||||
const __u8 *p = REG_XDATA(regcmd);
|
||||
if(regcmd->is_multibyte) {
|
||||
char buf[MAX_PROC_WRITE + 1];
|
||||
int i;
|
||||
int n = 0;
|
||||
size_t len = regcmd->bytes;
|
||||
const byte *p = REG_XDATA(regcmd);
|
||||
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < len && n < MAX_PROC_WRITE; i++)
|
||||
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ",
|
||||
p[i]);
|
||||
for(i = 0; i < len && n < MAX_PROC_WRITE; i++)
|
||||
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ", p[i]);
|
||||
PORT_DBG(REGS, xbus, unit, port,
|
||||
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
|
||||
"%s[0..%zd]: %s%s\n",
|
||||
unit, port, regcmd->eoframe, msg, len - 1, buf,
|
||||
(n >= MAX_PROC_WRITE) ? "..." : "");
|
||||
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) %s[0..%zd]: %s%s\n",
|
||||
unit, port, regcmd->eoframe,
|
||||
msg, len-1, buf, (n >= MAX_PROC_WRITE)?"...":"");
|
||||
return;
|
||||
}
|
||||
/* The size byte is not included */
|
||||
if (regcmd->bytes != sizeof(*regcmd) - 1) {
|
||||
PORT_NOTICE(xbus, unit, port,
|
||||
"%s: %s: Wrong size: regcmd->bytes = %d\n",
|
||||
__func__, msg, regcmd->bytes);
|
||||
if(regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */
|
||||
PORT_NOTICE(xbus, unit, port, "%s: %s: Wrong size: regcmd->bytes = %d\n",
|
||||
__FUNCTION__, msg, regcmd->bytes);
|
||||
return;
|
||||
}
|
||||
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum,
|
||||
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
|
||||
snprintf(port_buf, MAX_PROC_WRITE, "%d%s",
|
||||
regcmd->portnum,
|
||||
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
|
||||
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
|
||||
modifier = 'D';
|
||||
if (REG_FIELD(regcmd, do_subreg)) {
|
||||
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
|
||||
REG_FIELD(regcmd, regnum), REG_FIELD(regcmd, subreg));
|
||||
if(REG_FIELD(regcmd, do_subreg)) {
|
||||
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
|
||||
REG_FIELD(regcmd, regnum),
|
||||
REG_FIELD(regcmd, subreg));
|
||||
modifier = 'S';
|
||||
} else {
|
||||
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
|
||||
REG_FIELD(regcmd, regnum));
|
||||
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
|
||||
REG_FIELD(regcmd, regnum));
|
||||
}
|
||||
if (REG_FIELD(regcmd, read_request)) {
|
||||
if(REG_FIELD(regcmd, read_request)) {
|
||||
data_buf[0] = '\0';
|
||||
} else if (REG_FIELD(regcmd, do_datah)) {
|
||||
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
|
||||
REG_FIELD(regcmd, data_low), REG_FIELD(regcmd,
|
||||
data_high));
|
||||
} else if(REG_FIELD(regcmd, do_datah)) {
|
||||
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
|
||||
REG_FIELD(regcmd, data_low),
|
||||
REG_FIELD(regcmd, data_high));
|
||||
modifier = 'I';
|
||||
} else {
|
||||
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
|
||||
REG_FIELD(regcmd, data_low));
|
||||
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
|
||||
REG_FIELD(regcmd, data_low));
|
||||
}
|
||||
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n", msg, port_buf,
|
||||
action, modifier, reg_buf, data_buf);
|
||||
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n",
|
||||
msg, port_buf, action, modifier,
|
||||
reg_buf, data_buf);
|
||||
}
|
||||
EXPORT_SYMBOL(dump_reg_cmd);
|
||||
|
||||
const char *xproto_name(xpd_type_t xpd_type)
|
||||
{
|
||||
const xproto_table_t *proto_table;
|
||||
const xproto_table_t *proto_table;
|
||||
|
||||
BUG_ON(xpd_type >= XPD_TYPE_NOMODULE);
|
||||
proto_table = xprotocol_tables[xpd_type];
|
||||
if (!proto_table)
|
||||
if(!proto_table)
|
||||
return NULL;
|
||||
return proto_table->name;
|
||||
}
|
||||
EXPORT_SYMBOL(xproto_name);
|
||||
|
||||
#define CHECK_XOP(xops, f) \
|
||||
if (!(xops)->f) { \
|
||||
ERR("%s: missing xmethod %s [%s (%d)]\n", \
|
||||
__func__, #f, name, type); \
|
||||
if(!(xops)->f) { \
|
||||
ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
|
||||
return -EINVAL; \
|
||||
}
|
||||
|
||||
#define CHECK_PHONEOP(phoneops, f) \
|
||||
if (!(phoneops)->f) { \
|
||||
ERR("%s: missing phone method %s [%s (%d)]\n", \
|
||||
__func__, #f, name, type); \
|
||||
if(!(phoneops)->f) { \
|
||||
ERR("%s: missing phone method %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
|
||||
return -EINVAL; \
|
||||
}
|
||||
|
||||
int xproto_register(const xproto_table_t *proto_table)
|
||||
{
|
||||
int type;
|
||||
const char *name;
|
||||
const struct xops *xops;
|
||||
const struct phoneops *phoneops;
|
||||
|
||||
int type;
|
||||
const char *name;
|
||||
const struct xops *xops;
|
||||
const struct phoneops *phoneops;
|
||||
|
||||
BUG_ON(!proto_table);
|
||||
type = proto_table->type;
|
||||
name = proto_table->name;
|
||||
if (type >= XPD_TYPE_NOMODULE) {
|
||||
NOTICE("%s: Bad xproto type %d\n", __func__, type);
|
||||
if(type >= XPD_TYPE_NOMODULE) {
|
||||
NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
DBG(GENERAL, "%s (%d)\n", name, type);
|
||||
if (xprotocol_tables[type])
|
||||
NOTICE("%s: overriding registration of %s (%d)\n", __func__,
|
||||
name, type);
|
||||
if(xprotocol_tables[type])
|
||||
NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type);
|
||||
xops = proto_table->xops;
|
||||
CHECK_XOP(xops, card_new);
|
||||
CHECK_XOP(xops, card_init);
|
||||
@@ -500,30 +468,38 @@ int xproto_register(const xproto_table_t *proto_table)
|
||||
CHECK_PHONEOP(phoneops, card_dahdi_preregistration);
|
||||
CHECK_PHONEOP(phoneops, card_dahdi_postregistration);
|
||||
/* optional method -- call after testing: */
|
||||
/*CHECK_PHONEOP(phoneops, card_ioctl); */
|
||||
/*CHECK_PHONEOP(phoneops, card_ioctl);*/
|
||||
}
|
||||
|
||||
xprotocol_tables[type] = proto_table;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xproto_register);
|
||||
|
||||
void xproto_unregister(const xproto_table_t *proto_table)
|
||||
{
|
||||
int type;
|
||||
const char *name;
|
||||
|
||||
int type;
|
||||
const char *name;
|
||||
|
||||
BUG_ON(!proto_table);
|
||||
type = proto_table->type;
|
||||
name = proto_table->name;
|
||||
DBG(GENERAL, "%s (%d)\n", name, type);
|
||||
if (type >= XPD_TYPE_NOMODULE) {
|
||||
NOTICE("%s: Bad xproto type %s (%d)\n", __func__, name, type);
|
||||
if(type >= XPD_TYPE_NOMODULE) {
|
||||
NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type);
|
||||
return;
|
||||
}
|
||||
if (!xprotocol_tables[type])
|
||||
NOTICE("%s: xproto type %s (%d) is already unregistered\n",
|
||||
__func__, name, type);
|
||||
if(!xprotocol_tables[type])
|
||||
NOTICE("%s: xproto type %s (%d) is already unregistered\n", __FUNCTION__, name, type);
|
||||
xprotocol_tables[type] = NULL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dump_packet);
|
||||
EXPORT_SYMBOL(dump_reg_cmd);
|
||||
EXPORT_SYMBOL(xframe_receive);
|
||||
EXPORT_SYMBOL(notify_bad_xpd);
|
||||
EXPORT_SYMBOL(valid_xpd_addr);
|
||||
EXPORT_SYMBOL(xproto_global_entry);
|
||||
EXPORT_SYMBOL(xproto_card_entry);
|
||||
EXPORT_SYMBOL(xproto_name);
|
||||
EXPORT_SYMBOL(xproto_register);
|
||||
EXPORT_SYMBOL(xproto_unregister);
|
||||
|
||||
@@ -35,25 +35,25 @@
|
||||
#define XPP_PROTOCOL_VERSION 30
|
||||
|
||||
struct xpd_addr {
|
||||
uint8_t subunit:SUBUNIT_BITS;
|
||||
uint8_t reserved:1;
|
||||
uint8_t unit:UNIT_BITS;
|
||||
uint8_t sync_master:1;
|
||||
uint8_t subunit:SUBUNIT_BITS;
|
||||
uint8_t reserved:1;
|
||||
uint8_t unit:UNIT_BITS;
|
||||
uint8_t sync_master:1;
|
||||
} PACKED;
|
||||
|
||||
#define MKADDR(p, u, s) do { \
|
||||
(p)->unit = (u); \
|
||||
(p)->subunit = (s); \
|
||||
(p)->sync_master = 0; \
|
||||
} while (0)
|
||||
} while(0)
|
||||
|
||||
struct xpacket_header {
|
||||
uint16_t packet_len:10;
|
||||
uint16_t reserved:1;
|
||||
uint16_t is_pcm:1;
|
||||
uint16_t pcmslot:4;
|
||||
uint8_t opcode;
|
||||
struct xpd_addr addr;
|
||||
uint16_t packet_len:10;
|
||||
uint16_t reserved:1;
|
||||
uint16_t is_pcm:1;
|
||||
uint16_t pcmslot:4;
|
||||
uint8_t opcode;
|
||||
struct xpd_addr addr;
|
||||
} PACKED;
|
||||
|
||||
#define XPACKET_OP(p) ((p)->head.opcode)
|
||||
@@ -71,8 +71,8 @@ struct xpacket_header {
|
||||
|
||||
/*
|
||||
* The LSB of the type number signifies:
|
||||
* 0 - TO_PSTN
|
||||
* 1 - TO_PHONE
|
||||
* 0 - TO_PSTN
|
||||
* 1 - TO_PHONE
|
||||
*/
|
||||
#define XPD_TYPE_FXS 1 // TO_PHONE
|
||||
#define XPD_TYPE_FXO 2 // TO_PSTN
|
||||
@@ -81,61 +81,60 @@ struct xpacket_header {
|
||||
#define XPD_TYPE_ECHO 5 // Octasic echo canceller
|
||||
#define XPD_TYPE_NOMODULE 7
|
||||
|
||||
typedef __u8 xpd_type_t;
|
||||
typedef byte xpd_type_t;
|
||||
|
||||
#define XPD_TYPE_PREFIX "xpd-type-"
|
||||
|
||||
#define MODULE_ALIAS_XPD(type) \
|
||||
#define MODULE_ALIAS_XPD(type) \
|
||||
MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type))
|
||||
|
||||
#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */
|
||||
|
||||
bool valid_xpd_addr(const struct xpd_addr *addr);
|
||||
|
||||
#define XPROTO_NAME(card, op) card ## _ ## op
|
||||
#define XPROTO_HANDLER(card, op) XPROTO_NAME(card, op ## _handler)
|
||||
#define XPROTO_CALLER(card, op) XPROTO_NAME(card, op ## _send)
|
||||
#define XPROTO_NAME(card,op) card ## _ ## op
|
||||
#define XPROTO_HANDLER(card,op) XPROTO_NAME(card,op ## _handler)
|
||||
#define XPROTO_CALLER(card,op) XPROTO_NAME(card,op ## _send)
|
||||
|
||||
#define HANDLER_DEF(card, op) \
|
||||
static int XPROTO_HANDLER(card, op) ( \
|
||||
#define HANDLER_DEF(card,op) \
|
||||
static int XPROTO_HANDLER(card,op) ( \
|
||||
xbus_t *xbus, \
|
||||
xpd_t *xpd, \
|
||||
const xproto_entry_t *cmd, \
|
||||
xpacket_t *pack)
|
||||
|
||||
#define CALL_PROTO(card, op, ...) XPROTO_CALLER(card, op)(__VA_ARGS__)
|
||||
#define CALL_PROTO(card,op, ...) XPROTO_CALLER(card,op)( __VA_ARGS__ )
|
||||
|
||||
#define DECLARE_CMD(card, op, ...) \
|
||||
int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__)
|
||||
#define DECLARE_CMD(card,op, ...) \
|
||||
int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ )
|
||||
|
||||
#define HOSTCMD(card, op, ...) \
|
||||
DECLARE_CMD(card, op, ## __VA_ARGS__)
|
||||
#define HOSTCMD(card, op, ...) \
|
||||
DECLARE_CMD(card, op, ## __VA_ARGS__ )
|
||||
|
||||
#define RPACKET_NAME(card, op) XPROTO_NAME(RPACKET_ ## card, op)
|
||||
#define RPACKET_TYPE(card, op) struct RPACKET_NAME(card, op)
|
||||
#define RPACKET_NAME(card,op) XPROTO_NAME(RPACKET_ ## card, op)
|
||||
#define RPACKET_TYPE(card,op) struct RPACKET_NAME(card, op)
|
||||
|
||||
#define DEF_RPACKET_DATA(card, op, ...) \
|
||||
RPACKET_TYPE(card, op) { \
|
||||
#define DEF_RPACKET_DATA(card,op, ...) \
|
||||
RPACKET_TYPE(card,op) { \
|
||||
struct xpacket_header head; \
|
||||
__VA_ARGS__ \
|
||||
} PACKED
|
||||
#define RPACKET_HEADERSIZE sizeof(struct xpacket_header)
|
||||
#define RPACKET_FIELD(p, card, op, field) \
|
||||
(((RPACKET_TYPE(card, op) *)(p))->field)
|
||||
#define RPACKET_SIZE(card, op) sizeof(RPACKET_TYPE(card, op))
|
||||
#define RPACKET_FIELD(p,card,op,field) (((RPACKET_TYPE(card,op) *)(p))->field)
|
||||
#define RPACKET_SIZE(card,op) sizeof(RPACKET_TYPE(card,op))
|
||||
|
||||
#define XENTRY(prototab, module, op) \
|
||||
[ XPROTO_NAME(module, op) ] = { \
|
||||
.handler = XPROTO_HANDLER(module, op), \
|
||||
.datalen = RPACKET_SIZE(module, op), \
|
||||
#define XENTRY(prototab,module,op) \
|
||||
[ XPROTO_NAME(module,op) ] = { \
|
||||
.handler = XPROTO_HANDLER(module,op), \
|
||||
.datalen = RPACKET_SIZE(module,op), \
|
||||
.name = #op, \
|
||||
.table = &PROTO_TABLE(prototab) \
|
||||
}
|
||||
|
||||
#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \
|
||||
#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \
|
||||
do { \
|
||||
XPACKET_OP(p) = XPROTO_NAME(card, op); \
|
||||
XPACKET_LEN(p) = RPACKET_SIZE(card, op); \
|
||||
XPACKET_OP(p) = XPROTO_NAME(card,op); \
|
||||
XPACKET_LEN(p) = RPACKET_SIZE(card,op); \
|
||||
XPACKET_IS_PCM(p) = (pcm); \
|
||||
XPACKET_PCMSLOT(p) = (pcmslot); \
|
||||
XPACKET_RESERVED(p) = 0; \
|
||||
@@ -143,138 +142,138 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
|
||||
XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \
|
||||
XPACKET_ADDR_SYNC(p) = 0; \
|
||||
XPACKET_ADDR_RESERVED(p) = 0; \
|
||||
} while (0)
|
||||
} while(0)
|
||||
|
||||
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
|
||||
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
|
||||
do { \
|
||||
int pack_len = RPACKET_SIZE(card, op); \
|
||||
int pack_len = RPACKET_SIZE(card,op); \
|
||||
\
|
||||
if (!XBUS_FLAGS(xbus, CONNECTED)) \
|
||||
if(!XBUS_FLAGS(xbus, CONNECTED)) \
|
||||
return -ENODEV; \
|
||||
(frm) = ALLOC_SEND_XFRAME(xbus); \
|
||||
if (!(frm)) \
|
||||
if(!(frm)) \
|
||||
return -ENOMEM; \
|
||||
(p) = xframe_next_packet(frm, pack_len); \
|
||||
if (!(p)) \
|
||||
if(!(p)) \
|
||||
return -ENOMEM; \
|
||||
XPACKET_INIT(p, card, op, to, 0, 0); \
|
||||
(frm)->usec_towait = 0; \
|
||||
} while (0)
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
/*----------------- register handling --------------------------------*/
|
||||
/*--------------------------- register handling --------------------------------*/
|
||||
|
||||
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
|
||||
|
||||
typedef struct reg_cmd {
|
||||
__u8 bytes:3; /* Length (for Multibyte) */
|
||||
__u8 eoframe:1; /* For BRI -- end of frame */
|
||||
__u8 portnum:3; /* For port specific registers */
|
||||
__u8 is_multibyte:1;
|
||||
byte bytes:3; /* Length (for Multibyte) */
|
||||
byte eoframe:1; /* For BRI -- end of frame */
|
||||
byte portnum:3; /* For port specific registers */
|
||||
byte is_multibyte:1;
|
||||
union {
|
||||
struct {
|
||||
__u8 reserved:4;
|
||||
__u8 do_datah:1;
|
||||
__u8 do_subreg:1;
|
||||
__u8 read_request:1;
|
||||
__u8 all_ports_broadcast:1;
|
||||
__u8 regnum;
|
||||
__u8 subreg;
|
||||
__u8 data_low;
|
||||
__u8 data_high;
|
||||
byte reserved:4;
|
||||
byte do_datah:1;
|
||||
byte do_subreg:1;
|
||||
byte read_request:1;
|
||||
byte all_ports_broadcast:1;
|
||||
byte regnum;
|
||||
byte subreg;
|
||||
byte data_low;
|
||||
byte data_high;
|
||||
} PACKED r;
|
||||
/* For Write-Multibyte commands in BRI */
|
||||
struct {
|
||||
__u8 xdata[MULTIBYTE_MAX_LEN];
|
||||
byte xdata[MULTIBYTE_MAX_LEN];
|
||||
} PACKED d;
|
||||
} PACKED alt;
|
||||
} PACKED reg_cmd_t;
|
||||
|
||||
/* Shortcut access macros */
|
||||
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
|
||||
#define REG_FIELD(regptr,member) ((regptr)->alt.r.member)
|
||||
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/*----------------- protocol tables ----------------------------------*/
|
||||
/*--------------------------- protocol tables ----------------------------------*/
|
||||
|
||||
typedef struct xproto_entry xproto_entry_t;
|
||||
typedef struct xproto_table xproto_table_t;
|
||||
typedef struct xproto_entry xproto_entry_t;
|
||||
typedef struct xproto_table xproto_table_t;
|
||||
|
||||
typedef int (*xproto_handler_t) (xbus_t *xbus, xpd_t *xpd,
|
||||
const xproto_entry_t *cmd, xpacket_t *pack);
|
||||
typedef int (*xproto_handler_t)(
|
||||
xbus_t *xbus,
|
||||
xpd_t *xpd,
|
||||
const xproto_entry_t *cmd,
|
||||
xpacket_t *pack);
|
||||
|
||||
const xproto_table_t *xproto_get(xpd_type_t cardtype);
|
||||
void xproto_put(const xproto_table_t *xtable);
|
||||
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
|
||||
__u8 opcode);
|
||||
xproto_handler_t xproto_card_handler(const xproto_table_t *table,
|
||||
__u8 opcode);
|
||||
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode);
|
||||
xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode);
|
||||
|
||||
const xproto_entry_t *xproto_global_entry(__u8 opcode);
|
||||
xproto_handler_t xproto_global_handler(__u8 opcode);
|
||||
const xproto_entry_t *xproto_global_entry(byte opcode);
|
||||
xproto_handler_t xproto_global_handler(byte opcode);
|
||||
|
||||
/*
|
||||
* XMETHOD() resolve to method pointer (NULL for optional methods)
|
||||
* CALL_XMETHOD() calls the method, passing mandatory arguments
|
||||
*/
|
||||
#define XMETHOD(name, xpd) ((xpd)->xops->name)
|
||||
#define CALL_XMETHOD(name, xpd, ...) \
|
||||
(XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__))
|
||||
#define CALL_XMETHOD(name, xpd, ...) \
|
||||
(XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__ ))
|
||||
|
||||
/*
|
||||
* PHONE_METHOD() resolve to method pointer (NULL for optional methods)
|
||||
* CALL_PHONE_METHOD() calls the method, passing mandatory arguments
|
||||
*/
|
||||
#define PHONE_METHOD(name, xpd) (PHONEDEV(xpd).phoneops->name)
|
||||
#define CALL_PHONE_METHOD(name, xpd, ...) \
|
||||
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__))
|
||||
#define CALL_PHONE_METHOD(name, xpd, ...) \
|
||||
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__ ))
|
||||
|
||||
struct phoneops {
|
||||
void (*card_pcm_recompute) (xpd_t *xpd, xpp_line_t pcm_mask);
|
||||
void (*card_pcm_fromspan) (xpd_t *xpd, xpacket_t *pack);
|
||||
void (*card_pcm_tospan) (xpd_t *xpd, xpacket_t *pack);
|
||||
int (*echocancel_timeslot) (xpd_t *xpd, int pos);
|
||||
int (*echocancel_setmask) (xpd_t *xpd, xpp_line_t ec_mask);
|
||||
int (*card_timing_priority) (xpd_t *xpd);
|
||||
int (*card_dahdi_preregistration) (xpd_t *xpd, bool on);
|
||||
int (*card_dahdi_postregistration) (xpd_t *xpd, bool on);
|
||||
int (*card_hooksig) (xpd_t *xpd, int pos, enum dahdi_txsig txsig);
|
||||
int (*card_ioctl) (xpd_t *xpd, int pos, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
int (*card_open) (xpd_t *xpd, lineno_t pos);
|
||||
int (*card_close) (xpd_t *xpd, lineno_t pos);
|
||||
int (*card_state) (xpd_t *xpd, bool on);
|
||||
void (*card_pcm_recompute)(xpd_t *xpd, xpp_line_t pcm_mask);
|
||||
void (*card_pcm_fromspan)(xpd_t *xpd, xpacket_t *pack);
|
||||
void (*card_pcm_tospan)(xpd_t *xpd, xpacket_t *pack);
|
||||
int (*echocancel_timeslot)(xpd_t *xpd, int pos);
|
||||
int (*echocancel_setmask)(xpd_t *xpd, xpp_line_t ec_mask);
|
||||
int (*card_timing_priority)(xpd_t *xpd);
|
||||
int (*card_dahdi_preregistration)(xpd_t *xpd, bool on);
|
||||
int (*card_dahdi_postregistration)(xpd_t *xpd, bool on);
|
||||
int (*card_hooksig)(xpd_t *xpd, int pos, enum dahdi_txsig txsig);
|
||||
int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg);
|
||||
int (*card_open)(xpd_t *xpd, lineno_t pos);
|
||||
int (*card_close)(xpd_t *xpd, lineno_t pos);
|
||||
int (*card_state)(xpd_t *xpd, bool on);
|
||||
};
|
||||
|
||||
struct xops {
|
||||
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, __u8 subtype,
|
||||
int subunits, int subunit_ports, bool to_phone);
|
||||
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_register_reply) (xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
|
||||
xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, byte subtype,
|
||||
int subunits, int subunit_ports, bool to_phone);
|
||||
int (*card_init)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
|
||||
};
|
||||
|
||||
struct xproto_entry {
|
||||
xproto_handler_t handler;
|
||||
int datalen;
|
||||
const char *name;
|
||||
xproto_table_t *table;
|
||||
xproto_handler_t handler;
|
||||
int datalen;
|
||||
const char *name;
|
||||
xproto_table_t *table;
|
||||
};
|
||||
|
||||
struct xproto_table {
|
||||
struct module *owner;
|
||||
xproto_entry_t entries[256]; /* Indexed by opcode */
|
||||
const struct xops *xops; /* Card level operations */
|
||||
const struct phoneops *phoneops; /* DAHDI operations */
|
||||
const struct echoops *echoops; /* Echo Canceller operations */
|
||||
xpd_type_t type;
|
||||
__u8 ports_per_subunit;
|
||||
const char *name;
|
||||
bool (*packet_is_valid) (xpacket_t *pack);
|
||||
void (*packet_dump) (const char *msg, xpacket_t *pack);
|
||||
struct module *owner;
|
||||
xproto_entry_t entries[256]; /* Indexed by opcode */
|
||||
const struct xops *xops; /* Card level operations */
|
||||
const struct phoneops *phoneops; /* DAHDI operations */
|
||||
const struct echoops *echoops; /* Echo Canceller operations */
|
||||
xpd_type_t type;
|
||||
byte ports_per_subunit;
|
||||
const char *name;
|
||||
bool (*packet_is_valid)(xpacket_t *pack);
|
||||
void (*packet_dump)(const char *msg, xpacket_t *pack);
|
||||
};
|
||||
|
||||
#include "card_global.h"
|
||||
@@ -283,10 +282,11 @@ struct xproto_table {
|
||||
#include "card_bri.h"
|
||||
#include "card_pri.h"
|
||||
|
||||
#define MEMBER(card, op) RPACKET_TYPE(card, op) RPACKET_NAME(card, op)
|
||||
|
||||
#define MEMBER(card,op) RPACKET_TYPE(card,op) RPACKET_NAME(card,op)
|
||||
|
||||
struct xpacket {
|
||||
struct xpacket_header head;
|
||||
struct xpacket_header head;
|
||||
union {
|
||||
MEMBER(GLOBAL, NULL_REPLY);
|
||||
MEMBER(GLOBAL, PCM_WRITE);
|
||||
@@ -297,22 +297,20 @@ struct xpacket {
|
||||
MEMBER(FXS, SIG_CHANGED);
|
||||
MEMBER(FXO, SIG_CHANGED);
|
||||
|
||||
__u8 data[0];
|
||||
byte data[0];
|
||||
};
|
||||
/* Last byte is chksum */
|
||||
} PACKED;
|
||||
|
||||
void dump_packet(const char *msg, const xpacket_t *packet, bool debug);
|
||||
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
||||
__u8 unit, xportno_t port, const reg_cmd_t *regcmd);
|
||||
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, byte unit, xportno_t port, const reg_cmd_t *regcmd);
|
||||
int xframe_receive(xbus_t *xbus, xframe_t *xframe);
|
||||
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
|
||||
const struct xpd_addr addr, const char *msg);
|
||||
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg);
|
||||
int xproto_register(const xproto_table_t *proto_table);
|
||||
void xproto_unregister(const xproto_table_t *proto_table);
|
||||
const xproto_entry_t *xproto_global_entry(__u8 opcode);
|
||||
const xproto_entry_t *xproto_global_entry(byte opcode);
|
||||
const char *xproto_name(xpd_type_t xpd_type);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* XPROTO_H */
|
||||
#endif /* XPROTO_H */
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* DAHDI compile time options */
|
||||
@@ -73,8 +76,10 @@
|
||||
/* You can still override them below */
|
||||
#if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE)
|
||||
#define DAHDI_HDLC_TYPE_TRANS
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)
|
||||
#define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncomment CONFIG_DAHDI_NET to enable SyncPPP, CiscoHDLC, and Frame Relay
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* written by Jim Dixon <jim@lambdatel.com>.
|
||||
*
|
||||
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
|
||||
* Copyright (C) 2001 - 2012 Digium, Inc.
|
||||
* Copyright (C) 2001 - 2010 Digium, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -38,8 +38,11 @@
|
||||
|
||||
#include <dahdi/dahdi_config.h>
|
||||
#include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
@@ -52,12 +55,14 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/interrupt.h>
|
||||
#endif
|
||||
#include <linux/device.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include <linux/poll.h>
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
|
||||
#define dahdi_pci_module pci_register_driver
|
||||
#else
|
||||
#define dahdi_pci_module pci_module_init
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
|
||||
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id)
|
||||
@@ -65,39 +70,37 @@
|
||||
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
|
||||
#ifdef CONFIG_PCI
|
||||
#include <linux/pci-aspm.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
|
||||
#define HAVE_NET_DEVICE_OPS
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
|
||||
#define DAHDI_IRQ_SHARED IRQF_SHARED
|
||||
#define DAHDI_IRQ_DISABLED IRQF_DISABLED
|
||||
#define DAHDI_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED
|
||||
#else
|
||||
#define DAHDI_IRQ_SHARED SA_SHIRQ
|
||||
#define DAHDI_IRQ_DISABLED SA_INTERRUPT
|
||||
#define DAHDI_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
|
||||
#ifndef dev_notice
|
||||
#define dev_notice(dev, format, arg...) \
|
||||
dev_printk(KERN_NOTICE , dev , format , ## arg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
|
||||
# ifdef RHEL_RELEASE_VERSION
|
||||
# if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 6)
|
||||
#define dev_name(dev) ((dev)->bus_id)
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
|
||||
# else
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
do { \
|
||||
kobject_set_name(&(dev)->kobj, format, ## __VA_ARGS__); \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, \
|
||||
kobject_name(&(dev)->kobj)); \
|
||||
} while (0)
|
||||
# endif
|
||||
# else
|
||||
#define dev_name(dev) ((dev)->bus_id)
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
|
||||
# endif
|
||||
#define dev_set_name(dev, format, ...) \
|
||||
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
|
||||
#endif
|
||||
|
||||
/*! Default chunk size for conferences and such -- static right now, might make
|
||||
@@ -107,7 +110,7 @@
|
||||
#define DAHDI_MIN_CHUNKSIZE DAHDI_CHUNKSIZE
|
||||
#define DAHDI_DEFAULT_CHUNKSIZE DAHDI_CHUNKSIZE
|
||||
#define DAHDI_MAX_CHUNKSIZE DAHDI_CHUNKSIZE
|
||||
#define DAHDI_CB_SIZE (1 << 3)
|
||||
#define DAHDI_CB_SIZE 2
|
||||
|
||||
/* DAHDI operates at 8Khz by default */
|
||||
#define DAHDI_MS_TO_SAMPLES(ms) ((ms) * 8)
|
||||
@@ -491,7 +494,10 @@ struct dahdi_chan {
|
||||
|
||||
int numbufs; /*!< How many buffers in channel */
|
||||
int txbufpolicy; /*!< Buffer policy */
|
||||
int rxbufpolicy; /*!< Buffer policy */
|
||||
int txdisable; /*!< Disable transmitter */
|
||||
int rxdisable; /*!< Disable receiver */
|
||||
|
||||
|
||||
/* Tone zone stuff */
|
||||
struct dahdi_zone *curzone; /*!< Zone for selecting tones */
|
||||
@@ -536,6 +542,7 @@ struct dahdi_chan {
|
||||
|
||||
short getlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples */
|
||||
unsigned char getraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */
|
||||
short getlin_lastchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples from last chunk */
|
||||
short putlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last received samples */
|
||||
unsigned char putraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */
|
||||
short conflast[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- base part of channel */
|
||||
@@ -788,23 +795,6 @@ struct dahdi_count {
|
||||
#define DAHDI_FLAG_TXUNDERRUN DAHDI_FLAG(TXUNDERRUN)
|
||||
#define DAHDI_FLAG_RXOVERRUN DAHDI_FLAG(RXOVERRUN)
|
||||
|
||||
enum spantypes {
|
||||
SPANTYPE_INVALID = 0,
|
||||
SPANTYPE_ANALOG_FXS,
|
||||
SPANTYPE_ANALOG_FXO,
|
||||
SPANTYPE_ANALOG_MIXED,
|
||||
SPANTYPE_DIGITAL_E1,
|
||||
SPANTYPE_DIGITAL_T1,
|
||||
SPANTYPE_DIGITAL_J1,
|
||||
SPANTYPE_DIGITAL_BRI_NT,
|
||||
SPANTYPE_DIGITAL_BRI_TE,
|
||||
SPANTYPE_DIGITAL_BRI_SOFT,
|
||||
};
|
||||
const char *dahdi_spantype2str(enum spantypes st);
|
||||
enum spantypes dahdi_str2spantype(const char *name);
|
||||
const char *dahdi_lineconfig_bit_name(int lineconfig_bit);
|
||||
ssize_t lineconfig_str(int lineconfig, char buf[], size_t size);
|
||||
|
||||
struct file;
|
||||
|
||||
struct dahdi_span_ops {
|
||||
@@ -896,49 +886,21 @@ 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, enum spantypes st);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
spinlock_t lock;
|
||||
char name[40]; /*!< Span name */
|
||||
char desc[80]; /*!< Span description */
|
||||
enum spantypes spantype; /*!< span type */
|
||||
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
|
||||
@@ -952,6 +914,7 @@ 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 */
|
||||
@@ -971,11 +934,7 @@ struct dahdi_span {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_entry;
|
||||
#endif
|
||||
struct list_head spans_node;
|
||||
|
||||
struct dahdi_device *parent;
|
||||
struct list_head device_node;
|
||||
struct device *span_device;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct dahdi_transcoder_channel {
|
||||
@@ -992,8 +951,6 @@ 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);
|
||||
@@ -1075,7 +1032,6 @@ 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;
|
||||
@@ -1083,7 +1039,6 @@ struct dahdi_dynamic {
|
||||
int timing;
|
||||
int master;
|
||||
unsigned char *msgbuf;
|
||||
struct device *dev;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
@@ -1109,9 +1064,6 @@ struct dahdi_dynamic_driver {
|
||||
|
||||
struct list_head list;
|
||||
struct module *owner;
|
||||
|
||||
/*! Numberic id of next device created by this driver. */
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
/*! \brief Receive a dynamic span message */
|
||||
@@ -1150,22 +1102,6 @@ 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);
|
||||
|
||||
@@ -1180,12 +1116,10 @@ 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 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);
|
||||
|
||||
/*! 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);
|
||||
|
||||
/*! Allocate / free memory for a transcoder */
|
||||
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
|
||||
@@ -1200,6 +1134,9 @@ 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);
|
||||
|
||||
@@ -1273,13 +1210,8 @@ extern u_char __dahdi_lin2mu[16384];
|
||||
extern u_char __dahdi_lin2a[16384];
|
||||
#endif
|
||||
|
||||
struct dahdi_dynamic_ops {
|
||||
struct module *owner;
|
||||
int (*ioctl)(unsigned int cmd, unsigned long data);
|
||||
};
|
||||
|
||||
/*! \brief Used by dynamic DAHDI -- don't use directly */
|
||||
void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops);
|
||||
void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));
|
||||
|
||||
/*! \brief Used by DAHDI HPEC module -- don't use directly */
|
||||
void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data));
|
||||
@@ -1398,16 +1330,6 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
|
||||
#define fatal_signal_pending(p) \
|
||||
(signal_pending((p)) && sigismember(&(p)->pending.signal, SIGKILL))
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#ifndef PCIE_LINK_STATE_L0S
|
||||
#define PCIE_LINK_STATE_L0S 1
|
||||
#define PCIE_LINK_STATE_L1 2
|
||||
#define PCIE_LINK_STATE_CLKPM 4
|
||||
#endif
|
||||
#define pci_disable_link_state dahdi_pci_disable_link_state
|
||||
void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
|
||||
|
||||
#ifndef __packed
|
||||
@@ -1435,16 +1357,59 @@ static inline int strcasecmp(const char *s1, const char *s2)
|
||||
return c1 - c2;
|
||||
}
|
||||
#endif /* clamp_val */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
static inline void list_replace(struct list_head *old, struct list_head *new)
|
||||
{
|
||||
new->next = old->next;
|
||||
new->next->prev = new;
|
||||
new->prev = old->prev;
|
||||
new->prev->next = new;
|
||||
}
|
||||
|
||||
#ifndef WARN_ON_ONCE
|
||||
#define WARN_ON_ONCE(__condition) do { \
|
||||
static int __once = 1; \
|
||||
if (unlikely(__condition)) { \
|
||||
if (__once) { \
|
||||
__once = 0; \
|
||||
WARN_ON(0); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
|
||||
#define kzalloc(a, b) kcalloc(1, a, b)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
|
||||
#define synchronize_rcu() synchronize_kernel()
|
||||
#define kasprintf dahdi_kasprintf
|
||||
char *dahdi_kasprintf(gfp_t gfp, const char *fmt, ...);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
|
||||
#if !defined(HAVE_WAIT_FOR_COMPLETION_TIMEOUT)
|
||||
static inline unsigned long
|
||||
wait_for_completion_interruptible_timeout(struct completion *x,
|
||||
unsigned long timeout)
|
||||
{
|
||||
/* There is a race condition here. If x->done is reset to 0
|
||||
* before the call to wait_for_completion after this thread wakes.
|
||||
*/
|
||||
timeout = wait_event_interruptible_timeout(x->wait, x->done, timeout);
|
||||
if (timeout)
|
||||
wait_for_completion(x);
|
||||
|
||||
return timeout;
|
||||
}
|
||||
#endif
|
||||
typedef u32 __bitwise pm_message_t;
|
||||
#endif /* 2.6.11 */
|
||||
#endif /* 2.6.12 */
|
||||
#endif /* 2.6.14 */
|
||||
#endif /* 2.6.18 */
|
||||
#endif /* 2.6.22 */
|
||||
#endif /* 2.6.25 */
|
||||
#endif /* 2.6.26 */
|
||||
#endif /* 2.6.31 */
|
||||
|
||||
#ifndef CONFIG_TRACING
|
||||
#define trace_printk printk
|
||||
#endif
|
||||
|
||||
#ifndef DEFINE_SPINLOCK
|
||||
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
|
||||
#endif
|
||||
@@ -1489,10 +1454,6 @@ struct mutex {
|
||||
#define DAHDI_PSEUDO 255
|
||||
|
||||
/* prink-wrapper macros */
|
||||
|
||||
#define module_printk(level, fmt, args...) \
|
||||
printk(level "%s: " fmt, THIS_MODULE->name, ## args)
|
||||
|
||||
#define DAHDI_PRINTK(level, category, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, \
|
||||
THIS_MODULE->name, ## __VA_ARGS__)
|
||||
@@ -1500,7 +1461,7 @@ struct mutex {
|
||||
printk(KERN_ ## level "%s%s-%s: span-%d: " fmt, #level, \
|
||||
category, THIS_MODULE->name, (span)->spanno, ## __VA_ARGS__)
|
||||
#define chan_printk(level, category, chan, fmt, ...) \
|
||||
printk(KERN_ ## level "%s%s-%s: chan-%d: " fmt, #level, \
|
||||
printk(KERN_ ## level "%s%s-%s: %d: " fmt, #level, \
|
||||
category, THIS_MODULE->name, (chan)->channo, ## __VA_ARGS__)
|
||||
#define dahdi_err(fmt, ...) DAHDI_PRINTK(ERR, "", fmt, ## __VA_ARGS__)
|
||||
#define span_info(span, fmt, ...) span_printk(INFO, "", span, fmt, \
|
||||
@@ -1514,26 +1475,6 @@ 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.
|
||||
*/
|
||||
@@ -1545,7 +1486,6 @@ 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, \
|
||||
@@ -1558,10 +1498,6 @@ 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