Compare commits

..

2 Commits

Author SHA1 Message Date
Shaun Ruffell
c1d867b8b7 dahdi: Fix previous CentOS 6.5 commit.
The previous commit from earlier today to fix the backport of PDE_DATA was
wrong in that it would not then process the other defines for older kernels if
it detected it was running on a redhat release.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
(cherry picked from commit 71c003ba49)
2013-12-03 09:36:40 -06:00
Shaun Ruffell
1ff5629078 dahdi: CentOS 6.5 backported PDE_DATA definition.
This will fix the "error: redefinition of 'PDE_DATA'" error when compiling.

Internal-Issue-ID: DAHLIN-330
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
(cherry picked from commit 5ec9d756aa)
2013-12-03 09:36:40 -06:00
39 changed files with 1765 additions and 32556 deletions

9
.gitignore vendored
View File

@@ -5,7 +5,6 @@
*.mod
*.mod.[oc]
*.ko
*.ko.unsigned
*.cmd
*.order
*.tar.gz
@@ -39,12 +38,4 @@ drivers/dahdi/firmware/dahdi-fw-oct6114-256.bin
drivers/dahdi/firmware/dahdi-fw-tc400m.bin
drivers/dahdi/firmware/dahdi-fw-te820.bin
drivers/dahdi/firmware/dahdi-fw-vpmoct032.bin
drivers/dahdi/firmware/dahdi-fw-a4a.bin
drivers/dahdi/firmware/dahdi-fw-a4b.bin
drivers/dahdi/firmware/dahdi-fw-a8a.bin
drivers/dahdi/firmware/dahdi-fw-a8b.bin
drivers/dahdi/firmware/dahdi-fw-oct6114-032.bin
drivers/dahdi/firmware/dahdi-fw-te133.bin
drivers/dahdi/firmware/dahdi-fw-te134.bin
drivers/dahdi/firmware/dahdi-fw-te435.bin
drivers/dahdi/firmware/make_firmware_object

View File

@@ -47,6 +47,8 @@ ifeq (yes,$(HAS_KSRC))
HOTPLUG_FIRMWARE:=$(shell if grep -q '^CONFIG_FW_LOADER=[ym]' $(KCONFIG); then echo "yes"; else echo "no"; fi)
endif
UDEV_DIR:=/etc/udev/rules.d
MODULE_ALIASES:=wcfxs wctdm8xxp wct2xxp
INST_HEADERS:=kernel.h user.h fasthdlc.h wctdm_user.h dahdi_config.h
@@ -80,12 +82,12 @@ include/dahdi/version.h: FORCE
fi
@rm -f $@.tmp
prereq: include/dahdi/version.h firmware-loaders
prereq: include/dahdi/version.h firmware-loaders oct612x-lib
stackcheck: $(CHECKSTACK) modules
objdump -d drivers/dahdi/*.ko drivers/dahdi/*/*.ko | $(CHECKSTACK)
install: all install-modules install-include install-firmware install-xpp-firm
install: all install-modules install-devices install-include install-firmware install-xpp-firm
@echo "###################################################"
@echo "###"
@echo "### DAHDI installed successfully."
@@ -94,7 +96,7 @@ install: all install-modules install-include install-firmware install-xpp-firm
@echo "###"
@echo "###################################################"
uninstall: uninstall-modules uninstall-include uninstall-firmware
uninstall: uninstall-modules uninstall-devices uninstall-include uninstall-firmware
install-modconf:
build_tools/genmodconf $(BUILDVER) "$(ROOT_PREFIX)" "$(filter-out dahdi dahdi_dummy xpp dahdi_transcode dahdi_dynamic,$(BUILD_MODULES)) $(MODULE_ALIASES)"
@@ -116,6 +118,13 @@ uninstall-firmware:
firmware-loaders:
$(MAKE) -C drivers/dahdi/firmware firmware-loaders
oct612x-lib:
ifeq (no,$(HAS_KSRC))
@echo "You do not appear to have the sources for the $(KVERS) kernel installed."
@exit 1
endif
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x'
install-include:
for hdr in $(INST_HEADERS); do \
install -D -m 644 include/dahdi/$$hdr $(DESTDIR)/usr/include/dahdi/$$hdr; \
@@ -128,6 +137,14 @@ uninstall-include:
done
-rmdir $(DESTDIR)/usr/include/dahdi
install-devices:
install -d $(DESTDIR)$(UDEV_DIR)
build_tools/genudevrules > $(DESTDIR)$(UDEV_DIR)/dahdi.rules
install -m 644 drivers/dahdi/xpp/xpp.rules $(DESTDIR)$(UDEV_DIR)/
uninstall-devices:
rm -f $(DESTDIR)$(UDEV_DIR)/dahdi.rules
install-modules: modules
ifndef DESTDIR
@if modinfo zaptel > /dev/null 2>&1; then \
@@ -169,9 +186,6 @@ update:
echo "Not under version control"; \
fi
dist:
@./build_tools/make_dist "dahdi-linux" "$(DAHDIVERSION)"
clean:
ifneq (no,$(HAS_KSRC))
$(KMAKE) clean
@@ -201,6 +215,6 @@ README.html: README
dahdi-api.html: drivers/dahdi/dahdi-base.c
build_tools/kernel-doc --kernel $(KSRC) $^ >$@
.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders dist
.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders
FORCE:

17
README
View File

@@ -534,19 +534,10 @@ DAHDI hardware. However if you have such systems, automatic
registration can cause the order of spans to be unpredictable.
The standard startup scripts use 'dahdi_registration on' instead of this.
==== tools_rootdir
(xpp)
Defaults to /. Passed (as the variable DAHDI_TOOLS_ROOTDIR) to generated
events (which can be used in udev hooks). Also serves as the base of
the variable DAHDI_INIT_DIR (by default: $DAHDI_TOOLS_DIR/usr/share/dahdi).
==== initdir
(xpp)
Deprecated. Setting both initdir and tools_rootdir will generate an error.
A directory under tools_rootdir containing the initialization scripts.
This is the directory containing the initialization scripts.
The default is /usr/share/dahdi .
Setting this value could be useful if that location is inconvenient for you.
@@ -989,12 +980,6 @@ A very short type string.
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
Current sync source.
==== sys/bus/dahdi_spans/drivers/generic_lowlevel/master_span
All spans in the bus are handled by a single driver. The driver has one
non-standard attribute: master_span. printing it shows the current DAHDI
master span writing a number to it forces setting this span as the master
span.
Channels Bus
^^^^^^^^^^^^

40
build_tools/genudevrules Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
ver=`udevinfo -V | cut -f3 -d" "`
if [ -z "${ver}" ]; then
# Not found - try udevadm
ver=`udevadm info -V | cut -f3 -d" "`
if [ -z "${ver}" ]; then
# nobody has that old version, anyway.
ver=54
fi
fi
# udev versions prior to 055 use a single '=' for matching key values
# udev versions 055 and later support '==' for that purpose, and versions
# beyond 092 will probably make it mandatory
#
# very old versions of udev required naming rules and permissions rules to be
# in separate files, but it's not clear at what version number that changed
if [ ${ver} -gt 54 ]; then
match="=="
else
match="="
fi
cat <<EOF
# udev rules to generate the /dev/dahdi device files (if not yet provided
# by your distribution):
KERNEL${match}"dahdictl", NAME="dahdi/ctl"
KERNEL${match}"dahditranscode", NAME="dahdi/transcode"
KERNEL${match}"dahditimer", NAME="dahdi/timer"
KERNEL${match}"dahdichannel", NAME="dahdi/channel"
KERNEL${match}"dahdipseudo", NAME="dahdi/pseudo"
KERNEL${match}"dahdi[0-9]*", NAME="dahdi/%n"
# DAHDI devices with ownership/permissions for running as non-root
SUBSYSTEM${match}"dahdi", OWNER="asterisk", GROUP="asterisk", MODE="0660"
EOF

View File

@@ -61,7 +61,7 @@ export ASTRIBANK_HEXLOAD
# make sure Astribank initialization scripts are from our tree.
xpp_ARGS="$xpp_ARGS initdir=$FIRMWARE_DIR"
dahdi_ARGS="$dahdi_ARGS tools_rootdir=$DESTDIR"
#dahdi_ARGS="$dahdi_ARGS initdir=$FIRMWARE_DIR"
if [ "$DYNAMIC_LOC" = 'yes' ]; then
MODULES_LOAD="$MODULES_LOAD dahdi_dynamic dahdi_dynamic_loc"

View File

@@ -1,26 +0,0 @@
#! /bin/sh
if [ "$#" -ne 2 ]; then
echo >&2 "Usage: $0 <package> <version>"
exit 1
fi
package="$1"
version="$2"
tarball_prefix="$package-$version"
echo "I: Making dist tarball for $tarball_prefix"
tarball_name="$tarball_prefix.tar.gz"
tmp_work_dir=".tmp"
tmp_version_dir="$tmp_work_dir/$tarball_prefix"
if [ "$DESTDIR" != '' ]; then
destdir="$DESTDIR/"
fi
output="$destdir$tarball_name"
mkdir -p "$tmp_version_dir"
git archive --format tar HEAD | tar xf - -C "$tmp_version_dir"
echo "$version" > "$tmp_version_dir/.version"
tar czf "$output" -C "$tmp_work_dir" "$tarball_prefix"
rm -rf "$tmp_work_dir"
echo "I: tarball is ready: '$output'"

View File

@@ -7,35 +7,18 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF) += dahdi_dynamic_ethmf.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o
ifdef CONFIG_PCI
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) += oct612x/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
wcte13xp-objs := wcte13xp-base.o oct612x/lib.a
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE43X) += wcte43x.o
wcte43x-objs := wcte43x-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcte43x-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte43x-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCAXX) += wcaxx.o
wcaxx-objs := wcaxx-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcaxx-base.o += -I$(src)/oct612x/ -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcaxx-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/

View File

@@ -173,7 +173,7 @@ static sumtype *conf_sums_next;
static sumtype *conf_sums;
static sumtype *conf_sums_prev;
static struct dahdi_span *master_span;
static struct dahdi_span *master;
struct file_operations *dahdi_transcode_fops = NULL;
@@ -611,7 +611,7 @@ void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec)
/* Is this span our syncronization master? */
int dahdi_is_sync_master(const struct dahdi_span *span)
{
return span == master_span;
return span == master;
}
static inline void rotate_sums(void)
@@ -732,8 +732,6 @@ enum spantypes dahdi_str2spantype(const char *name)
return SPANTYPE_DIGITAL_BRI_TE;
else if (strcasecmp("BRI_SOFT", name) == 0)
return SPANTYPE_DIGITAL_BRI_SOFT;
else if (strcasecmp("DYNAMIC", name) == 0)
return SPANTYPE_DIGITAL_DYNAMIC;
else
return SPANTYPE_INVALID;
}
@@ -751,7 +749,6 @@ const char *dahdi_spantype2str(enum spantypes st)
case SPANTYPE_DIGITAL_BRI_NT: return "BRI_NT";
case SPANTYPE_DIGITAL_BRI_TE: return "BRI_TE";
case SPANTYPE_DIGITAL_BRI_SOFT: return "BRI_SOFT";
case SPANTYPE_DIGITAL_DYNAMIC: return "DYNAMIC";
default:
case SPANTYPE_INVALID: return "INVALID";
};
@@ -790,7 +787,6 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
int crc4_bit = 0;
int len = 0;
int bit;
bool written = false;
for (bit = 4; bit <= 12; bit++) {
int mask = (1 << bit);
@@ -802,10 +798,8 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
case DAHDI_CONFIG_AMI:
case DAHDI_CONFIG_HDB3:
framing_bit = bit;
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
len += snprintf(buf + len, size, "%s/",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
if (!coding_bit) {
@@ -814,18 +808,14 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
case DAHDI_CONFIG_D4:
case DAHDI_CONFIG_CCS:
coding_bit = bit;
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
len += snprintf(buf + len, size, "%s",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
if (!crc4_bit && mask == DAHDI_CONFIG_CRC4) {
crc4_bit = bit;
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
len += snprintf(buf + len, size, "/%s",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
return len;
@@ -3843,31 +3833,6 @@ void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms)
spin_unlock_irqrestore(&chan->lock, flags);
}
struct dahdi_span *get_master_span(void)
{
return master_span;
}
void set_master_span(int spanno)
{
struct dahdi_span *s;
unsigned long flags;
struct dahdi_span *old_master;
spin_lock_irqsave(&chan_lock, flags);
old_master = master_span;
list_for_each_entry(s, &span_list, spans_node) {
if (spanno == s->spanno) {
master_span = s;
break;
}
}
spin_unlock_irqrestore(&chan_lock, flags);
if ((debug & DEBUG_MAIN) && (old_master != master_span))
module_printk(KERN_NOTICE, "Master span is set to %d (%s)\n",
master_span->spanno, master_span->name);
}
static void __dahdi_find_master_span(void)
{
struct dahdi_span *s;
@@ -3875,7 +3840,7 @@ static void __dahdi_find_master_span(void)
struct dahdi_span *old_master;
spin_lock_irqsave(&chan_lock, flags);
old_master = master_span;
old_master = master;
list_for_each_entry(s, &span_list, spans_node) {
if (s->alarms && old_master)
continue;
@@ -3885,15 +3850,15 @@ static void __dahdi_find_master_span(void)
continue;
if (!can_provide_timing(s))
continue;
if (master_span == s)
if (master == s)
continue;
master_span = s;
master = s;
break;
}
spin_unlock_irqrestore(&chan_lock, flags);
if ((debug & DEBUG_MAIN) && (old_master != master_span))
if ((debug & DEBUG_MAIN) && (old_master != master))
module_printk(KERN_NOTICE, "Master changed to %s\n", s->name);
}
@@ -3934,7 +3899,7 @@ void dahdi_alarm_notify(struct dahdi_span *span)
dahdi_alarm_channel(span->chans[x], span->alarms);
/* If we're going into or out of alarm we should try to find a
* new master_span that may be a better fit. */
* new master that may be a better fit. */
dahdi_find_master_span();
/* Report more detailed alarms */
@@ -5164,7 +5129,7 @@ static int dahdi_ioctl_startup(struct file *file, unsigned long data)
}
/* Now that this span is running, it might be selected as the
* master_span */
* master span */
__dahdi_find_master_span();
}
put_span(s);
@@ -7188,13 +7153,6 @@ static void __dahdi_init_span(struct dahdi_span *span)
spin_lock_init(&span->lock);
clear_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags);
/* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via
* sysfs, so when the span is being initialized again before
* reassignment we should make sure it's cleared. This eliminates the
* need for board drivers to re-report their alarm states on span
* reassignment. */
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
if (!span->deflaw) {
module_printk(KERN_NOTICE, "Span %s didn't specify default "
"law. Assuming mulaw, please fix driver!\n",
@@ -7236,7 +7194,7 @@ EXPORT_SYMBOL(dahdi_init_span);
* @spanno: The span number we would like assigned. If 0, the first
* available spanno/basechan will be used.
* @basechan: The base channel number we would like. Ignored if spanno is 0.
* @prefmaster: will the new span be preferred as a master_span?
* @prefmaster: will the new span be preferred as a master?
*
* Assigns a span for usage with DAHDI. All the channel numbers in it will
* have their numbering started at basechan.
@@ -7514,8 +7472,8 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
for (x=0;x<span->channels;x++)
dahdi_chan_unreg(span->chans[x]);
new_master = master_span; /* FIXME: locking */
if (master_span == span)
new_master = master; /* FIXME: locking */
if (master == span)
new_master = NULL;
spin_lock_irqsave(&chan_lock, flags);
@@ -7526,13 +7484,13 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
break;
}
spin_unlock_irqrestore(&chan_lock, flags);
if (master_span != new_master) {
if (master != new_master) {
if (debug & DEBUG_MAIN) {
module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__,
(new_master)? new_master->name: "no master");
}
}
master_span = new_master;
master = new_master;
return 0;
}

View File

@@ -32,15 +32,8 @@
#include "dahdi-sysfs.h"
static char *initdir;
module_param(initdir, charp, 0444);
MODULE_PARM_DESC(initdir,
"deprecated, should use <tools_rootdir>/usr/share/dahdi");
static char *tools_rootdir;
module_param(tools_rootdir, charp, 0444);
MODULE_PARM_DESC(tools_rootdir,
"root directory of all tools paths (default /)");
static char *initdir = "/usr/share/dahdi";
module_param(initdir, charp, 0644);
static int span_match(struct device *dev, struct device_driver *driver)
{
@@ -54,9 +47,7 @@ static inline struct dahdi_span *dev_to_span(struct device *dev)
#define SPAN_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
initdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
} while (0)
@@ -231,51 +222,16 @@ static struct device_attribute span_dev_attrs[] = {
__ATTR_NULL,
};
static ssize_t master_span_show(struct device_driver *driver, char *buf)
{
struct dahdi_span *s = get_master_span();
return snprintf(buf, PAGE_SIZE, "%d\n", (s) ? s->spanno : 0);
}
static ssize_t master_span_store(struct device_driver *driver, const char *buf,
size_t count)
{
int spanno;
if (sscanf(buf, "%d", &spanno) != 1) {
module_printk(KERN_ERR, "non-numeric input '%s'\n", buf);
return -EINVAL;
}
set_master_span(spanno);
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static struct driver_attribute dahdi_attrs[] = {
__ATTR(master_span, S_IRUGO | S_IWUSR, master_span_show,
master_span_store),
__ATTR_NULL,
};
#else
static DRIVER_ATTR_RW(master_span);
static struct attribute *dahdi_attrs[] = {
&driver_attr_master_span.attr,
NULL,
};
ATTRIBUTE_GROUPS(dahdi);
#endif
static struct bus_type spans_bus_type = {
.name = "dahdi_spans",
.match = span_match,
.uevent = span_uevent,
.dev_attrs = span_dev_attrs,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.drv_attrs = dahdi_attrs,
#else
.drv_groups = dahdi_groups,
#endif
};
static int span_probe(struct device *dev)
@@ -340,7 +296,6 @@ void span_sysfs_remove(struct dahdi_span *span)
get_device(span_device);
span_uevent_send(span, KOBJ_OFFLINE);
sysfs_remove_link(&span_device->kobj, "ddev");
device_unregister(span->span_device);
dev_set_drvdata(span_device, NULL);
span_device->parent = NULL;
@@ -381,15 +336,6 @@ int span_sysfs_create(struct dahdi_span *span)
span->span_device = NULL;
goto cleanup;
}
res = sysfs_create_link(&span_device->kobj, &span_device->parent->kobj,
"ddev");
if (res) {
span_err(span, "%s: sysfs_create_link failed: %d\n", __func__,
res);
kfree(span->span_device);
span->span_device = NULL;
goto cleanup;
}
for (x = 0; x < span->channels; x++) {
res = chan_sysfs_create(span->chans[x]);
@@ -416,71 +362,6 @@ static inline struct dahdi_device *to_ddev(struct device *dev)
return container_of(dev, struct dahdi_device, dev);
}
#define DEVICE_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
initdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_HWID=%s", \
ddev->hardware_id); \
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_LOCATION=%s", \
ddev->location); \
} while (0)
#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 device_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct dahdi_device *ddev;
int i = 0;
int len = 0;
if (!dev)
return -ENODEV;
ddev = to_ddev(dev);
if (!ddev)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev));
DEVICE_VAR_BLOCK;
envp[i] = NULL;
return 0;
}
#else
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(kenv, fmt, val); \
if (err) \
return err; \
} while (0)
static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv)
{
struct dahdi_device *ddev;
if (!dev)
return -ENODEV;
ddev = to_ddev(dev);
if (!ddev)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev));
DEVICE_VAR_BLOCK;
return 0;
}
#endif
static ssize_t
dahdi_device_manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -521,16 +402,6 @@ dahdi_device_hardware_id_show(struct device *dev,
(ddev->hardware_id) ? ddev->hardware_id : "");
}
static ssize_t
dahdi_device_location_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n",
(ddev->location) ? ddev->location : "");
}
static ssize_t
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -678,7 +549,6 @@ static struct device_attribute dahdi_device_attrs[] = {
__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(location, S_IRUGO, dahdi_device_location_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),
@@ -689,7 +559,6 @@ static struct device_attribute dahdi_device_attrs[] = {
static struct bus_type dahdi_device_bus = {
.name = "dahdi_devices",
.uevent = device_uevent,
.dev_attrs = dahdi_device_attrs,
};
@@ -770,19 +639,6 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
int res = 0;
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
/* Handle dahdi-tools paths (for udev environment) */
if (tools_rootdir && initdir) {
dahdi_err("Cannot use tools-rootdir and initdir parameters simultaneously\n");
return -EINVAL;
}
if (initdir)
pr_notice("dahdi: initdir is depracated -- prefer using \"tools_rootdir\" parameter\n");
else
initdir = "/usr/share/dahdi";
if (!tools_rootdir)
tools_rootdir = "";
res = bus_register(&dahdi_device_bus);
if (res)
return res;

View File

@@ -630,10 +630,6 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
d->span.deflaw = DAHDI_LAW_MULAW;
d->span.flags |= DAHDI_FLAG_RBS;
d->span.chans = d->chans;
d->span.spantype = SPANTYPE_DIGITAL_DYNAMIC;
d->span.linecompat = DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_CCS |
DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_NOTOPEN;
d->span.ops = &dynamic_ops;
for (x = 0; x < d->span.channels; x++) {
sprintf(d->chans[x]->name, "DYN/%s/%s/%d",

View File

@@ -3,7 +3,7 @@
#
# Makefile for firmware downloading/installation
#
# Copyright (C) 2007-2013, Digium, Inc.
# Copyright (C) 2007-2010, Digium, Inc.
#
# Joshua Colp <jcolp@digium.com>
#
@@ -33,17 +33,10 @@ VPMOCT032_VERSION:=1.12.0
WCT820_VERSION:=1.76
TE133_VERSION:=6f0017
TE134_VERSION:=6f0017
TE435_VERSION:=e0017
A8A_VERSION:=1d0017
A8B_VERSION:=1d0017
A4A_VERSION:=a0017
A4B_VERSION:=b0017
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256
ALL_FIRMWARE+=FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
# First example: dahdi-fw-oct6114-064-1.05.01
@@ -62,11 +55,6 @@ FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE435=dahdi-fw-te435-$(TE435_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8A=dahdi-fw-a8b-$(A8B_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8B=dahdi-fw-a8a-$(A8A_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4A=dahdi-fw-a4b-$(A4B_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4B=dahdi-fw-a4a-$(A4A_VERSION).tar.gz)
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
@@ -237,61 +225,6 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE
else
@echo "Firmware dahdi-fw-te134.bin is already installed with required version $(TE134_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-$(TE435_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te435-$(TE435_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te435.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te435.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-$(TE435_VERSION)
@install -m 644 dahdi-fw-te435.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te435-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te435-$(TE435_VERSION)
else
@echo "Firmware dahdi-fw-te435.bin is already installed with required version $(TE435_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-$(A8A_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-$(A8A_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a8a.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a8a.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-$(A8A_VERSION)
@install -m 644 dahdi-fw-a8a.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-$(A8A_VERSION)
else
@echo "Firmware dahdi-fw-a8a.bin is already installed with required version $(A8A_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-$(A8B_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-$(A8B_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a8b.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a8b.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-$(A8B_VERSION)
@install -m 644 dahdi-fw-a8b.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-$(A8B_VERSION)
else
@echo "Firmware dahdi-fw-a8b.bin is already installed with required version $(A8B_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-$(A4A_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-$(A4A_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a4a.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a4a.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-$(A4A_VERSION)
@install -m 644 dahdi-fw-a4a.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-$(A4A_VERSION)
else
@echo "Firmware dahdi-fw-a4a.bin is already installed with required version $(A4A_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-$(A4B_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-$(A4B_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a4b.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a4b.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-$(A4B_VERSION)
@install -m 645 dahdi-fw-a4b.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-$(A4B_VERSION)
else
@echo "Firmware dahdi-fw-a4b.bin is already installed with required version $(A4B_VERSION)"
endif
# Uninstall any installed dahdi firmware images from hotplug firmware directories
hotplug-uninstall:

View File

@@ -1,32 +0,0 @@
#
# Produces the oct612x library
#
octapi_files = octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_channel.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_debug.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_events.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_memory.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.o \
apilib/bt/octapi_bt0.o \
apilib/largmath/octapi_largmath.o \
apilib/llman/octapi_llman.o \
oct612x-user.o
# TODO: ccflags was added in 2.6.24 in commit f77bf01425b11947eeb3b5b54. This
# should be changed to a conditional compilation based on the Kernel Version.
# ccflags-y := -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
EXTRA_CFLAGS = -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) := oct612x.o
oct612x-objs := $(octapi_files)

View File

@@ -1,200 +0,0 @@
/*
* Octasic OCT6100 Interface
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <dahdi/kernel.h>
#include "oct612x.h"
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
{
/* Why couldn't they just take a timeval like everyone else? */
struct timeval tv;
unsigned long long total_usecs;
unsigned int mask = ~0;
do_gettimeofday(&tv);
total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
(((unsigned long long)(tv.tv_usec)));
f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern,
UINT32 f_ulLength)
{
memset(f_pAddress, f_ulPattern, f_ulLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource,
UINT32 f_ulLength)
{
memcpy(f_pDestination, f_pSource, f_ulLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserCreateSerializeObject(
tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
{
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDestroySerializeObject(
tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
{
#ifdef OCTASIC_DEBUG
pr_debug("I should never be called! (destroy serialize object)\n");
#endif
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserSeizeSerializeObject(
tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserReleaseSerializeObject(
tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
{
struct oct612x_context *context = f_pWriteParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write(context, f_pWriteParams->ulWriteAddress,
f_pWriteParams->usWriteData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
{
struct oct612x_context *context = f_pSmearParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write_smear) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write_smear(context, f_pSmearParams->ulWriteAddress,
f_pSmearParams->usWriteData,
f_pSmearParams->ulWriteLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteBurstApi(
tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
{
struct oct612x_context *context = f_pBurstParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write_burst) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write_burst(context, f_pBurstParams->ulWriteAddress,
f_pBurstParams->pusWriteData,
f_pBurstParams->ulWriteLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
{
struct oct612x_context *context = f_pReadParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->read) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->read(context, f_pReadParams->ulReadAddress,
f_pReadParams->pusReadData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
{
struct oct612x_context *context = f_pBurstParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->read_burst) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->read_burst(context, f_pBurstParams->ulReadAddress,
f_pBurstParams->pusReadData,
f_pBurstParams->ulReadLength);
return cOCT6100_ERR_OK;
}
EXPORT_SYMBOL(Oct6100ChipOpen);
EXPORT_SYMBOL(Oct6100ChipClose);
EXPORT_SYMBOL(Oct6100ChipCloseDef);
EXPORT_SYMBOL(Oct6100GetInstanceSize);
EXPORT_SYMBOL(Oct6100GetInstanceSizeDef);
EXPORT_SYMBOL(Oct6100ChipOpenDef);
EXPORT_SYMBOL(Oct6100ChannelModify);
EXPORT_SYMBOL(Oct6100ToneDetectionEnableDef);
EXPORT_SYMBOL(Oct6100InterruptServiceRoutine);
EXPORT_SYMBOL(Oct6100InterruptServiceRoutineDef);
EXPORT_SYMBOL(Oct6100ApiGetCapacityPins);
EXPORT_SYMBOL(Oct6100ToneDetectionEnable);
EXPORT_SYMBOL(Oct6100EventGetToneDef);
EXPORT_SYMBOL(Oct6100EventGetTone);
EXPORT_SYMBOL(Oct6100ApiGetCapacityPinsDef);
EXPORT_SYMBOL(Oct6100ChannelOpen);
EXPORT_SYMBOL(Oct6100ChannelOpenDef);
EXPORT_SYMBOL(Oct6100ChannelModifyDef);
static int __init oct612x_module_init(void)
{
/* This registration with dahdi.ko will fail since the span is not
* defined, but it will make sure that this module is a dependency of
* dahdi.ko, so that when it is being unloded, this module will be
* unloaded as well. */
dahdi_register_device(NULL, NULL);
return 0;
}
module_init(oct612x_module_init);
static void __exit oct612x_module_cleanup(void)
{
/* Nothing to do */;
}
module_exit(oct612x_module_cleanup);
MODULE_AUTHOR("Digium Incorporated <support@digium.com>");
MODULE_DESCRIPTION("Octasic OCT6100 Hardware Echocan Library");
MODULE_LICENSE("GPL v2");

View File

@@ -1,49 +0,0 @@
/*
* Octasic OCT6100 Interface
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __OCT612X_H__
#define __OCT612X_H__
#include <oct6100api/oct6100_api.h>
struct oct612x_context;
/**
* struct oct612x_ops - Callbacks used by oct612x library to talk to part.
*
*/
struct oct612x_ops {
int (*write)(struct oct612x_context *context, u32 address, u16 value);
int (*read)(struct oct612x_context *context, u32 address, u16 *value);
int (*write_smear)(struct oct612x_context *context, u32 address,
u16 value, size_t count);
int (*write_burst)(struct oct612x_context *context, u32 address,
const u16 *value, size_t count);
int (*read_burst)(struct oct612x_context *context, u32 address,
u16 *value, size_t count);
};
struct oct612x_context {
const struct oct612x_ops *ops;
struct device *dev;
};
#endif /* __OCT612X_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp.o
FIRM_DIR := ../firmware
EXTRA_CFLAGS += -I$(src)/.. -I$(src)/../oct612x/ $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef
EXTRA_CFLAGS += -I$(src)/.. $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef
# The OCT612X source files are from a vendor drop and we do not want to edit
# them to make this warning go away. Therefore, turn off the
@@ -14,7 +14,7 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
endif
wct4xxp-objs := base.o vpm450m.o
wct4xxp-objs := base.o vpm450m.o ../oct612x/lib.a
ifneq ($(HOTPLUG_FIRMWARE),yes)
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o

View File

@@ -183,7 +183,7 @@ static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct
"CONFIG_NOEXTENDED_RESET."
#endif
int debug = 0;
static int debug=0;
static int timingcable = 0;
static int t1e1override = -1; /* deprecated */
static char *default_linemode = "auto";
@@ -299,7 +299,6 @@ struct t4_span {
unsigned long alarmcheck_time;
int spanflags;
int syncpos;
#ifdef SUPPORT_GEN1
int e1check; /* E1 check */
#endif
@@ -346,7 +345,6 @@ struct t4 {
int irq; /* IRQ used by device */
int order; /* Order */
const struct devtype *devtype;
unsigned int reset_required:1; /* If reset needed in serial_setup */
unsigned int falc31:1; /* are we falc v3.1 (atomic not necessary) */
unsigned int t1e1:8; /* T1 / E1 select pins */
int ledreg; /* LED Register */
@@ -507,7 +505,7 @@ static void t4_check_sigbits(struct t4 *wc, int span);
#define FMR5_EIBR (1 << 6) /* Internal Bit Robbing Access */
#define DEC_T 0x60 /* Diable Error Counter */
#define IERR_T 0x1B /* Single Bit Defect Insertion Register */
#define IBV (1 << 0) /* Bipolar violation */
#define IBV 0 /* Bipolar violation */
#define IPE (1 << 1) /* PRBS defect */
#define ICASE (1 << 2) /* CAS defect */
#define ICRCE (1 << 3) /* CRC defect */
@@ -1714,11 +1712,8 @@ _t4_spanconfig(struct file *file, struct dahdi_span *span,
if (lc->sync < 0)
lc->sync = 0;
if (lc->sync > wc->numspans) {
dev_warn(&wc->dev->dev, "WARNING: Cannot set priority on span %d to %d. Please set to a number between 1 and %d\n",
span->spanno, lc->sync, wc->numspans);
if (lc->sync > wc->numspans)
lc->sync = 0;
}
/* remove this span number from the current sync sources, if there */
for(i = 0; i < wc->numspans; i++) {
@@ -1895,33 +1890,6 @@ static void setup_chunks(struct t4 *wc, int which)
}
}
static int __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags,
bool first_time);
static int __t4_hardware_init_2(struct t4 *wc, bool first_time);
static int t4_hardware_stop(struct t4 *wc);
static void t4_framer_reset(struct t4 *wc)
{
const bool first_time = false;
bool have_vpm = wc->vpm != NULL;
if (have_vpm) {
release_vpm450m(wc->vpm);
wc->vpm = NULL;
}
t4_hardware_stop(wc);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
__t4_hardware_init_1(wc, wc->devtype->flags, first_time);
__t4_hardware_init_2(wc, first_time);
if (have_vpm) {
t4_vpm_init(wc);
wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0;
t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
}
setup_chunks(wc, 0);
wc->lastindex = 0;
}
/**
* t4_serial_setup - Setup serial parameters and system interface.
* @wc: The card to configure.
@@ -1931,7 +1899,6 @@ static void t4_serial_setup(struct t4 *wc)
{
unsigned long flags;
unsigned int unit;
bool reset_required = false;
if (debug) {
dev_info(&wc->dev->dev,
@@ -1939,14 +1906,6 @@ static void t4_serial_setup(struct t4 *wc)
wc->numspans);
}
spin_lock_irqsave(&wc->reglock, flags);
reset_required = wc->reset_required > 0;
wc->reset_required = 0;
spin_unlock_irqrestore(&wc->reglock, flags);
if (reset_required)
t4_framer_reset(wc);
spin_lock_irqsave(&wc->reglock, flags);
/* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from
* channel 0 */
@@ -2097,7 +2056,6 @@ static void t4_span_assigned(struct dahdi_span *span)
struct t4 *wc = tspan->owner;
struct dahdi_span *pos;
unsigned int unassigned_spans = 0;
unsigned long flags;
/* We use this to make sure all the spans are assigned before
* running the serial setup. */
@@ -2106,14 +2064,8 @@ static void t4_span_assigned(struct dahdi_span *span)
++unassigned_spans;
}
if (0 == unassigned_spans) {
if (0 == unassigned_spans)
t4_serial_setup(wc);
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
}
}
static void free_wc(struct t4 *wc)
@@ -2275,7 +2227,6 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
enum linemode mode;
const char *old_name;
static DEFINE_MUTEX(linemode_lock);
unsigned long flags;
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name,
dahdi_spantype2str(linemode));
@@ -2283,10 +2234,6 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
if (span->spantype == linemode)
return 0;
spin_lock_irqsave(&wc->reglock, flags);
wc->reset_required = 1;
spin_unlock_irqrestore(&wc->reglock, flags);
/* Do not allow the t1e1 member to be changed by multiple threads. */
mutex_lock(&linemode_lock);
old_name = dahdi_spantype2str(span->spantype);
@@ -2883,10 +2830,6 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
__t4_framer_out(wc, unit, 0x17, 0x04 | imr3extra); /* IMR3: AIS */
__t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */
__t4_framer_out(wc, unit, 0x2f, 0x00);
__t4_framer_out(wc, unit, 0x30, 0x00);
__t4_framer_out(wc, unit, 0x31, 0x00);
dev_info(&wc->dev->dev, "TE%dXXP: Span %d configured for %s/%s%s\n",
wc->numspans, unit + 1, framing, line, crc4);
}
@@ -4363,7 +4306,7 @@ static void t4_vpm_init(struct t4 *wc)
laws[x] = 1;
}
vpm_capacity = get_vpm450m_capacity(&wc->dev->dev);
vpm_capacity = get_vpm450m_capacity(wc);
if (vpm_capacity != wc->numspans * 32) {
dev_info(&wc->dev->dev, "Disabling VPMOCT%03d. TE%dXXP"\
" requires a VPMOCT%03d", vpm_capacity,
@@ -4435,8 +4378,7 @@ static void t4_vpm_init(struct t4 *wc)
return;
}
wc->vpm = init_vpm450m(&wc->dev->dev, laws, wc->numspans, firmware);
if (!wc->vpm) {
if (!(wc->vpm = init_vpm450m(wc, laws, wc->numspans, firmware))) {
dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n");
if (firmware != &embedded_firmware)
release_firmware(firmware);
@@ -4923,18 +4865,17 @@ cleanup:
return res;
}
static int
__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
{
unsigned int version;
int res;
version = t4_pci_in(wc, WC_VERSION);
if (is_octal(wc) && first_time) {
if (is_octal(wc)) {
dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n",
(version & 0xf00) >> 8,
version & 0xff);
} else if (first_time) {
} else {
dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version);
}
if (debug) {
@@ -4982,33 +4923,30 @@ __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
t4_pci_out(wc, WC_INTR, 0x00000000);
/* Read T1/E1 status */
if (first_time) {
if (!strcasecmp("auto", default_linemode)) {
if (-1 == t1e1override) {
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) &
0x0f00) >> 8);
wc->t1e1 &= 0xf;
if (is_octal(wc)) {
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
0x0f00) >> 4;
}
} else {
dev_warn(&wc->dev->dev,
"'t1e1override' is deprecated. Please use 'default_linemode'.\n");
wc->t1e1 = t1e1override & 0xf;
if (!strcasecmp("auto", default_linemode)) {
if (-1 == t1e1override) {
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8);
wc->t1e1 &= 0xf;
if (is_octal(wc)) {
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
0x0f00) >> 4;
}
} else if (!strcasecmp("t1", default_linemode)) {
wc->t1e1 = 0;
} else if (!strcasecmp("e1", default_linemode)) {
wc->t1e1 = 0xff;
} else if (!strcasecmp("j1", default_linemode)) {
wc->t1e1 = 0;
j1mode = 1;
} else {
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
default_linemode);
wc->t1e1 = 0;
dev_warn(&wc->dev->dev, "'t1e1override' is deprecated. "
"Please use 'default_linemode'.\n");
wc->t1e1 = t1e1override & 0xf;
}
} else if (!strcasecmp("t1", default_linemode)) {
wc->t1e1 = 0;
} else if (!strcasecmp("e1", default_linemode)) {
wc->t1e1 = 0xff;
} else if (!strcasecmp("j1", default_linemode)) {
wc->t1e1 = 0;
j1mode = 1;
} else {
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
default_linemode);
wc->t1e1 = 0;
}
wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28;
@@ -5037,12 +4975,7 @@ __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
return 0;
}
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
{
return __t4_hardware_init_1(wc, cardflags, true);
}
static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
static int t4_hardware_init_2(struct t4 *wc)
{
int x;
unsigned int regval;
@@ -5074,14 +5007,13 @@ static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
if (!is_octal(wc)) {
regval = t4_framer_in(wc, 0, 0x4a);
if (first_time && regval == 0x05) {
if (regval == 0x05) {
dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or "
"earlier\n");
} else if (regval == 0x20) {
if (first_time)
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
wc->falc31 = 1;
} else if (first_time) {
} else {
dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
"(VSTR = 0x%02x)\n", regval);
}
@@ -5101,24 +5033,14 @@ static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
t4_pci_in(wc, x));
}
}
wc->gpio = 0x00000000;
t4_pci_out(wc, WC_GPIO, wc->gpio);
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
t4_gpio_setdir(wc, (0xff), (0xff));
return 0;
}
static int t4_hardware_init_2(struct t4 *wc)
{
return __t4_hardware_init_2(wc, true);
}
static int __devinit t4_launch(struct t4 *wc)
{
int x;
int res;
unsigned long flags;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
return 0;
@@ -5150,14 +5072,17 @@ static int __devinit t4_launch(struct t4 *wc)
&wc->ddev->spans);
}
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
if (res) {
dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n");
return res;
}
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
return 0;
}
@@ -5371,6 +5296,10 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&wc->dev->dev,
"Found a Wildcard: %s\n", wc->devtype->desc);
}
wc->gpio = 0x00000000;
t4_pci_out(wc, WC_GPIO, wc->gpio);
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
t4_gpio_setdir(wc, (0xff), (0xff));
#ifdef VPM_SUPPORT
if (!wc->vpm) {

View File

@@ -31,62 +31,99 @@
#include <stdbool.h>
#include "vpm450m.h"
#include <oct612x.h>
#include "oct6100api/oct6100_api.h"
static int wct4xxp_oct612x_write(struct oct612x_context *context,
u32 address, u16 value)
/* API for Octasic access */
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
{
struct t4 *wc = dev_get_drvdata(context->dev);
oct_set_reg(wc, address, value);
return 0;
/* Why couldn't they just take a timeval like everyone else? */
struct timeval tv;
unsigned long long total_usecs;
unsigned int mask = ~0;
do_gettimeofday(&tv);
total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
(((unsigned long long)(tv.tv_usec)));
f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
return cOCT6100_ERR_OK;
}
static int wct4xxp_oct612x_read(struct oct612x_context *context, u32 address,
u16 *value)
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength)
{
struct t4 *wc = dev_get_drvdata(context->dev);
*value = (u16)oct_get_reg(wc, address);
return 0;
memset(f_pAddress, f_ulPattern, f_ulLength);
return cOCT6100_ERR_OK;
}
static int wct4xxp_oct612x_write_smear(struct oct612x_context *context,
u32 address, u16 value, size_t count)
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength)
{
struct t4 *wc = dev_get_drvdata(context->dev);
int i;
for (i = 0; i < count; ++i)
oct_set_reg(wc, address + (i << 1), value);
return 0;
memcpy(f_pDestination, f_pSource, f_ulLength);
return cOCT6100_ERR_OK;
}
static int wct4xxp_oct612x_write_burst(struct oct612x_context *context,
u32 address, const u16 *buffer,
size_t count)
UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
{
struct t4 *wc = dev_get_drvdata(context->dev);
int i;
for (i = 0; i < count; ++i)
oct_set_reg(wc, address + (i << 1), buffer[i]);
return 0;
return cOCT6100_ERR_OK;
}
static int wct4xxp_oct612x_read_burst(struct oct612x_context *context,
u32 address, u16 *buffer, size_t count)
UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
{
struct t4 *wc = dev_get_drvdata(context->dev);
int i;
for (i = 0; i < count; ++i)
buffer[i] = oct_get_reg(wc, address + (i << 1));
return 0;
#ifdef OCTASIC_DEBUG
printk(KERN_DEBUG "I should never be called! (destroy serialize object)\n");
#endif
return cOCT6100_ERR_OK;
}
static const struct oct612x_ops wct4xxp_oct612x_ops = {
.write = wct4xxp_oct612x_write,
.read = wct4xxp_oct612x_read,
.write_smear = wct4xxp_oct612x_write_smear,
.write_burst = wct4xxp_oct612x_write_burst,
.read_burst = wct4xxp_oct612x_read_burst,
};
UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
{
oct_set_reg(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
{
unsigned int x;
for (x=0;x<f_pSmearParams->ulWriteLength;x++) {
oct_set_reg(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData);
}
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
{
unsigned int x;
for (x=0;x<f_pBurstParams->ulWriteLength;x++) {
oct_set_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]);
}
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
{
*(f_pReadParams->pusReadData) = oct_get_reg(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
{
unsigned int x;
for (x=0;x<f_pBurstParams->ulReadLength;x++) {
f_pBurstParams->pusReadData[x] = oct_get_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1));
}
return cOCT6100_ERR_OK;
}
#define SOUT_G168_1100GB_ON 0x40000004
#define SOUT_DTMF_1 0x40000011
@@ -136,7 +173,6 @@ static const struct oct612x_ops wct4xxp_oct612x_ops = {
struct vpm450m {
tPOCT6100_INSTANCE_API pApiInstance;
struct oct612x_context context;
UINT32 aulEchoChanHndl[256];
int chanflags[256];
int ecmode[256];
@@ -220,10 +256,8 @@ void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n",
vpm450m->aulEchoChanHndl[channel], channel, ulResult);
} else {
if (debug) {
pr_info("Changed companding on channel %d to %s.\n",
channel, (alaw) ? "alaw" : "ulaw");
}
pr_info("Changed companding on channel %d to %s.\n", channel,
(alaw) ? "alaw" : "ulaw");
if (alaw)
vpm450m->chanflags[channel] |= FLAG_ALAW;
else
@@ -417,18 +451,14 @@ int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start
return 0;
}
unsigned int get_vpm450m_capacity(struct device *device)
unsigned int get_vpm450m_capacity(void *wc)
{
struct oct612x_context context;
UINT32 ulResult;
tOCT6100_API_GET_CAPACITY_PINS CapacityPins;
context.dev = device;
context.ops = &wct4xxp_oct612x_ops;
Oct6100ApiGetCapacityPinsDef(&CapacityPins);
CapacityPins.pProcessContext = &context;
CapacityPins.pProcessContext = wc;
CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR;
CapacityPins.fEnableMemClkOut = TRUE;
CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
@@ -442,8 +472,7 @@ unsigned int get_vpm450m_capacity(struct device *device)
return CapacityPins.ulCapacityValue;
}
struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
int numspans, const struct firmware *firmware)
struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware)
{
tOCT6100_CHIP_OPEN *ChipOpen;
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
@@ -458,8 +487,6 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
return NULL;
memset(vpm450m, 0, sizeof(struct vpm450m));
vpm450m->context.dev = device;
vpm450m->context.ops = &wct4xxp_oct612x_ops;
if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) {
kfree(vpm450m);
@@ -488,7 +515,7 @@ struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;
Oct6100GetInstanceSizeDef(&InstanceSize);
ChipOpen->pProcessContext = &vpm450m->context;
ChipOpen->pProcessContext = wc;
ChipOpen->pbyImageFile = firmware->data;
ChipOpen->ulImageSize = firmware->size;

View File

@@ -25,7 +25,6 @@
#include <linux/firmware.h>
struct t4;
struct vpm450m;
/* From driver */
@@ -33,9 +32,8 @@ unsigned int oct_get_reg(void *data, unsigned int reg);
void oct_set_reg(void *data, unsigned int reg, unsigned int val);
/* From vpm450m */
struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
int numspans, const struct firmware *firmware);
unsigned int get_vpm450m_capacity(struct device *device);
struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware);
unsigned int get_vpm450m_capacity(void *wc);
void vpm450m_setec(struct vpm450m *instance, int channel, int eclen);
void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int dtmfmute);
int vpm450m_checkirq(struct vpm450m *vpm450m);
@@ -44,6 +42,4 @@ void release_vpm450m(struct vpm450m *instance);
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
int channel, bool alaw);
extern int debug;
#endif

View File

@@ -4384,6 +4384,32 @@ wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
return wctdm_wait_for_ready(wc);
}
/*
* wctdm24xxp_assigned - Called when span is assigned.
* @span: The span that is now assigned.
*
* This function is called by the core of DAHDI after the span number and
* channel numbers have been assigned.
*
*/
static void wctdm24xxp_assigned(struct dahdi_span *span)
{
struct dahdi_span *s;
struct dahdi_device *ddev = span->parent;
struct wctdm *wc = NULL;
list_for_each_entry(s, &ddev->spans, device_node) {
wc = (container_of(s, struct wctdm_span, span))->wc;
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
return;
}
if (wc) {
WARN_ON(0 == wc->not_ready);
--wc->not_ready;
}
}
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.owner = THIS_MODULE,
.hooksig = wctdm_hooksig,
@@ -4393,6 +4419,7 @@ static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.watchdog = wctdm_watchdog,
.chanconfig = wctdm_chanconfig,
.dacs = wctdm_dacs,
.assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -4411,6 +4438,7 @@ static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = {
.spanconfig = b400m_spanconfig,
.chanconfig = b400m_chanconfig,
.dacs = wctdm_dacs,
.assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -5923,9 +5951,6 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return -1;
}
WARN_ON(wc->not_ready <= 0);
--wc->not_ready;
dev_info(&wc->vb.pdev->dev,
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
(is_hx8(wc)) ? "Hybrid card" : "Wildcard TDM",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,951 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
#define HAVE_RATELIMIT
#include <linux/ratelimit.h>
#endif
#include <dahdi/kernel.h>
#include <stdbool.h>
#include "wcxb.h"
#include "wcxb_spi.h"
#include "wcxb_flash.h"
/* The definition for Surprise Down was added in Linux 3.6 in (a0dee2e PCI: misc
* pci_reg additions). It may be backported though so we won't check for the
* version. */
#ifndef PCI_ERR_UNC_SURPDN
#define PCI_ERR_UNC_SURPDN 0x20
#endif
/* FPGA Status definitions */
#define OCT_CPU_RESET (1 << 0)
#define OCT_CPU_DRAM_CKE (1 << 1)
#define STATUS_LED_GREEN (1 << 9)
#define STATUS_LED_RED (1 << 10)
#define FALC_CPU_RESET (1 << 11)
/* Descriptor ring definitions */
#define DRING_SIZE (1 << 7) /* Must be in multiples of 2 */
#define DRING_SIZE_MASK (DRING_SIZE-1)
#define DESC_EOR (1 << 0)
#define DESC_INT (1 << 1)
#define DESC_OWN (1 << 31)
#define DESC_DEFAULT_STATUS 0xdeadbeef
#define DMA_CHAN_SIZE 128
/* Echocan definitions */
#define OCT_OFFSET (xb->membase + 0x10000)
#define OCT_CONTROL_REG (OCT_OFFSET + 0)
#define OCT_DATA_REG (OCT_OFFSET + 0x4)
#define OCT_ADDRESS_HIGH_REG (OCT_OFFSET + 0x8)
#define OCT_ADDRESS_LOW_REG (OCT_OFFSET + 0xa)
#define OCT_DIRECT_WRITE_MASK 0x3001
#define OCT_INDIRECT_READ_MASK 0x0101
#define OCT_INDIRECT_WRITE_MASK 0x3101
/* DMA definitions */
#define TDM_DRING_ADDR 0x2000
#define TDM_CONTROL (TDM_DRING_ADDR + 0x4)
#define ENABLE_ECHOCAN_TDM (1 << 0)
#define TDM_RECOVER_CLOCK (1 << 1)
#define ENABLE_DMA (1 << 2)
#define DMA_RUNNING (1 << 3)
#define DMA_LOOPBACK (1 << 4)
#define AUTHENTICATED (1 << 5)
#define TDM_VERSION (TDM_DRING_ADDR + 0x24)
/* Interrupt definitions */
#define INTERRUPT_CONTROL 0x300
#define ISR (INTERRUPT_CONTROL + 0x0)
#define IPR (INTERRUPT_CONTROL + 0x4)
#define IER (INTERRUPT_CONTROL + 0x8)
#define IAR (INTERRUPT_CONTROL + 0xc)
#define SIE (INTERRUPT_CONTROL + 0x10)
#define CIE (INTERRUPT_CONTROL + 0x14)
#define IVR (INTERRUPT_CONTROL + 0x18)
#define MER (INTERRUPT_CONTROL + 0x1c)
#define MER_ME (1<<0)
#define MER_HIE (1<<1)
#define DESC_UNDERRUN (1<<0)
#define DESC_COMPLETE (1<<1)
#define OCT_INT (1<<2)
#define FALC_INT (1<<3)
#define SPI_INT (1<<4)
#define FLASH_SPI_BASE 0x200
struct wcxb_hw_desc {
volatile __be32 status;
__be32 tx_buf;
__be32 rx_buf;
volatile __be32 control;
} __packed;
struct wcxb_meta_desc {
void *tx_buf_virt;
void *rx_buf_virt;
};
static inline bool wcxb_is_pcie(const struct wcxb *xb)
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 33)
return pci_is_pcie(xb->pdev);
#else
#ifndef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
return (xb->pdev->is_pcie > 0);
#else
return (xb->flags.is_pcie > 0);
#endif
#endif
}
static const unsigned int CLK_SRC_MASK = ((1 << 13) | (1 << 12) | (1 << 1));
enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb)
{
static const u32 SELF = 0x0;
static const u32 RECOVER = (1 << 1);
static const u32 SLAVE = (1 << 12) | (1 << 1);
unsigned long flags;
u32 reg;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase + TDM_CONTROL) & CLK_SRC_MASK;
spin_unlock_irqrestore(&xb->lock, flags);
if (SELF == reg)
return WCXB_CLOCK_SELF;
else if (RECOVER == reg)
return WCXB_CLOCK_RECOVER;
else if (SLAVE == reg)
return WCXB_CLOCK_SLAVE;
else
WARN_ON(1);
return WCXB_CLOCK_SELF;
}
void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc)
{
unsigned long flags;
u32 clkbits = 0;
switch (clksrc) {
case WCXB_CLOCK_RECOVER:
if (xb->flags.drive_timing_cable)
clkbits = (1<<13) | (1 << 1);
else
clkbits = (1 << 1);
break;
case WCXB_CLOCK_SELF:
if (xb->flags.drive_timing_cable)
clkbits = (1<<13);
else
clkbits = 0;
break;
case WCXB_CLOCK_SLAVE:
/* When we're slave, do not ever drive the timing cable. */
clkbits = (1<<12) | (1 << 1);
break;
};
/* set new clock select */
spin_lock_irqsave(&xb->lock, flags);
if (!wcxb_is_stopped(xb)) {
dev_err(&xb->pdev->dev, "ERROR: Cannot set clock source while DMA engine is running.\n");
} else {
u32 reg;
reg = ioread32be(xb->membase + TDM_CONTROL);
reg &= ~CLK_SRC_MASK;
reg |= (clkbits & CLK_SRC_MASK);
iowrite32be(reg, xb->membase + TDM_CONTROL);
}
spin_unlock_irqrestore(&xb->lock, flags);
}
void wcxb_enable_echocan(struct wcxb *xb)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase + TDM_CONTROL);
reg |= ENABLE_ECHOCAN_TDM;
iowrite32be(reg, xb->membase + TDM_CONTROL);
spin_unlock_irqrestore(&xb->lock, flags);
}
void wcxb_disable_echocan(struct wcxb *xb)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase + TDM_CONTROL);
reg &= ~ENABLE_ECHOCAN_TDM;
iowrite32be(reg, xb->membase + TDM_CONTROL);
spin_unlock_irqrestore(&xb->lock, flags);
}
void wcxb_reset_echocan(struct wcxb *xb)
{
unsigned long flags;
int reg;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be((reg & ~OCT_CPU_RESET), xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
msleep_interruptible(1);
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be((reg | OCT_CPU_RESET), xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
dev_dbg(&xb->pdev->dev, "Reset octasic\n");
}
bool wcxb_is_echocan_present(struct wcxb *xb)
{
return 0x1 == ioread16be(OCT_CONTROL_REG);
}
void wcxb_enable_echocan_dram(struct wcxb *xb)
{
unsigned long flags;
int reg;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be((reg | OCT_CPU_DRAM_CKE), xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address)
{
uint16_t highaddress = ((address >> 20) & 0xfff);
uint16_t lowaddress = ((address >> 4) & 0xfffff);
unsigned long stop = jiffies + HZ/10;
unsigned long flags;
u16 ret;
spin_lock_irqsave(&xb->lock, flags);
iowrite16be(highaddress, OCT_ADDRESS_HIGH_REG);
iowrite16be(lowaddress, OCT_ADDRESS_LOW_REG);
iowrite16be(OCT_INDIRECT_READ_MASK | ((address & 0xe) << 8),
OCT_CONTROL_REG);
do {
ret = ioread16be(OCT_CONTROL_REG);
} while ((ret & (1<<8)) && time_before(jiffies, stop));
WARN_ON_ONCE(time_after_eq(jiffies, stop));
ret = ioread16be(OCT_DATA_REG);
spin_unlock_irqrestore(&xb->lock, flags);
return ret;
}
void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val)
{
unsigned long flags;
uint16_t ret;
uint16_t highaddress = ((address >> 20) & 0xfff);
uint16_t lowaddress = ((address >> 4) & 0xffff);
unsigned long stop = jiffies + HZ/10;
spin_lock_irqsave(&xb->lock, flags);
iowrite16be(highaddress, OCT_ADDRESS_HIGH_REG);
iowrite16be(lowaddress, OCT_ADDRESS_LOW_REG);
iowrite16be(val, OCT_DATA_REG);
iowrite16be(OCT_INDIRECT_WRITE_MASK | ((address & 0xe) << 8),
OCT_CONTROL_REG);
/* No write should take longer than 100ms */
do {
ret = ioread16be(OCT_CONTROL_REG);
} while ((ret & (1<<8)) && time_before(jiffies, stop));
spin_unlock_irqrestore(&xb->lock, flags);
WARN_ON_ONCE(time_after_eq(jiffies, stop));
}
#ifdef HAVE_RATELIMIT
static DEFINE_RATELIMIT_STATE(_underrun_rl, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
#endif
/* wcxb_reset_dring needs to be called with xb->lock held. */
static void _wcxb_reset_dring(struct wcxb *xb)
{
int x;
struct wcxb_meta_desc *mdesc;
struct wcxb_hw_desc *hdesc = NULL;
xb->dma_head = xb->dma_tail = 0;
if (unlikely(xb->latency > DRING_SIZE)) {
#ifdef HAVE_RATELIMIT
if (__ratelimit(&_underrun_rl)) {
#else
if (printk_ratelimit()) {
#endif
dev_info(&xb->pdev->dev,
"Oops! Tried to increase latency past buffer size.\n");
}
xb->latency = DRING_SIZE;
}
for (x = 0; x < xb->latency; x++) {
dma_addr_t dma_tmp;
mdesc = &xb->meta_dring[x];
hdesc = &xb->hw_dring[x];
hdesc->status = cpu_to_be32(DESC_DEFAULT_STATUS);
if (!mdesc->tx_buf_virt) {
mdesc->tx_buf_virt =
dma_pool_alloc(xb->pool, GFP_ATOMIC, &dma_tmp);
hdesc->tx_buf = cpu_to_be32(dma_tmp);
mdesc->rx_buf_virt =
dma_pool_alloc(xb->pool, GFP_ATOMIC, &dma_tmp);
hdesc->rx_buf = cpu_to_be32(dma_tmp);
}
hdesc->control = cpu_to_be32(DESC_INT|DESC_OWN);
BUG_ON(!mdesc->tx_buf_virt || !mdesc->rx_buf_virt);
}
BUG_ON(!hdesc);
/* Set end of ring bit in last descriptor to force hw to loop around */
hdesc->control |= cpu_to_be32(DESC_EOR);
iowrite32be(xb->hw_dring_phys, xb->membase + TDM_DRING_ADDR);
}
static void wcxb_handle_dma(struct wcxb *xb)
{
struct wcxb_meta_desc *mdesc;
while (!(xb->hw_dring[xb->dma_tail].control & cpu_to_be32(DESC_OWN))) {
u_char *frame;
mdesc = &xb->meta_dring[xb->dma_tail];
frame = mdesc->rx_buf_virt;
xb->ops->handle_receive(xb, frame);
xb->dma_tail =
(xb->dma_tail == xb->latency-1) ? 0 : xb->dma_tail + 1;
mdesc = &xb->meta_dring[xb->dma_head];
frame = mdesc->tx_buf_virt;
xb->ops->handle_transmit(xb, frame);
wmb();
xb->hw_dring[xb->dma_head].control |= cpu_to_be32(DESC_OWN);
xb->dma_head =
(xb->dma_head == xb->latency-1) ? 0 : xb->dma_head + 1;
}
}
static irqreturn_t _wcxb_isr(int irq, void *dev_id)
{
struct wcxb *xb = dev_id;
unsigned int limit = 8;
u32 pending;
pending = ioread32be(xb->membase + ISR);
if (!pending)
return IRQ_NONE;
do {
iowrite32be(pending, xb->membase + IAR);
if (pending & DESC_UNDERRUN) {
u32 reg;
/* bump latency */
spin_lock(&xb->lock);
if (!xb->flags.latency_locked) {
xb->latency++;
#ifdef HAVE_RATELIMIT
if (__ratelimit(&_underrun_rl)) {
#else
if (printk_ratelimit()) {
#endif
dev_info(&xb->pdev->dev,
"Underrun detected by hardware. Latency bumped to: %dms\n",
xb->latency);
}
}
/* re-setup dma ring */
_wcxb_reset_dring(xb);
/* set dma enable bit */
reg = ioread32be(xb->membase + TDM_CONTROL);
reg |= ENABLE_DMA;
iowrite32be(reg, xb->membase + TDM_CONTROL);
spin_unlock(&xb->lock);
}
if (pending & DESC_COMPLETE) {
xb->framecount++;
wcxb_handle_dma(xb);
}
if (NULL != xb->ops->handle_interrupt)
xb->ops->handle_interrupt(xb, pending);
pending = ioread32be(xb->membase + ISR);
} while (pending && --limit);
return IRQ_HANDLED;
}
DAHDI_IRQ_HANDLER(wcxb_isr)
{
irqreturn_t ret;
unsigned long flags;
local_irq_save(flags);
ret = _wcxb_isr(irq, dev_id);
local_irq_restore(flags);
return ret;
}
static int wcxb_alloc_dring(struct wcxb *xb, const char *board_name)
{
xb->meta_dring =
kzalloc(sizeof(struct wcxb_meta_desc) * DRING_SIZE,
GFP_KERNEL);
if (!xb->meta_dring)
return -ENOMEM;
xb->hw_dring = dma_alloc_coherent(&xb->pdev->dev,
sizeof(struct wcxb_hw_desc) * DRING_SIZE,
&xb->hw_dring_phys,
GFP_KERNEL);
if (!xb->hw_dring) {
kfree(xb->meta_dring);
return -ENOMEM;
}
xb->pool = dma_pool_create(board_name, &xb->pdev->dev,
PAGE_SIZE, PAGE_SIZE, 0);
if (!xb->pool) {
kfree(xb->meta_dring);
dma_free_coherent(&xb->pdev->dev,
sizeof(struct wcxb_hw_desc) * DRING_SIZE,
xb->hw_dring,
xb->hw_dring_phys);
return -ENOMEM;
}
return 0;
}
/**
* wcxb_soft_reset - Set interface registers back to known good values.
*
* This represents the normal default state after a reset of the FPGA. This
* function is preferred over the hard reset function.
*
*/
static void wcxb_soft_reset(struct wcxb *xb)
{
/* digium_gpo */
iowrite32be(0x0, xb->membase);
/* xps_intc */
iowrite32be(0x0, xb->membase + 0x300);
iowrite32be(0x0, xb->membase + 0x308);
iowrite32be(0x0, xb->membase + 0x310);
iowrite32be(0x0, xb->membase + 0x31C);
/* xps_spi_config_flash */
iowrite32be(0xA, xb->membase + 0x200);
/* tdm engine */
iowrite32be(0x0, xb->membase + 0x2000);
iowrite32be(0x0, xb->membase + 0x2004);
}
static void _wcxb_hard_reset(struct wcxb *xb)
{
struct pci_dev *const pdev = xb->pdev;
u32 microblaze_version;
unsigned long stop_time = jiffies + msecs_to_jiffies(2000);
pci_save_state(pdev);
iowrite32be(0xe00, xb->membase + TDM_CONTROL);
/* This sleep is to give FPGA time to bring up the PCI/PCIe interface */
msleep(200);
pci_restore_state(pdev);
/* Wait for the Microblaze CPU to complete it's startup */
do {
msleep(20);
/* Can return either 0xffff or 0 before it's fully booted */
microblaze_version = ioread32be(xb->membase + 0x2018) ?: 0xffff;
} while (time_before(jiffies, stop_time)
&& 0xffff == microblaze_version);
}
/*
* Since the FPGA hard reset drops the PCIe link we need to disable
* error reporting on the upsteam link. Otherwise Surprise Down errors
* may be reported in reponse to the link going away.
*
* NOTE: We cannot use pci_disable_pcie_error_reporting() because it will not
* disable error reporting if the system firmware is attached to the advanced
* error reporting mechanism.
*/
static void _wcxb_pcie_hard_reset(struct wcxb *xb)
{
struct pci_dev *const parent = xb->pdev->bus->self;
u32 aer_mask;
int pos;
if (!wcxb_is_pcie(xb))
return;
pos = pci_find_ext_capability(parent, PCI_EXT_CAP_ID_ERR);
if (pos) {
pci_read_config_dword(parent, pos + PCI_ERR_UNCOR_MASK,
&aer_mask);
pci_write_config_dword(parent, pos + PCI_ERR_UNCOR_MASK,
aer_mask | PCI_ERR_UNC_SURPDN);
}
_wcxb_hard_reset(xb);
if (pos) {
pci_write_config_dword(parent, pos + PCI_ERR_UNCOR_MASK,
aer_mask);
/* Clear the error as well from the status register. */
pci_write_config_dword(parent, pos + PCI_ERR_UNCOR_STATUS,
PCI_ERR_UNC_SURPDN);
}
return;
}
/**
* wcxb_hard_reset - Reset FPGA and reload firmware.
*
* This may be called in the context of device probe and therefore the PCI
* device may be locked.
*
*/
static void wcxb_hard_reset(struct wcxb *xb)
{
if (wcxb_is_pcie(xb))
_wcxb_pcie_hard_reset(xb);
else
_wcxb_hard_reset(xb);
}
int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode)
{
int res = 0;
struct pci_dev *pdev = xb->pdev;
u32 tdm_control;
if (pci_enable_device(pdev))
return -EIO;
pci_set_master(pdev);
#ifdef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
xb->flags.is_pcie = pci_find_capability(pdev, PCI_CAP_ID_EXP) ? 1 : 0;
#endif
WARN_ON(!pdev);
if (!pdev)
return -EINVAL;
xb->latency = WCXB_DEFAULT_LATENCY;
spin_lock_init(&xb->lock);
xb->membase = pci_iomap(pdev, 0, 0);
if (pci_request_regions(pdev, board_name))
dev_info(&xb->pdev->dev, "Unable to request regions\n");
wcxb_soft_reset(xb);
res = wcxb_alloc_dring(xb, board_name);
if (res) {
dev_err(&xb->pdev->dev,
"Failed to allocate descriptor rings.\n");
goto fail_exit;
}
/* Enable writes to fpga status register */
iowrite32be(0, xb->membase + 0x04);
xb->flags.have_msi = (int_mode) ? 0 : (0 == pci_enable_msi(pdev));
if (request_irq(pdev->irq, wcxb_isr,
(xb->flags.have_msi) ? 0 : DAHDI_IRQ_SHARED,
board_name, xb)) {
dev_notice(&xb->pdev->dev, "Unable to request IRQ %d\n",
pdev->irq);
res = -EIO;
goto fail_exit;
}
iowrite32be(0, xb->membase + TDM_CONTROL);
tdm_control = ioread32be(xb->membase + TDM_CONTROL);
if (!(tdm_control & 0x20)) {
dev_err(&xb->pdev->dev,
"This board is not authenticated and may not function properly.\n");
msleep(1000);
} else {
dev_dbg(&xb->pdev->dev, "Authenticated. %08x\n", tdm_control);
}
return res;
fail_exit:
pci_release_regions(xb->pdev);
return res;
}
void wcxb_stop_dma(struct wcxb *xb)
{
unsigned long flags;
u32 reg;
/* Quiesce DMA engine interrupts */
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase + TDM_CONTROL);
reg &= ~ENABLE_DMA;
iowrite32be(reg, xb->membase + TDM_CONTROL);
spin_unlock_irqrestore(&xb->lock, flags);
}
int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms)
{
unsigned long stop;
stop = jiffies + msecs_to_jiffies(timeout_ms);
do {
if (time_after(jiffies, stop))
return -EIO;
else
cpu_relax();
} while (!wcxb_is_stopped(xb));
return 0;
}
void wcxb_disable_interrupts(struct wcxb *xb)
{
iowrite32be(0, xb->membase + IER);
}
void wcxb_stop(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
/* Stop everything */
iowrite32be(0, xb->membase + TDM_CONTROL);
iowrite32be(0, xb->membase + IER);
iowrite32be(0, xb->membase + MER);
iowrite32be(-1, xb->membase + IAR);
/* Flush quiesce commands before exit */
ioread32be(xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
synchronize_irq(xb->pdev->irq);
}
bool wcxb_is_stopped(struct wcxb *xb)
{
return !(ioread32be(xb->membase + TDM_CONTROL) & DMA_RUNNING);
}
static void wcxb_free_dring(struct wcxb *xb)
{
struct wcxb_meta_desc *mdesc;
struct wcxb_hw_desc *hdesc;
int i;
/* Free tx/rx buffs */
for (i = 0; i < DRING_SIZE; i++) {
mdesc = &xb->meta_dring[i];
hdesc = &xb->hw_dring[i];
if (mdesc->tx_buf_virt) {
dma_pool_free(xb->pool,
mdesc->tx_buf_virt,
be32_to_cpu(hdesc->tx_buf));
dma_pool_free(xb->pool,
mdesc->rx_buf_virt,
be32_to_cpu(hdesc->rx_buf));
}
}
dma_pool_destroy(xb->pool);
dma_free_coherent(&xb->pdev->dev,
sizeof(struct wcxb_hw_desc) * DRING_SIZE,
xb->hw_dring,
xb->hw_dring_phys);
kfree(xb->meta_dring);
}
void wcxb_release(struct wcxb *xb)
{
wcxb_stop(xb);
synchronize_irq(xb->pdev->irq);
free_irq(xb->pdev->irq, xb);
if (xb->flags.have_msi)
pci_disable_msi(xb->pdev);
if (xb->membase)
pci_iounmap(xb->pdev, xb->membase);
wcxb_free_dring(xb);
pci_release_regions(xb->pdev);
pci_disable_device(xb->pdev);
return;
}
int wcxb_start(struct wcxb *xb)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
_wcxb_reset_dring(xb);
/* Enable hardware interrupts */
iowrite32be(-1, xb->membase + IAR);
iowrite32be(DESC_UNDERRUN|DESC_COMPLETE, xb->membase + IER);
/* iowrite32be(0x3f7, xb->membase + IER); */
iowrite32be(MER_ME|MER_HIE, xb->membase + MER);
/* Start the DMA engine processing. */
reg = ioread32be(xb->membase + TDM_CONTROL);
reg |= ENABLE_DMA;
iowrite32be(reg, xb->membase + TDM_CONTROL);
spin_unlock_irqrestore(&xb->lock, flags);
return 0;
}
struct wcxb_meta_block {
__le32 chksum;
__le32 version;
__le32 size;
} __packed;
struct wcxb_firm_header {
u8 header[6];
__le32 chksum;
u8 pad[18];
__le32 version;
} __packed;
static u32 wcxb_get_firmware_version(struct wcxb *xb)
{
u32 version = 0;
/* Two version registers are read and catenated into one */
/* Firmware version goes in bits upper byte */
version = ((ioread32be(xb->membase + 0x400) & 0xffff)<<16);
/* Microblaze version goes in lower word */
version += ioread32be(xb->membase + 0x2018);
return version;
}
static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
const char *filename)
{
u32 tdm_control;
static const int APPLICATION_ADDRESS = 0x200000;
static const int META_BLOCK_OFFSET = 0x170000;
static const int ERASE_BLOCK_SIZE = 0x010000;
static const int END_OFFSET = APPLICATION_ADDRESS + META_BLOCK_OFFSET +
ERASE_BLOCK_SIZE;
struct wcxb_spi_master *flash_spi_master;
struct wcxb_spi_device *flash_spi_device;
struct wcxb_meta_block meta;
int offset;
struct wcxb_firm_header *head = (struct wcxb_firm_header *)(fw->data);
if (fw->size > (META_BLOCK_OFFSET + sizeof(*head))) {
dev_err(&xb->pdev->dev,
"Firmware is too large to fit in available space.\n");
return -EINVAL;
}
meta.size = cpu_to_le32(fw->size);
meta.version = head->version;
meta.chksum = head->chksum;
flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev,
xb->membase + FLASH_SPI_BASE,
false);
flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0);
dev_info(&xb->pdev->dev,
"Uploading %s. This can take up to 30 seconds.\n", filename);
/* First erase all the blocks in the application area. */
offset = APPLICATION_ADDRESS;
while (offset < END_OFFSET) {
wcxb_flash_sector_erase(flash_spi_device, offset);
offset += ERASE_BLOCK_SIZE;
}
/* Then write the new firmware file. */
wcxb_flash_write(flash_spi_device, APPLICATION_ADDRESS,
&fw->data[sizeof(struct wcxb_firm_header)],
fw->size - sizeof(struct wcxb_firm_header));
/* Finally, update the meta block. */
wcxb_flash_write(flash_spi_device,
APPLICATION_ADDRESS + META_BLOCK_OFFSET,
&meta, sizeof(meta));
/* Reset fpga after loading firmware */
dev_info(&xb->pdev->dev, "Firmware load complete. Reseting device.\n");
tdm_control = ioread32be(xb->membase + TDM_CONTROL);
wcxb_hard_reset(xb);
iowrite32be(0, xb->membase + 0x04);
iowrite32be(tdm_control, xb->membase + TDM_CONTROL);
wcxb_spi_device_destroy(flash_spi_device);
wcxb_spi_master_destroy(flash_spi_master);
return 0;
}
int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
const char *firmware_filename, bool force_firmware)
{
const struct firmware *fw;
const struct wcxb_firm_header *header;
int res = 0;
u32 crc;
u32 version = 0;
version = wcxb_get_firmware_version(xb);
if (0xff000000 == (version & 0xff000000)) {
dev_info(&xb->pdev->dev,
"Invalid firmware %x. Please check your hardware.\n",
version);
return -EIO;
}
if ((expected_version == version) && !force_firmware) {
dev_info(&xb->pdev->dev, "Firmware version: %x\n", version);
return 0;
}
if (force_firmware) {
dev_info(&xb->pdev->dev,
"force_firmware module parameter is set. Forcing firmware load, regardless of version\n");
} else {
dev_info(&xb->pdev->dev,
"Firmware version %x is running, but we require version %x.\n",
version, expected_version);
}
res = request_firmware(&fw, firmware_filename, &xb->pdev->dev);
if (res) {
dev_info(&xb->pdev->dev,
"Firmware '%s' not available from userspace.\n",
firmware_filename);
goto cleanup;
}
header = (const struct wcxb_firm_header *)fw->data;
/* Check the crc */
crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0;
if (memcmp("DIGIUM", header->header, sizeof(header->header)) ||
(le32_to_cpu(header->chksum) != crc)) {
dev_info(&xb->pdev->dev,
"%s is invalid. Please reinstall.\n",
firmware_filename);
goto cleanup;
}
/* Check the file vs required firmware versions */
if (le32_to_cpu(header->version) != expected_version) {
dev_err(&xb->pdev->dev,
"Existing firmware file %s is version %x, but we require %x. Please install the correct firmware file.\n",
firmware_filename, le32_to_cpu(header->version),
expected_version);
res = -EIO;
goto cleanup;
}
dev_info(&xb->pdev->dev, "Found %s (version: %x) Preparing for flash\n",
firmware_filename, header->version);
res = wcxb_update_firmware(xb, fw, firmware_filename);
version = wcxb_get_firmware_version(xb);
dev_info(&xb->pdev->dev, "Reset into firmware version: %x\n", version);
if ((expected_version != version) && !force_firmware) {
/* On the off chance that the interface is in a state where it
* cannot boot into the updated firmware image, power cycling
* the card can recover. A simple "reset" of the computer is not
* sufficient, power has to be removed completely. */
dev_err(&xb->pdev->dev,
"The wrong firmware is running after update. Please power cycle and try again.\n");
res = -EIO;
goto cleanup;
}
if (res) {
dev_info(&xb->pdev->dev,
"Failed to load firmware %s\n", firmware_filename);
}
cleanup:
release_firmware(fw);
return res;
}

View File

@@ -1,184 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __WCXB_H__
#define __WCXB_H__
#define WCXB_DEFAULT_LATENCY 3U
#define WCXB_DEFAULT_MAXLATENCY 20U
#define WCXB_DMA_CHAN_SIZE 128
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
/* The is_pcie member was backported but I'm not sure in which version. */
# ifndef RHEL_RELEASE_VERSION
#define WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
# endif
#else
#endif
struct wcxb;
struct wcxb_operations {
void (*handle_receive)(struct wcxb *xb, void *frame);
void (*handle_transmit)(struct wcxb *xb, void *frame);
void (*handle_error)(struct wcxb *xb);
void (*handle_interrupt)(struct wcxb *xb, u32 pending);
};
struct wcxb_meta_desc;
struct wcxb_hw_desc;
struct wcxb {
struct pci_dev *pdev;
spinlock_t lock;
const struct wcxb_operations *ops;
unsigned int *debug;
unsigned int max_latency;
unsigned int latency;
struct {
u32 have_msi:1;
u32 latency_locked:1;
u32 drive_timing_cable:1;
#ifdef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
u32 is_pcie:1;
#endif
} flags;
void __iomem *membase;
struct wcxb_meta_desc *meta_dring;
struct wcxb_hw_desc *hw_dring;
unsigned int dma_head;
unsigned int dma_tail;
dma_addr_t hw_dring_phys;
struct dma_pool *pool;
unsigned long framecount;
};
extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode);
extern void wcxb_release(struct wcxb *xb);
extern int wcxb_start(struct wcxb *xb);
extern void wcxb_stop(struct wcxb *xb);
extern int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms);
extern bool wcxb_is_stopped(struct wcxb *xb);
enum wcxb_clock_sources {
WCXB_CLOCK_SELF, /* Use the internal oscillator for timing. */
WCXB_CLOCK_RECOVER, /* Recover the clock from a framer. */
#ifdef RPC_RCLK
WCXB_CLOCK_RECOVER_ALT, /* Recover the clock from a framer. */
#endif
WCXB_CLOCK_SLAVE /* Recover clock from any timing header. */
};
extern enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb);
extern void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc);
static inline void wcxb_enable_timing_header_driver(struct wcxb *xb)
{
xb->flags.drive_timing_cable = 1;
}
static inline bool wcxb_is_timing_header_driver_enabled(struct wcxb *xb)
{
return 1 == xb->flags.drive_timing_cable;
}
static inline void wcxb_disable_timing_header_driver(struct wcxb *xb)
{
xb->flags.drive_timing_cable = 0;
}
extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
const char *firmware_filename,
bool force_firmware);
extern void wcxb_stop_dma(struct wcxb *xb);
extern void wcxb_disable_interrupts(struct wcxb *xb);
static inline void wcxb_gpio_set(struct wcxb *xb, u32 bits)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be(reg | bits, xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void wcxb_gpio_clear(struct wcxb *xb, u32 bits)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be(reg & (~bits), xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_set_maxlatency(struct wcxb *xb, unsigned int max_latency)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->max_latency = clamp(max_latency,
xb->latency,
WCXB_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_set_minlatency(struct wcxb *xb, unsigned int min_latency)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->latency = clamp(min_latency, WCXB_DEFAULT_LATENCY,
WCXB_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_lock_latency(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->flags.latency_locked = 1;
spin_unlock_irqrestore(&xb->lock, flags);
return;
}
static inline void
wcxb_unlock_latency(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->flags.latency_locked = 0;
spin_unlock_irqrestore(&xb->lock, flags);
return;
}
/* Interface for the echocan block */
extern void wcxb_enable_echocan(struct wcxb *xb);
extern void wcxb_disable_echocan(struct wcxb *xb);
extern void wcxb_reset_echocan(struct wcxb *xb);
extern void wcxb_enable_echocan_dram(struct wcxb *xb);
extern bool wcxb_is_echocan_present(struct wcxb *xb);
extern u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address);
extern void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val);
#endif

View File

@@ -1,170 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/sched.h>
#include "wcxb_spi.h"
#include "wcxb_flash.h"
#define FLASH_PAGE_PROGRAM 0x02
#define FLASH_READ 0x03
#define FLASH_READ_STATUS 0x05
#define FLASH_WRITE_ENABLE 0x06
#define FLASH_SECTOR_ERASE 0xd8
static int wcxb_flash_read_status_register(struct wcxb_spi_device *spi,
u8 *status)
{
u8 command[] = {
FLASH_READ_STATUS,
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_serial = {
.rx_buf = status,
.len = 1,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_serial, &m);
return wcxb_spi_sync(spi, &m);
}
int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address,
void *data, size_t len)
{
u8 command[] = {
FLASH_READ,
(address & 0xff0000) >> 16,
(address & 0xff00) >> 8,
(address & 0xff)
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_serial = {
.rx_buf = data,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_serial, &m);
return wcxb_spi_sync(spi, &m);
}
static int wcxb_flash_wait_until_not_busy(struct wcxb_spi_device *spi)
{
int res;
u8 status;
unsigned long stop = jiffies + 5*HZ;
do {
res = wcxb_flash_read_status_register(spi, &status);
} while (!res && (status & 0x1) && time_before(jiffies, stop));
if (!res)
return res;
if (time_after_eq(jiffies, stop))
return -EIO;
return 0;
}
static int wcxb_flash_write_enable(struct wcxb_spi_device *spi)
{
u8 command = FLASH_WRITE_ENABLE;
return wcxb_spi_write(spi, &command, 1);
}
int wcxb_flash_sector_erase(struct wcxb_spi_device *spi,
unsigned int address)
{
int res;
u8 command[] = {FLASH_SECTOR_ERASE, (address >> 16)&0xff, 0x00, 0x00};
/* Sector must be on 64KB boundary. */
if (address & 0xffff)
return -EINVAL;
/* Start the erase. */
res = wcxb_flash_write_enable(spi);
if (res)
return res;
res = wcxb_spi_write(spi, &command, sizeof(command));
if (res)
return res;
return wcxb_flash_wait_until_not_busy(spi);
}
int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address,
const void *data, size_t len)
{
int res;
const size_t FLASH_PAGE_SIZE = 256;
u8 command[] = {
FLASH_PAGE_PROGRAM,
(address & 0xff0000) >> 16,
(address & 0xff00) >> 8,
0x00,
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_data = {
.tx_buf = data,
.len = len,
};
struct wcxb_spi_message m;
/* We need to write on page size boundaries */
WARN_ON(address & 0xff);
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_data, &m);
while (len) {
res = wcxb_flash_write_enable(spi);
if (res)
return res;
command[1] = (address >> 16) & 0xff;
command[2] = (address >> 8) & 0xff;
t_data.tx_buf = data;
t_data.len = min(len, FLASH_PAGE_SIZE);
res = wcxb_spi_sync(spi, &m);
WARN_ON(res);
if (res)
return res;
res = wcxb_flash_wait_until_not_busy(spi);
WARN_ON(res);
if (res)
return res;
len -= t_data.len;
address += t_data.len;
data += t_data.len;
}
return 0;
}

View File

@@ -1,34 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __WCXB_FLASH_H__
#define __WCXB_FLASH_H__
extern int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address,
void *data, size_t len);
extern int wcxb_flash_sector_erase(struct wcxb_spi_device *spi, unsigned int
address);
extern int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address,
const void *data, size_t len);
#endif

View File

@@ -1,386 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <dahdi/kernel.h>
#include "wcxb_spi.h"
#define BBIT(n) (1UL << (31UL - (n)))
#define SPISRR 0x40
#define SPISRR_RESET 0x0000000a /* Resets Device */
#define SPICR 0x60
#define SPICR_LSB_FIRST BBIT(22) /* LSB First. 0=MSB first transfer */
#define SPICR_MASTER_INHIBIT BBIT(23) /* Master Transaction Inhibit */
#define SPICR_SLAVE_SELECT BBIT(24) /* Manual Slave Select Assert Enable */
#define SPICR_RX_FIFO_RESET BBIT(25) /* Receive FIFO Reset */
#define SPICR_TX_FIFO_RESET BBIT(26) /* Transmit FIFO Reset */
#define SPICR_CPHA BBIT(27) /* Clock Phase */
#define SPICR_CPOL BBIT(28) /* Clock Polarity 0=Active High */
#define SPICR_MASTER BBIT(29) /* Master Enable */
#define SPICR_SPE BBIT(30) /* SPI System Enable */
#define SPICR_LOOP BBIT(31) /* Local Loopback Mode */
#define SPICR_START_TRANSFER (SPICR_CPHA | SPICR_CPOL | \
SPICR_MASTER | SPICR_SPE)
#define SPICR_READY_TRANSFER (SPICR_MASTER_INHIBIT | SPICR_START_TRANSFER)
#define SPISR 0x64 /* SPI Status Register */
#define SPISR_SLAVE_MODE_SEL BBIT(26) /* Slave Mode Select Flag */
#define SPISR_MODF BBIT(27) /* Mode-Fault Error Flag */
#define SPISR_TX_FULL BBIT(28) /* Transmit FIFO Full */
#define SPISR_TX_EMPTY BBIT(29) /* Transmit FIFO Empty */
#define SPISR_RX_FULL BBIT(30) /* Receive FIFO Full */
#define SPISR_RX_EMPTY BBIT(31) /* Receive FIFO Empty */
#define SPIDTR 0x68 /* SPI Data Transmit Register */
#define SPIDRR 0x6c /* SPI Data Receive Register */
#define SPISSR 0x70 /* SPI Slave Select Register */
#undef SUCCESS
#define SUCCESS 0
struct wcxb_spi_master {
struct device *parent;
struct list_head message_queue;
spinlock_t lock;
void __iomem *base;
struct wcxb_spi_message *cur_msg;
struct wcxb_spi_transfer *cur_transfer;
u16 bytes_left;
u16 bytes_in_fifo;
const u8 *cur_tx_byte;
u8 *cur_rx_byte;
u16 auto_cs:1;
};
static inline void _wcxb_assert_chip_select(struct wcxb_spi_master *master,
unsigned int cs)
{
const int cs_mask = ~(1UL << cs);
iowrite32be(cs_mask, master->base + SPISSR);
ioread32be(master->base + SPISSR);
}
static inline void _wcxb_clear_chip_select(struct wcxb_spi_master *master)
{
iowrite32be(~(0), master->base + SPISSR);
ioread32(master->base + SPISSR);
}
static inline void wcxb_spi_reset_controller(struct wcxb_spi_master *master)
{
u32 spicr = SPICR_READY_TRANSFER;
spicr |= (master->auto_cs) ? 0 : SPICR_SLAVE_SELECT;
iowrite32be(SPISRR_RESET, master->base + SPISRR);
iowrite32be(spicr, master->base + SPICR);
iowrite32be(0xffffffff, master->base + SPISSR);
}
struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent,
void __iomem *membase,
bool auto_cs)
{
struct wcxb_spi_master *master = NULL;
master = kzalloc(sizeof(struct wcxb_spi_master), GFP_KERNEL);
if (!master)
goto error_exit;
spin_lock_init(&master->lock);
INIT_LIST_HEAD(&master->message_queue);
master->base = membase;
master->parent = parent;
master->auto_cs = (auto_cs) ? 1 : 0;
wcxb_spi_reset_controller(master);
return master;
error_exit:
kfree(master);
return NULL;
}
void wcxb_spi_master_destroy(struct wcxb_spi_master *master)
{
struct wcxb_spi_message *m;
if (!master)
return;
while (!list_empty(&master->message_queue)) {
m = list_first_entry(&master->message_queue,
struct wcxb_spi_message, node);
list_del(&m->node);
if (m->complete)
m->complete(m->arg);
}
kfree(master);
return;
}
static inline bool is_txfifo_empty(const struct wcxb_spi_master *master)
{
return ((ioread32(master->base + SPISR) &
cpu_to_be32(SPISR_TX_EMPTY)) > 0);
}
static const u8 DUMMY_TX = 0xff;
static u8 DUMMY_RX;
static void _wcxb_spi_transfer_to_fifo(struct wcxb_spi_master *master)
{
const unsigned int FIFO_SIZE = 16;
u32 spicr;
while (master->bytes_left && master->bytes_in_fifo < FIFO_SIZE) {
iowrite32be(*master->cur_tx_byte, master->base + SPIDTR);
master->bytes_in_fifo++;
master->bytes_left--;
if (&DUMMY_TX != master->cur_tx_byte)
master->cur_tx_byte++;
}
spicr = (master->auto_cs) ? SPICR_START_TRANSFER :
SPICR_START_TRANSFER | SPICR_SLAVE_SELECT;
iowrite32be(spicr, master->base + SPICR);
}
static void _wcxb_spi_transfer_from_fifo(struct wcxb_spi_master *master)
{
u32 spicr;
while (master->bytes_in_fifo) {
*master->cur_rx_byte = ioread32be(master->base + SPIDRR);
if (&DUMMY_RX != master->cur_rx_byte)
master->cur_rx_byte++;
--master->bytes_in_fifo;
}
spicr = SPICR_START_TRANSFER;
spicr |= (master->auto_cs) ? 0 : SPICR_SLAVE_SELECT;
iowrite32be(spicr | SPICR_MASTER_INHIBIT, master->base + SPICR);
}
static void _wcxb_spi_start_transfer(struct wcxb_spi_master *master,
struct wcxb_spi_transfer *t)
{
#ifdef DEBUG
if (!t || !master || (!t->tx_buf && !t->rx_buf) ||
master->cur_transfer) {
WARN_ON(1);
return;
}
#endif
master->cur_transfer = t;
master->bytes_left = t->len;
master->cur_tx_byte = (t->tx_buf) ?: &DUMMY_TX;
master->cur_rx_byte = (t->rx_buf) ?: &DUMMY_RX;
_wcxb_spi_transfer_to_fifo(master);
}
/**
* _wcxb_spi_start_message - Start a new message transferring.
*
* Must be called with master->lock held.
*
*/
static int _wcxb_spi_start_message(struct wcxb_spi_master *master,
struct wcxb_spi_message *message)
{
struct wcxb_spi_transfer *t;
if (master->cur_msg) {
/* There is already a message in progress. Queue for later. */
list_add_tail(&message->node, &master->message_queue);
return 0;
}
if (!message->spi) {
dev_dbg(master->parent,
"Queueing message without SPI device specified?\n");
return -EINVAL;
};
master->cur_msg = message;
_wcxb_assert_chip_select(master, message->spi->chip_select);
t = list_first_entry(&message->transfers,
struct wcxb_spi_transfer, node);
_wcxb_spi_start_transfer(master, t);
return 0;
}
/**
* wcxb_spi_complete_message - Complete the current message.
*
* Called after all transfers in current message have been completed. This will
* complete the current message and start the next queued message if there are
* any.
*
* Must be called with the master->lock held.
*
*/
static void _wcxb_spi_complete_cur_msg(struct wcxb_spi_master *master)
{
struct wcxb_spi_message *message;
if (!master->cur_msg)
return;
message = master->cur_msg;
message->status = SUCCESS;
_wcxb_clear_chip_select(master);
master->cur_msg = NULL;
if (!list_empty(&master->message_queue)) {
message = list_first_entry(&master->message_queue,
struct wcxb_spi_message, node);
list_del(&message->node);
_wcxb_spi_start_message(master, message);
}
return;
}
static inline bool
_wcxb_spi_is_last_transfer(const struct wcxb_spi_transfer *t,
const struct wcxb_spi_message *message)
{
return t->node.next == &message->transfers;
}
static inline struct wcxb_spi_transfer *
_wcxb_spi_next_transfer(struct wcxb_spi_transfer *t)
{
return list_entry(t->node.next, struct wcxb_spi_transfer, node);
}
/**
* wcxb_spi_handle_interrupt - Drives the transfers forward.
*
* Doesn't necessarily need to be called in the context of a real interrupt, but
* should be called with interrupts disabled on the local CPU.
*
*/
void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master)
{
struct wcxb_spi_message *msg;
struct wcxb_spi_transfer *t;
void (*complete)(void *arg) = NULL;
unsigned long flags;
/* Check if we're not in the middle of a transfer, or not finished with
* a part of one. */
spin_lock_irqsave(&master->lock, flags);
t = master->cur_transfer;
msg = master->cur_msg;
if (!msg || !is_txfifo_empty(master))
goto done;
#ifdef DEBUG
if (!t) {
dev_dbg(master->parent,
"No current transfer in %s\n", __func__);
goto done;
}
#endif
/* First read any data out of the receive FIFO into the current
* transfer. */
_wcxb_spi_transfer_from_fifo(master);
if (master->bytes_left) {
/* The current transfer isn't finished. */
_wcxb_spi_transfer_to_fifo(master);
goto done;
}
/* The current transfer is finished. Check for another transfer in this
* message or complete it and look for another message to start. */
master->cur_transfer = NULL;
if (_wcxb_spi_is_last_transfer(t, msg)) {
complete = msg->complete;
_wcxb_spi_complete_cur_msg(master);
} else {
t = _wcxb_spi_next_transfer(t);
_wcxb_spi_start_transfer(master, t);
}
done:
spin_unlock_irqrestore(&master->lock, flags);
/* Do not call the complete call back under the bus lock. */
if (complete)
complete(msg->arg);
return;
}
int wcxb_spi_async(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message)
{
int res;
unsigned long flags;
WARN_ON(!spi || !message || !spi->master);
if (list_empty(&message->transfers)) {
/* No transfers in this message? */
if (message->complete)
message->complete(message->arg);
message->status = -EINVAL;
return 0;
}
message->status = -EINPROGRESS;
message->spi = spi;
spin_lock_irqsave(&spi->master->lock, flags);
res = _wcxb_spi_start_message(spi->master, message);
spin_unlock_irqrestore(&spi->master->lock, flags);
return res;
}
static void wcxb_spi_complete_message(void *arg)
{
complete((struct completion *)arg);
}
int wcxb_spi_sync(struct wcxb_spi_device *spi, struct wcxb_spi_message *message)
{
DECLARE_COMPLETION_ONSTACK(done);
WARN_ON(!spi || !spi->master);
message->complete = wcxb_spi_complete_message;
message->arg = &done;
wcxb_spi_async(spi, message);
/* TODO: There has got to be a better way to do this. */
while (!try_wait_for_completion(&done)) {
wcxb_spi_handle_interrupt(spi->master);
cpu_relax();
}
return message->status;
}

View File

@@ -1,116 +0,0 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef __WCXB_SPI_H
#define __WCXB_SPI_H
#include <linux/spi/spi.h>
#include <stdbool.h>
struct wcxb_spi_transfer {
const void *tx_buf;
void *rx_buf;
u32 len:16;
u16 delay_usecs;
struct list_head node;
};
struct wcxb_spi_message {
struct list_head transfers;
struct list_head node;
struct wcxb_spi_device *spi;
void (*complete)(void *arg);
void *arg;
int status;
};
struct wcxb_spi_master;
struct wcxb_spi_device {
struct wcxb_spi_master *master;
u16 chip_select;
};
extern struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent,
void __iomem *base, bool auto_cs);
extern void wcxb_spi_master_destroy(struct wcxb_spi_master *master);
extern int wcxb_spi_sync(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message);
extern int wcxb_spi_async(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message);
extern void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master);
static inline struct wcxb_spi_device *
wcxb_spi_device_create(struct wcxb_spi_master *master, u16 chip_select)
{
struct wcxb_spi_device *spi = kzalloc(sizeof(*spi), GFP_KERNEL);
if (!spi)
return NULL;
spi->master = master;
spi->chip_select = chip_select;
return spi;
}
static inline void wcxb_spi_device_destroy(struct wcxb_spi_device *spi)
{
kfree(spi);
}
static inline void wcxb_spi_message_init(struct wcxb_spi_message *m)
{
memset(m, 0, sizeof(*m));
INIT_LIST_HEAD(&m->transfers);
}
static inline void wcxb_spi_message_add_tail(struct wcxb_spi_transfer *t,
struct wcxb_spi_message *m)
{
list_add_tail(&t->node, &m->transfers);
}
static inline int
wcxb_spi_write(struct wcxb_spi_device *spi, const void *buffer, size_t len)
{
struct wcxb_spi_transfer t = {
.tx_buf = buffer,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t, &m);
return wcxb_spi_sync(spi, &m);
}
static inline int
wcxb_spi_read(struct wcxb_spi_device *spi, void *buffer, size_t len)
{
struct wcxb_spi_transfer t = {
.rx_buf = buffer,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t, &m);
return wcxb_spi_sync(spi, &m);
}
#endif

View File

@@ -654,95 +654,6 @@ static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
CALL_PHONE_METHOD(card_pcm_recompute, xpd, priv->search_fsk_pattern);
}
struct ring_reg_param {
int is_indirect;
int regno;
uint8_t h_val;
uint8_t l_val;
};
enum ring_types {
RING_TYPE_NEON = 0,
RING_TYPE_TRAPEZ,
RING_TYPE_NORMAL,
};
struct byte_pair {
uint8_t h_val;
uint8_t l_val;
};
struct ring_reg_params {
const int is_indirect;
const int regno;
struct byte_pair values[1 + RING_TYPE_NORMAL - RING_TYPE_NEON];
};
#define REG_ENTRY(di, reg, vh1, vl1, vh2, vl2, vh3, vl3) \
{ (di), (reg), .values = { \
[RING_TYPE_NEON] = { .h_val = (vh1), .l_val = (vl1) }, \
[RING_TYPE_TRAPEZ] = { .h_val = (vh2), .l_val = (vl2) }, \
[RING_TYPE_NORMAL] = { .h_val = (vh3), .l_val = (vl3) }, \
}, \
}
static struct ring_reg_params ring_parameters[] = {
/* INDIR REG NEON TRAPEZ NORMAL */
REG_ENTRY(1, 0x16, 0xE8, 0x03, 0xC8, 0x00, 0x00, 0x00),
REG_ENTRY(1, 0x15, 0xEF, 0x7B, 0xAB, 0x5E, 0x77, 0x01),
REG_ENTRY(1, 0x14, 0x9F, 0x00, 0x8C, 0x01, 0xFD, 0x7E),
REG_ENTRY(0, 0x22, 0x00, 0x19, 0x00, 0x01, 0x00, 0x00),
REG_ENTRY(0, 0x30, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(0, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(0, 0x32, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(0, 0x33, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(1, 0x1D, 0x00, 0x46, 0x00, 0x36, 0x00, 0x36),
};
static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
enum ring_types rtype)
{
const struct ring_reg_params *p;
const struct byte_pair *v;
int ret = 0;
int i;
if (rtype < RING_TYPE_NEON || rtype > RING_TYPE_NORMAL)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
p = &ring_parameters[i];
v = &(p->values[rtype]);
if (p->is_indirect) {
LINE_DBG(REGS, xpd, pos,
"[%d] 0x%02X: I 0x%02X 0x%02X\n",
i, p->regno, v->h_val, v->l_val);
ret = SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
p->regno, v->h_val, v->l_val);
if (ret < 0) {
LINE_ERR(xpd, pos,
"Failed: 0x%02X: I 0x%02X, 0x%02X\n",
p->regno, v->h_val, v->l_val);
break;
}
} else {
LINE_DBG(REGS, xpd, pos, "[%d] 0x%02X: D 0x%02X\n",
i, p->regno, v->l_val);
ret = SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
p->regno, v->l_val);
if (ret < 0) {
LINE_ERR(xpd, pos,
"Failed: 0x%02X: D 0x%02X\n",
p->regno, v->l_val);
break;
}
}
}
return ret;
}
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
unsigned int msg_waiting)
{
@@ -756,15 +667,81 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
/* A write to register 0x40 will now turn on/off the VM led */
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
BIT_SET(priv->neon_blinking, pos);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NEON);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
0xE8, 0x03);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
0xEF, 0x7B);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
0x9F, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
0x00, 0x46);
} else if (ring_trapez) {
LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_TRAPEZ);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
0xC8, 0x00);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
0xAB, 0x5E);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
0x8C, 0x01);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x01);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
0x00, 0x36);
} else {
/* A write to register 0x40 will now turn on/off the ringer */
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
BIT_CLR(priv->neon_blinking, pos);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NORMAL);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x16, 0x00, 0x00);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x15, 0x77, 0x01);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x14, 0xFD, 0x7E);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x22, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x30, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x31, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x32, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x33, 0x00);
/* High Vbat~ -82V[Dc] */
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x4A, 0x34);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x1D, 0x00, 0x36);
}
return (ret ? -EPROTO : 0);
}
@@ -1861,134 +1838,9 @@ static const struct file_operations proc_xpd_metering_ops = {
#endif
#endif
static DEVICE_ATTR_READER(fxs_ring_registers_show, dev, buf)
{
xpd_t *xpd;
struct FXS_priv_data *priv;
unsigned long flags;
const struct ring_reg_params *p;
const struct byte_pair *v;
enum ring_types rtype;
int len = 0;
int i;
BUG_ON(!dev);
xpd = dev_to_xpd(dev);
if (!xpd)
return -ENODEV;
priv = xpd->priv;
BUG_ON(!priv);
spin_lock_irqsave(&xpd->lock, flags);
len += sprintf(buf + len, "# Reg#: D/I\tNEON \tTRAPEZ \tNORMAL \n");
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
p = &ring_parameters[i];
len += sprintf(buf + len, "[%d] 0x%02X: %c",
i, p->regno, (p->is_indirect) ? 'I' : 'D');
for (rtype = RING_TYPE_NEON; rtype <= RING_TYPE_NORMAL; rtype++) {
v = &(p->values[rtype]);
if (p->is_indirect)
len += sprintf(buf + len, "\t0x%02X 0x%02X",
v->h_val, v->l_val);
else
len += sprintf(buf + len, "\t0x%02X ----",
v->l_val);
}
len += sprintf(buf + len, "\n");
}
spin_unlock_irqrestore(&xpd->lock, flags);
return len;
}
static DEVICE_ATTR_WRITER(fxs_ring_registers_store, dev, buf, count)
{
xpd_t *xpd;
struct FXS_priv_data *priv;
unsigned long flags;
char rtype_name[MAX_PROC_WRITE];
enum ring_types rtype;
struct ring_reg_params *params;
struct byte_pair *v;
int regno;
int h_val;
int l_val;
int ret;
int i;
BUG_ON(!dev);
xpd = dev_to_xpd(dev);
if (!xpd)
return -ENODEV;
priv = xpd->priv;
BUG_ON(!priv);
ret = sscanf(buf, "%10s %X %X %X\n",
rtype_name, &regno, &h_val, &l_val);
if (ret < 3 || ret > 4) {
XPD_ERR(xpd, "Bad input: '%s'\n", buf);
XPD_ERR(xpd, "# Correct input\n");
XPD_ERR(xpd, "{NEON|TRAPEZ|NORMAL} <regno> <byte> [<byte>]\n");
goto invalid_input;
}
if (strcasecmp("NEON", rtype_name) == 0)
rtype = RING_TYPE_NEON;
else if (strcasecmp("TRAPEZ", rtype_name) == 0)
rtype = RING_TYPE_TRAPEZ;
else if (strcasecmp("NORMAL", rtype_name) == 0)
rtype = RING_TYPE_NORMAL;
else {
XPD_ERR(xpd, "Unknown ring type '%s' (NEON/TRAPEZ/NORMAL)\n",
rtype_name);
goto invalid_input;
}
params = NULL;
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
if (ring_parameters[i].regno == regno) {
params = &ring_parameters[i];
break;
}
}
if (!params) {
XPD_ERR(xpd, "Bad register 0x%X\n", regno);
goto invalid_input;
}
if (params->is_indirect) {
if (ret != 4) {
XPD_ERR(xpd,
"Missing low-byte (0x%X is indirect register)\n",
regno);
goto invalid_input;
}
XPD_INFO(xpd, "%s Indirect 0x%X <=== 0x%X 0x%X\n",
rtype_name, regno, h_val, l_val);
} else {
if (ret != 3) {
XPD_ERR(xpd,
"Should give exactly one value (0x%X is direct register)\n",
regno);
goto invalid_input;
}
l_val = h_val;
h_val = 0;
XPD_INFO(xpd, "%s Direct 0x%X <=== 0x%X\n",
rtype_name, regno, h_val);
}
spin_lock_irqsave(&xpd->lock, flags);
v = &(params->values[rtype]);
v->h_val = h_val;
v->l_val = l_val;
spin_unlock_irqrestore(&xpd->lock, flags);
return count;
invalid_input:
return -EINVAL;
}
static DEVICE_ATTR(fxs_ring_registers, S_IRUGO | S_IWUSR,
fxs_ring_registers_show,
fxs_ring_registers_store);
static int fxs_xpd_probe(struct device *dev)
{
xpd_t *xpd;
int ret;
xpd = dev_to_xpd(dev);
/* Is it our device? */
@@ -1998,15 +1850,7 @@ static int fxs_xpd_probe(struct device *dev)
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
ret = device_create_file(dev, &dev_attr_fxs_ring_registers);
if (ret) {
XPD_ERR(xpd, "%s: device_create_file(fxs_ring_registers) failed: %d\n",
__func__, ret);
goto fail_fxs_ring_registers;
}
return 0;
fail_fxs_ring_registers:
return ret;
}
static int fxs_xpd_remove(struct device *dev)
@@ -2015,7 +1859,6 @@ static int fxs_xpd_remove(struct device *dev)
xpd = dev_to_xpd(dev);
XPD_DBG(DEVICES, xpd, "SYSFS\n");
device_remove_file(dev, &dev_attr_fxs_ring_registers);
return 0;
}

View File

@@ -511,11 +511,6 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
ret = -EPROTO;
goto proto_err;
}
if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) {
XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n");
ret = -EPROTO;
goto proto_err;
}
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
ret = -EPROTO;
goto proto_err;
@@ -573,7 +568,6 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
goto out;
proto_err:
xbus_setstate(xbus, XBUS_STATE_FAIL);
dump_packet("AB_DESCRIPTION", pack, DBG_ANY);
out:
return ret;

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
USB_FW = USB_FW.hex USB_FW.201.hex USB_RECOV.hex
FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex \
FPGA_1161.201.hex FPGA_1161.202.hex
FPGA_1161.201.hex
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
OCT_FW = $(wildcard OCT6104E-256D.ima)
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
@@ -20,7 +20,4 @@ install:
mkdir -p $(TARGET)
install $(SCRIPTS) $(TARGET)/
install -m 644 ../XppConfig.pm $(FIRMWARES) $(TARGET)/
if [ ! -r $(TARGET)/USB_FW.202.hex ]; then \
ln -s USB_FW.201.hex $(TARGET)/USB_FW.202.hex;\
fi

View File

@@ -1 +0,0 @@
USB_FW.201.hex

View File

@@ -59,7 +59,6 @@ my %settings;
$settings{debug} = 0;
$settings{fxs_skip_calib} = 0;
my $chipregs;
my $ring_registers;
sub logit {
print STDERR "$unit_id: @_\n";
@@ -105,10 +104,6 @@ if (-t STDERR) {
logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
if -f $chipregs;
}
$ring_registers = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/fxs_ring_registers",
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
logit "OLD DRIVER: missing '$ring_registers' -- fallback to hard-coded defaults"
unless -f $ring_registers;
}
sub set_output() {
@@ -152,16 +147,6 @@ sub write_to_slic_file($) {
}
sub write_to_ring_register($) {
my $write_str = shift;
open(SLICS,">$ring_registers") or
die("Failed writing to ring_registers file $ring_registers");
print SLICS $write_str;
close(SLICS) or die "Failed writing '$write_str' to '$ring_registers': $!";
main::mysleep(0.001);
}
sub read_reg($$$) {
my $read_slic = shift;
my $read_reg = shift;
@@ -313,7 +298,7 @@ sub init_early_direct_regs() {
return write_to_slic_file("#
* WD 08 00 # Audio Path Loopback Control
* WD 6C 01
* WD 4A 34 # High Battery Voltage
* WD 4A 3F # High Battery Voltage
* WD 4B $lbv # Low Battery Voltage
* WD 49 $vcm # Common Mode Voltage (VCM)
* WD 40 00 # Line Feed Control
@@ -457,10 +442,6 @@ sub check_slics() {
return @slics;
}
sub overwrite_ring_registers() {
write_to_ring_register("NEON 0x33 0x12");
}
package main;
main::debug "Starting '$0'";
@@ -489,7 +470,6 @@ while(<DATA>) {
print "$_\n";
}
close REG;
FXS::overwrite_ring_registers();
main::debug "Ending '$0'";
close STDERR;

View File

@@ -24,7 +24,6 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#ifdef PROTOCOL_DEBUG
@@ -60,7 +59,7 @@ static DEF_PARM(uint, command_queue_length, 1500, 0444,
static DEF_PARM(uint, poll_timeout, 1000, 0644,
"Timeout (in jiffies) waiting for units to reply");
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
static DEF_PARM_BOOL(dahdi_autoreg, 1, 0644,
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
"Register devices automatically (1) or not (0)");
#ifdef CONFIG_PROC_FS
@@ -938,8 +937,6 @@ static void xbus_free_ddev(xbus_t *xbus)
xbus->ddev = NULL;
}
static DEFINE_MUTEX(dahdi_registration_mutex);
int xbus_register_dahdi_device(xbus_t *xbus)
{
int i;
@@ -947,11 +944,6 @@ int xbus_register_dahdi_device(xbus_t *xbus)
int ret;
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
if (ret < 0) {
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
goto err;
}
if (xbus_is_registered(xbus)) {
XBUS_ERR(xbus, "Already registered to DAHDI\n");
WARN_ON(1);
@@ -1016,26 +1008,17 @@ int xbus_register_dahdi_device(xbus_t *xbus)
xpd_dahdi_postregister(xpd);
}
}
ret = 0;
out:
mutex_unlock(&dahdi_registration_mutex);
return ret;
return 0;
err:
xbus_free_ddev(xbus);
goto out;
return ret;
}
void xbus_unregister_dahdi_device(xbus_t *xbus)
{
int i;
int ret;
XBUS_NOTICE(xbus, "%s\n", __func__);
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
if (ret < 0) {
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
return;
}
for (i = 0; i < MAX_XPDS; i++) {
xpd_t *xpd = xpd_of(xbus, i);
xpd_dahdi_preunregister(xpd);
@@ -1050,7 +1033,6 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
xpd_t *xpd = xpd_of(xbus, i);
xpd_dahdi_postunregister(xpd);
}
mutex_unlock(&dahdi_registration_mutex);
}
/*

View File

@@ -23,7 +23,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#ifdef PROTOCOL_DEBUG
#include <linux/ctype.h>
@@ -55,19 +54,10 @@ static ssize_t sync_store(struct device_driver *driver, const char *buf,
return exec_sync_command(buf, count);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static struct driver_attribute xpp_attrs[] = {
__ATTR(sync, S_IRUGO | S_IWUSR, sync_show, sync_store),
__ATTR_NULL,
};
#else
static DRIVER_ATTR_RW(sync);
static struct attribute *xpp_attrs[] = {
&driver_attr_sync.attr,
NULL,
};
ATTRIBUTE_GROUPS(xpp);
#endif
/*--------- Sysfs Bus handling ----*/
static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
@@ -419,11 +409,7 @@ static struct bus_type toplevel_bus_type = {
.match = astribank_match,
.uevent = astribank_uevent,
.dev_attrs = xbus_dev_attrs,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.drv_attrs = xpp_attrs,
#else
.drv_groups = xpp_groups,
#endif
};
static int astribank_probe(struct device *dev)
@@ -596,8 +582,6 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
return len;
}
static DEFINE_MUTEX(span_store_mutex);
/*
* For backward compatibility with old dahdi-tools
* Remove after dahdi_registration is upgraded
@@ -617,13 +601,8 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
return -EINVAL;
if (!XBUS_IS(xpd->xbus, READY))
return -ENODEV;
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n",
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use pinned-spans)\n",
(dahdi_reg) ? "register" : "unregister");
ret = mutex_lock_interruptible(&span_store_mutex);
if (ret < 0) {
XBUS_ERR(xpd->xbus, "span_store_mutex already taken\n");
return ret;
}
if (xbus_is_registered(xpd->xbus)) {
if (dahdi_reg) {
XPD_DBG(DEVICES, xpd,
@@ -641,7 +620,6 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
xbus_register_dahdi_device(xpd->xbus);
}
}
mutex_unlock(&span_store_mutex);
return count;
}

View File

@@ -0,0 +1,11 @@
# Load firmware into the Xorcom Astribank device:
SUBSYSTEM=="usb", ACTION=="add", \
ENV{PRODUCT}=="e4e4/11[3456][013]/*", ENV{DEVTYPE}!="usb_interface", \
RUN+="/usr/share/dahdi/xpp_fxloader udev $env{PRODUCT}"
# Hotplug hook for Astribank up/down
# If you need this functionality, copy the astribank_hook.sample
# to $XPP_INIT_DIR/astribank_hook
#
# By default XPP_INIT_DIR="/usr/share/dahdi"
KERNEL=="xbus*", RUN+="%E{XPP_INIT_DIR}/astribank_hook udev $kernel $sysfs{status} $sysfs{connector}"

View File

@@ -40,10 +40,11 @@
/* #define SHORT_FLASH_TIME */
/*
* Uncomment to disable calibration tests
* Uncomment to disable calibration and/or DC/DC converter tests
* (not generally recommended)
*/
/* #define NO_CALIBRATION */
/* #define NO_DCDC */
/*
* Boost ring voltage (Higher ring voltage, takes more power)

View File

@@ -811,7 +811,6 @@ enum spantypes {
SPANTYPE_DIGITAL_BRI_NT,
SPANTYPE_DIGITAL_BRI_TE,
SPANTYPE_DIGITAL_BRI_SOFT,
SPANTYPE_DIGITAL_DYNAMIC,
};
const char *dahdi_spantype2str(enum spantypes st);
enum spantypes dahdi_str2spantype(const char *name);
@@ -910,7 +909,7 @@ 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 "assigned spans", this function is called back when this
/*! When using "pinned_spans", this function is called back when this
* span has been assigned with the system. */
void (*assigned)(struct dahdi_span *span);
@@ -1004,8 +1003,6 @@ struct dahdi_transcoder_channel {
};
int dahdi_is_sync_master(const struct dahdi_span *span);
struct dahdi_span *get_master_span(void);
void set_master_span(int spanno);
static inline int
dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) {
@@ -1426,25 +1423,6 @@ static inline void *PDE_DATA(const struct inode *inode)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
#define KERN_CONT ""
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
# ifndef RHEL_RELEASE_VERSION
/* I'm not sure which 5.x release this was backported into. */
static inline int try_wait_for_completion(struct completion *x)
{
unsigned long flags;
int ret = 1;
spin_lock_irqsave(&x->wait.lock, flags);
if (!x->done)
ret = 0;
else
x->done--;
spin_unlock_irqrestore(&x->wait.lock, flags);
return ret;
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
@@ -1484,11 +1462,8 @@ void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#ifndef __packed
#define __packed __attribute__((packed))
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#include <linux/ctype.h>
@@ -1516,7 +1491,6 @@ static inline int strcasecmp(const char *s1, const char *s2)
#endif /* 2.6.22 */
#endif /* 2.6.25 */
#endif /* 2.6.26 */
#endif /* 2.6.27 */
#endif /* 2.6.31 */
#endif /* 3.10.0 */
@@ -1609,17 +1583,6 @@ struct mutex {
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
#endif
/* If KBUILD_MODNAME is not defined in a compilation unit, then the dev_dbg
* macro will not work properly. */
#ifndef KBUILD_MODNAME
#undef dev_dbg
#ifdef DEBUG
#define dev_dbg dev_info
#else
#define dev_dbg(...) do { } while (0)
#endif
#endif
/* The dbg_* ones use a magical variable 'debug' and the user should be
* aware of that.
*/