summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaik Broemme2015-10-04 21:51:11 +0200
committerMaik Broemme2015-10-04 21:51:11 +0200
commit205e1524de216b894a99a525a9cd45f49a6d2119 (patch)
treed6683bbd43e65fe52c986a349662aff443c5c60b
parent126ae972e89a76accea7bcc79972ae8f72c17ab3 (diff)
downloadaur-205e1524de216b894a99a525a9cd45f49a6d2119.tar.gz
Removed no longer needed patches
-rw-r--r--dahdi-linux-2.10.1-allo.patch7300
-rw-r--r--dahdi-linux-2.10.1-openvox-1.patch6228
-rw-r--r--dahdi-linux-2.10.1-openvox-2.patch5851
-rw-r--r--dahdi-linux-2.10.1-openvox-3.patch7272
-rw-r--r--dahdi-linux-2.10.1-yeastar.patch6269
5 files changed, 0 insertions, 32920 deletions
diff --git a/dahdi-linux-2.10.1-allo.patch b/dahdi-linux-2.10.1-allo.patch
deleted file mode 100644
index 99a1ed2d21f..00000000000
--- a/dahdi-linux-2.10.1-allo.patch
+++ /dev/null
@@ -1,7300 +0,0 @@
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/Kbuild dahdi-linux-2.10.0.1-allo/drivers/dahdi/Kbuild
---- dahdi-linux-2.10.0.1/drivers/dahdi/Kbuild 2014-09-22 20:40:19.000000000 +0200
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/Kbuild 2015-02-10 15:12:17.829888792 +0100
-@@ -14,6 +14,8 @@
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
-
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ALLO4XXP) += allo4xxp/
-+
- 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
- ifeq ($(HOTPLUG_FIRMWARE),yes)
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/Kconfig dahdi-linux-2.10.0.1-allo/drivers/dahdi/Kconfig
---- dahdi-linux-2.10.0.1/drivers/dahdi/Kconfig 2014-09-22 20:40:19.000000000 +0200
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/Kconfig 2015-02-10 15:01:15.886129051 +0100
-@@ -291,4 +291,14 @@
-
- If unsure, say Y.
-
-+config DAHDI_ALLO4XXP
-+ tristate "Allo TE410P Quad-T1/E1 PCI"
-+ depends on DAHDI && PCI
-+ default DAHDI
-+ ---help---
-+ To compile this driver as a module, choose M here: the
-+ module will be called wcte11xp.
-+
-+ If unsure, say Y.
-+
- source "drivers/dahdi/xpp/Kconfig"
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/Kbuild dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/Kbuild
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/Kbuild 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/Kbuild 2015-02-10 15:01:15.886129051 +0100
-@@ -0,0 +1,31 @@
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ALLO4XXP) += allo4xxp.o
-+
-+FIRM_DIR := ../firmware
-+
-+EXTRA_CFLAGS += -I$(src)/.. -I$(src)/../oct612x/ $(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
-+# unused-but-set-variable warning for this driver.
-+
-+EXTRA_CFLAGS += $(call cc-option, -Wno-unused-but-set-variable)
-+
-+ifeq ($(HOTPLUG_FIRMWARE),yes)
-+ EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
-+endif
-+
-+allo4xxp-objs := base.o vpm450m.o
-+
-+ifneq ($(HOTPLUG_FIRMWARE),yes)
-+allo4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o
-+$(warning WARNING: You are compiling firmware into allo4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
-+endif
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-064.o
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/allo4xxp.h dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/allo4xxp.h
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/allo4xxp.h 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/allo4xxp.h 2015-02-10 15:01:15.886129051 +0100
-@@ -0,0 +1,144 @@
-+/*
-+ * Wildcard T400P FXS Interface Driver for DAHDI Telephony interface
-+ *
-+ * Written by Mark Spencer <markster@linux-support.net>
-+ *
-+ * Copyright (C) 2001-2010, 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/ioctl.h>
-+
-+#define FRMR_TTR_BASE 0x10
-+#define FRMR_RTR_BASE 0x0c
-+#define FRMR_TSEO 0xa0
-+#define FRMR_TSBS1 0xa1
-+#define FRMR_CCR1 0x09
-+#define FRMR_CCR1_ITF 0x08
-+#define FRMR_CCR1_EITS 0x10
-+#define FRMR_CCR2 0x0a
-+#define FRMR_CCR2_RCRC 0x04
-+#define FRMR_CCR2_RADD 0x10
-+#define FRMR_MODE 0x03
-+#define FRMR_MODE_NO_ADDR_CMP 0x80
-+#define FRMR_MODE_SS7 0x20
-+#define FRMR_MODE_HRAC 0x08
-+#define FRMR_IMR0 0x14
-+#define FRMR_IMR0_RME 0x80
-+#define FRMR_IMR0_RPF 0x01
-+#define FRMR_IMR1 0x15
-+#define FRMR_IMR1_ALLS 0x20
-+#define FRMR_IMR1_XDU 0x10
-+#define FRMR_IMR1_XPR 0x01
-+#define FRMR_XC0 0x22
-+#define FRMR_XC1 0x23
-+#define FRMR_RC0 0x24
-+#define FRMR_RC1 0x25
-+#define FRMR_SIC1 0x3e
-+#define FRMR_SIC2 0x3f
-+#define FRMR_SIC3 0x40
-+#define FRMR_CMR1 0x44
-+#define FRMR_CMR2 0x45
-+/* OctalFALC Only */
-+#define FRMR_CMR4 0x41
-+#define FRMR_CMR5 0x42
-+#define FRMR_CMR6 0x43
-+#define FRMR_GPC2 0x8a
-+/* End Octal */
-+#define FRMR_GCR 0x46
-+#define FRMR_ISR0 0x68
-+#define FRMR_ISR0_RME 0x80
-+#define FRMR_ISR0_RPF 0x01
-+#define FRMR_ISR1 0x69
-+#define FRMR_ISR1_ALLS 0x20
-+#define FRMR_ISR1_XDU 0x10
-+#define FRMR_ISR1_XPR 0x01
-+#define FRMR_ISR2 0x6a
-+#define FRMR_ISR3 0x6b
-+#define FRMR_ISR4 0x6c
-+#define FRMR_GIS 0x6e
-+#define FRMR_GIS_ISR0 0x01
-+#define FRMR_GIS_ISR1 0x02
-+#define FRMR_GIS_ISR2 0x04
-+#define FRMR_GIS_ISR3 0x08
-+#define FRMR_GIS_ISR4 0x10
-+#define FRMR_CIS 0x6f
-+#define FRMR_CIS_GIS1 0x01
-+#define FRMR_CIS_GIS2 0x02
-+#define FRMR_CIS_GIS3 0x04
-+#define FRMR_CIS_GIS4 0x08
-+
-+/* CIS - Octal falc bits */
-+#define FRMR_CIS_GIS5 0x10
-+#define FRMR_CIS_GIS6 0x20
-+#define FRMR_CIS_GIS7 0x40
-+#define FRMR_CIS_GIS8 0x80
-+
-+#define FRMR_CMDR 0x02
-+#define FRMR_CMDR_SRES 0x01
-+#define FRMR_CMDR_XRES 0x10
-+#define FRMR_CMDR_RMC 0x80
-+#define FRMR_CMDR_XTF 0x04
-+#define FRMR_CMDR_XHF 0x08
-+#define FRMR_CMDR_XME 0x02
-+#define FRMR_RSIS 0x65
-+#define FRMR_RSIS_VFR 0x80
-+#define FRMR_RSIS_RDO 0x40
-+#define FRMR_RSIS_CRC16 0x20
-+#define FRMR_RSIS_RAB 0x10
-+#define FRMR_RBCL 0x66
-+#define FRMR_RBCL_MAX_SIZE 0x1f
-+#define FRMR_RBCH 0x67
-+#define FRMR_RXFIFO 0x00
-+#define FRMR_SIS 0x64
-+#define FRMR_SIS_XFW 0x40
-+#define FRMR_TXFIFO 0x00
-+
-+#define FRS0 0x4c
-+#define FRS0_LOS (1<<7)
-+#define FRS0_LFA (1<<5)
-+#define FRS0_LMFA (1<<1)
-+
-+#define FRS1 0x4d
-+#define FRS1_XLS (1<<1)
-+#define FRS1_XLO (1<<0)
-+
-+#define NUM_REGS 0xa9
-+#define NUM_PCI 12
-+
-+struct t4_regs {
-+ unsigned int pci[NUM_PCI];
-+ unsigned char regs[NUM_REGS];
-+};
-+
-+struct t4_reg {
-+ unsigned int reg;
-+ unsigned int val;
-+};
-+
-+#define T4_CHECK_VPM 0
-+#define T4_LOADING_FW 1
-+#define T4_STOP_DMA 2
-+#define T4_CHECK_TIMING 3
-+#define T4_CHANGE_LATENCY 4
-+#define T4_IGNORE_LATENCY 5
-+
-+#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
-+#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
-+#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
-+
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/base.c dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/base.c
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/base.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/base.c 2015-02-10 15:01:15.889462151 +0100
-@@ -0,0 +1,5677 @@
-+/*
-+ * TE410P Quad-T1/E1 PCI Driver version 0.1, 12/16/02
-+ *
-+ * Written by Mark Spencer <markster@digium.com>
-+ * Based on previous works, designs, and archetectures conceived and
-+ * written by Jim Dixon <jim@lambdatel.com>.
-+ * Further modified, optimized, and maintained by
-+ * Matthew Fredrickson <creslin@digium.com> and
-+ * Russ Meyerriecks <rmeyerriecks@digium.com>
-+ *
-+ * Copyright (C) 2001 Jim Dixon / Zapata Telephony.
-+ * Copyright (C) 2001-2012, Digium, Inc.
-+ *
-+ * All rights reserved.
-+ *
-+ */
-+
-+/*
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2 as published by the
-+ * Free Software Foundation. See the LICENSE file included with
-+ * this program for more details.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/spinlock.h>
-+#include <asm/io.h>
-+#include <linux/version.h>
-+#include <linux/delay.h>
-+#include <linux/moduleparam.h>
-+#include <linux/crc32.h>
-+
-+#include <stdbool.h>
-+#include <dahdi/kernel.h>
-+
-+#include "allo4xxp.h"
-+#include "vpm450m.h"
-+
-+/* Work queues are a way to better distribute load on SMP systems */
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
-+/*
-+ * Work queues can significantly improve performance and scalability
-+ * on multi-processor machines, but requires bypassing some kernel
-+ * API's, so it's not guaranteed to be compatible with all kernels.
-+ */
-+/* #define ENABLE_WORKQUEUES */
-+#endif
-+
-+/* Support first generation cards? */
-+#define SUPPORT_GEN1
-+
-+/* Define to get more attention-grabbing but slightly more I/O using
-+ alarm status */
-+#undef FANCY_ALARM
-+
-+/* Define to support Digium Voice Processing Module expansion card */
-+#define VPM_SUPPORT
-+
-+#define DEBUG_MAIN (1 << 0)
-+#define DEBUG_DTMF (1 << 1)
-+#define DEBUG_REGS (1 << 2)
-+#define DEBUG_TSI (1 << 3)
-+#define DEBUG_ECHOCAN (1 << 4)
-+#define DEBUG_RBS (1 << 5)
-+#define DEBUG_FRAMER (1 << 6)
-+
-+/* Maximum latency to be used with Gen 5 */
-+#define GEN5_MAX_LATENCY 127
-+
-+#ifdef ENABLE_WORKQUEUES
-+#include <linux/cpu.h>
-+
-+/* XXX UGLY!!!! XXX We have to access the direct structures of the workqueue which
-+ are only defined within workqueue.c because they don't give us a routine to allow us
-+ to nail a work to a particular thread of the CPU. Nailing to threads gives us substantially
-+ higher scalability in multi-CPU environments though! */
-+
-+/*
-+ * The per-CPU workqueue (if single thread, we always use cpu 0's).
-+ *
-+ * The sequence counters are for flush_scheduled_work(). It wants to wait
-+ * until until all currently-scheduled works are completed, but it doesn't
-+ * want to be livelocked by new, incoming ones. So it waits until
-+ * remove_sequence is >= the insert_sequence which pertained when
-+ * flush_scheduled_work() was called.
-+ */
-+
-+struct cpu_workqueue_struct {
-+
-+ spinlock_t lock;
-+
-+ long remove_sequence; /* Least-recently added (next to run) */
-+ long insert_sequence; /* Next to add */
-+
-+ struct list_head worklist;
-+ wait_queue_head_t more_work;
-+ wait_queue_head_t work_done;
-+
-+ struct workqueue_struct *wq;
-+ task_t *thread;
-+
-+ int run_depth; /* Detect run_workqueue() recursion depth */
-+} ____cacheline_aligned;
-+
-+/*
-+ * The externally visible workqueue abstraction is an array of
-+ * per-CPU workqueues:
-+ */
-+struct workqueue_struct {
-+ /* TODO: Find out exactly where the API changed */
-+ struct cpu_workqueue_struct *cpu_wq;
-+ const char *name;
-+ struct list_head list; /* Empty if single thread */
-+};
-+
-+/* Preempt must be disabled. */
-+static void __t4_queue_work(struct cpu_workqueue_struct *cwq,
-+ struct work_struct *work)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&cwq->lock, flags);
-+ work->wq_data = cwq;
-+ list_add_tail(&work->entry, &cwq->worklist);
-+ cwq->insert_sequence++;
-+ wake_up(&cwq->more_work);
-+ spin_unlock_irqrestore(&cwq->lock, flags);
-+}
-+
-+/*
-+ * Queue work on a workqueue. Return non-zero if it was successfully
-+ * added.
-+ *
-+ * We queue the work to the CPU it was submitted, but there is no
-+ * guarantee that it will be processed by that CPU.
-+ */
-+static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu)
-+{
-+ int ret = 0;
-+ get_cpu();
-+ if (!test_and_set_bit(0, &work->pending)) {
-+ BUG_ON(!list_empty(&work->entry));
-+ __t4_queue_work(wq->cpu_wq + cpu, work);
-+ ret = 1;
-+ }
-+ put_cpu();
-+ return ret;
-+}
-+
-+#endif
-+
-+/*
-+ * Define CONFIG_FORCE_EXTENDED_RESET to allow the qfalc framer extra time
-+ * to reset itself upon hardware initialization. This exits for rare
-+ * cases for customers who are seeing the qfalc returning unexpected
-+ * information at initialization
-+ */
-+/* #define CONFIG_FORCE_EXTENDED_RESET */
-+/* #define CONFIG_NOEXTENDED_RESET */
-+
-+/*
-+ * Uncomment the following definition in order to disable Active-State Power
-+ * Management on the PCIe bridge for PCIe cards. This has been known to work
-+ * around issues where the BIOS enables it on the cards even though the
-+ * platform does not support it.
-+ *
-+ */
-+/* #define CONFIG_WCT4XXP_DISABLE_ASPM */
-+
-+#if defined(CONFIG_FORCE_EXTENDED_RESET) && defined(CONFIG_NOEXTENDED_RESET)
-+#error "You cannot define both CONFIG_FORCE_EXTENDED_RESET and " \
-+ "CONFIG_NOEXTENDED_RESET."
-+#endif
-+
-+int debug = 0;
-+static int timingcable = 0;
-+static int t1e1override = -1; /* deprecated */
-+static char *default_linemode = "auto";
-+static int j1mode = 0;
-+static int sigmode = FRMR_MODE_NO_ADDR_CMP;
-+static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/
-+static int losalarmdebounce = 2500;/* LOS def to 2.5s AT&T TR54016*/
-+static int aisalarmdebounce = 2500;/* AIS(blue) def to 2.5s AT&T TR54016*/
-+static int yelalarmdebounce = 500;/* RAI(yellow) def to 0.5s AT&T devguide */
-+static int max_latency = GEN5_MAX_LATENCY; /* Used to set a maximum latency (if you don't wish it to hard cap it at a certain value) in milliseconds */
-+#ifdef VPM_SUPPORT
-+static int vpmsupport = 1;
-+/* If set to auto, vpmdtmfsupport is enabled for VPM400M and disabled for VPM450M */
-+static int vpmdtmfsupport = -1; /* -1=auto, 0=disabled, 1=enabled*/
-+#endif /* VPM_SUPPORT */
-+
-+/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but
-+ can also cause PCI bus starvation, especially in combination with other
-+ aggressive cards. Please note that burst mode has no effect on CPU
-+ utilization / max number of calls / etc. */
-+static int noburst;
-+/* For 56kbps links, set this module parameter to 0x7f */
-+static int hardhdlcmode = 0xff;
-+
-+static int latency = 1;
-+
-+static int ms_per_irq = 1;
-+static int ignore_rotary;
-+
-+#ifdef FANCY_ALARM
-+static int altab[] = {
-+0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0,
-+};
-+#endif
-+
-+#define MAX_SPANS 16
-+
-+#define FLAG_STARTED (1 << 0)
-+#define FLAG_NMF (1 << 1)
-+#define FLAG_SENDINGYELLOW (1 << 2)
-+
-+#define FLAG_2NDGEN (1 << 3)
-+#define FLAG_2PORT (1 << 4)
-+#define FLAG_VPM2GEN (1 << 5)
-+#define FLAG_OCTOPT (1 << 6)
-+#define FLAG_3RDGEN (1 << 7)
-+#define FLAG_BURST (1 << 8)
-+#define FLAG_EXPRESS (1 << 9)
-+#define FLAG_5THGEN (1 << 10)
-+#define FLAG_8PORT (1 << 11)
-+#define FLAG_1PORT (1 << 12)
-+
-+#define CANARY 0xc0de
-+
-+/* names of available HWEC modules */
-+#ifdef VPM_SUPPORT
-+#define T4_VPM_PRESENT (1 << 28)
-+static const char *vpmoct032_name = "VPMOCT032"; //cem:1port change
-+static const char *vpmoct064_name = "VPMOCT064";
-+static const char *vpmoct128_name = "VPMOCT128";
-+static const char *vpmoct256_name = "VPMOCT256";
-+#endif
-+
-+struct devtype {
-+ char *desc;
-+ unsigned int flags;
-+};
-+/*ALLO:*/
-+static struct devtype allo1280p2 = { "Allocard 2aCP8e (2nd Gen)", FLAG_8PORT | FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS };
-+static struct devtype allo1240p2 = { "Allocard 2aCP4e (2nd Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS };
-+static struct devtype allo1241p2 = { "Allocard 2aCP4 (2nd Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN };
-+static struct devtype allo1220p2 = { "Allocard 2aCP2e (2nd Gen)", FLAG_2PORT | FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS };
-+static struct devtype allo1210p2 = { "Allocard 2aCP1e (2nd Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_1PORT };
-+
-+
-+struct t4;
-+
-+enum linemode {T1, E1, J1};
-+
-+struct spi_state {
-+ int wrreg;
-+ int rdreg;
-+};
-+
-+struct t4_span {
-+ struct t4 *owner;
-+ u32 *writechunk; /* Double-word aligned write memory */
-+ u32 *readchunk; /* Double-word aligned read memory */
-+ enum linemode linemode;
-+ int sync;
-+ int alarmtimer;
-+ int notclear;
-+ unsigned long alarm_time;
-+ unsigned long losalarm_time;
-+ unsigned long aisalarm_time;
-+ unsigned long yelalarm_time;
-+ unsigned long alarmcheck_time;
-+ int spanflags;
-+ int syncpos;
-+
-+#ifdef SUPPORT_GEN1
-+ int e1check; /* E1 check */
-+#endif
-+ struct dahdi_span span;
-+ unsigned char txsigs[16]; /* Transmit sigs */
-+ int loopupcnt;
-+ int loopdowncnt;
-+#ifdef SUPPORT_GEN1
-+ unsigned char ec_chunk1[31][DAHDI_CHUNKSIZE]; /* first EC chunk buffer */
-+ unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE]; /* second EC chunk buffer */
-+#endif
-+ /* HDLC controller fields */
-+ struct dahdi_chan *sigchan;
-+ unsigned char sigmode;
-+ int sigactive;
-+ int frames_out;
-+ int frames_in;
-+
-+#ifdef VPM_SUPPORT
-+ unsigned long dtmfactive;
-+ unsigned long dtmfmask;
-+ unsigned long dtmfmutemask;
-+#endif
-+#ifdef ENABLE_WORKQUEUES
-+ struct work_struct swork;
-+#endif
-+ struct dahdi_chan *chans[32]; /* Individual channels */
-+ struct dahdi_echocan_state *ec[32]; /* Echocan state for each channel */
-+};
-+
-+struct t4 {
-+ /* This structure exists one per card */
-+ struct pci_dev *dev; /* Pointer to PCI device */
-+ unsigned int intcount;
-+ int num; /* Which card we are */
-+ int syncsrc; /* active sync source */
-+ struct dahdi_device *ddev;
-+ struct t4_span *tspans[8]; /* Individual spans */
-+ int numspans; /* Number of spans on the card */
-+ int blinktimer;
-+#ifdef FANCY_ALARM
-+ int alarmpos;
-+#endif
-+ 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 */
-+ int ledreg2; /* LED Register2 */
-+ unsigned int gpio;
-+ unsigned int gpioctl;
-+ int e1recover; /* E1 recovery timer */
-+ spinlock_t reglock; /* lock register access */
-+ int spansstarted; /* number of spans started */
-+ u32 *writechunk; /* Double-word aligned write memory */
-+ u32 *readchunk; /* Double-word aligned read memory */
-+#ifdef ENABLE_WORKQUEUES
-+ atomic_t worklist;
-+ struct workqueue_struct *workq;
-+#endif
-+ int last0; /* for detecting double-missed IRQ */
-+
-+ /* DMA related fields */
-+ unsigned int dmactrl;
-+ dma_addr_t readdma;
-+ dma_addr_t writedma;
-+ void __iomem *membase; /* Base address of card */
-+
-+ /* Flags for our bottom half */
-+ unsigned long checkflag;
-+ struct tasklet_struct t4_tlet;
-+ /* Latency related additions */
-+ unsigned char rxident;
-+ unsigned char lastindex;
-+ int numbufs;
-+ int needed_latency;
-+
-+#ifdef VPM_SUPPORT
-+ struct vpm450m *vpm;
-+#endif
-+ struct spi_state st;
-+};
-+
-+static inline bool is_pcie(const struct t4 *wc)
-+{
-+ return (wc->devtype->flags & FLAG_EXPRESS) > 0;
-+}
-+
-+static inline bool has_e1_span(const struct t4 *wc)
-+{
-+ return (wc->t1e1 > 0);
-+}
-+
-+static inline bool is_octal(const struct t4 *wc)
-+{
-+ return (wc->devtype->flags & FLAG_8PORT) > 0;
-+}
-+
-+static inline int T4_BASE_SIZE(struct t4 *wc)
-+{
-+ if (is_octal(wc))
-+ return DAHDI_MAX_CHUNKSIZE * 32 * 8;
-+ else
-+ return DAHDI_MAX_CHUNKSIZE * 32 * 4;
-+}
-+
-+/**
-+ * ports_on_framer - The number of ports on the framers.
-+ * @wc: Board to check.
-+ *
-+ * The framer ports could be different the the number of ports on the card
-+ * since the dual spans have four ports internally but two ports extenally.
-+ *
-+ */
-+static inline unsigned int ports_on_framer(const struct t4 *wc)
-+{
-+ return (is_octal(wc)) ? 8 : 4;
-+}
-+
-+#ifdef VPM_SUPPORT
-+static void t4_vpm_init(struct t4 *wc);
-+
-+static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
-+
-+static const struct dahdi_echocan_features vpm_ec_features = {
-+ .NLP_automatic = 1,
-+ .CED_tx_detect = 1,
-+ .CED_rx_detect = 1,
-+};
-+
-+static const struct dahdi_echocan_ops vpm_ec_ops = {
-+ .echocan_free = echocan_free,
-+};
-+#endif
-+
-+static void __set_clear(struct t4 *wc, int span);
-+static int _t4_startup(struct file *file, struct dahdi_span *span);
-+static int t4_startup(struct file *file, struct dahdi_span *span);
-+static int t4_shutdown(struct dahdi_span *span);
-+static int t4_rbsbits(struct dahdi_chan *chan, int bits);
-+static int t4_maint(struct dahdi_span *span, int cmd);
-+static int t4_clear_maint(struct dahdi_span *span);
-+static int t4_reset_counters(struct dahdi_span *span);
-+#ifdef SUPPORT_GEN1
-+static int t4_reset_dma(struct t4 *wc);
-+#endif
-+static void t4_hdlc_hard_xmit(struct dahdi_chan *chan);
-+static int t4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data);
-+static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan);
-+static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan);
-+static void __t4_set_rclk_src(struct t4 *wc, int span);
-+static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave);
-+static void t4_check_alarms(struct t4 *wc, int span);
-+static void t4_check_sigbits(struct t4 *wc, int span);
-+
-+#define WC_RDADDR 0
-+#define WC_WRADDR 1
-+#define WC_COUNT 2
-+#define WC_DMACTRL 3
-+#define WC_INTR 4
-+/* #define WC_GPIO 5 */
-+#define WC_VERSION 6
-+#define WC_LEDS 7
-+#define WC_GPIOCTL 8
-+#define WC_GPIO 9
-+#define WC_LADDR 10
-+#define WC_LDATA 11
-+#define WC_LEDS2 12
-+
-+#define WC_SET_AUTH (1 << 20)
-+#define WC_GET_AUTH (1 << 12)
-+
-+#define WC_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */
-+#define WC_LCS (1 << 11)
-+#define WC_LCS2 (1 << 12)
-+#define WC_LALE (1 << 13)
-+#define WC_LFRMR_CS2 (1 << 14) /* Framer's ChipSelect signal 2 */
-+#define WC_LREAD (1 << 15)
-+#define WC_LWRITE (1 << 16)
-+
-+#define WC_ACTIVATE (1 << 12)
-+
-+#define WC_OFF (0)
-+#define WC_RED (1)
-+#define WC_GREEN (2)
-+#define WC_YELLOW (3)
-+
-+#define WC_RECOVER 0
-+#define WC_SELF 1
-+
-+#define LIM0_T 0x36 /* Line interface mode 0 register */
-+#define LIM0_LL (1 << 1) /* Local Loop */
-+#define LIM1_T 0x37 /* Line interface mode 1 register */
-+#define LIM1_RL (1 << 1) /* Remote Loop */
-+
-+#define FMR0 0x1C /* Framer Mode Register 0 */
-+#define FMR0_SIM (1 << 0) /* Alarm Simulation */
-+#define FMR1_T 0x1D /* Framer Mode Register 1 */
-+#define FMR1_ECM (1 << 2) /* Error Counter 1sec Interrupt Enable */
-+#define FMR5 0x21 /* Framer Mode Register 5 */
-+#define FMR5_XLU (1 << 4) /* Transmit loopup code */
-+#define FMR5_XLD (1 << 5) /* Transmit loopdown code */
-+#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 IPE (1 << 1) /* PRBS defect */
-+#define ICASE (1 << 2) /* CAS defect */
-+#define ICRCE (1 << 3) /* CRC defect */
-+#define IMFE (1 << 4) /* Multiframe defect */
-+#define IFASE (1 << 5) /* FAS defect */
-+#define ISR3_SEC (1 << 6) /* Internal one-second interrupt bit mask */
-+#define ISR3_ES (1 << 7) /* Errored Second interrupt bit mask */
-+#define ESM 0x47 /* Errored Second mask register */
-+
-+#define FMR2_T 0x1E /* Framer Mode Register 2 */
-+#define FMR2_PLB (1 << 2) /* Framer Mode Register 2 */
-+
-+#define FECL_T 0x50 /* Framing Error Counter Lower Byte */
-+#define FECH_T 0x51 /* Framing Error Counter Higher Byte */
-+#define CVCL_T 0x52 /* Code Violation Counter Lower Byte */
-+#define CVCH_T 0x53 /* Code Violation Counter Higher Byte */
-+#define CEC1L_T 0x54 /* CRC Error Counter 1 Lower Byte */
-+#define CEC1H_T 0x55 /* CRC Error Counter 1 Higher Byte */
-+#define EBCL_T 0x56 /* E-Bit Error Counter Lower Byte */
-+#define EBCH_T 0x57 /* E-Bit Error Counter Higher Byte */
-+#define BECL_T 0x58 /* Bit Error Counter Lower Byte */
-+#define BECH_T 0x59 /* Bit Error Counter Higher Byte */
-+#define COEC_T 0x5A /* COFA Event Counter */
-+#define PRBSSTA_T 0xDA /* PRBS Status Register */
-+
-+#define LCR1_T 0x3B /* Loop Code Register 1 */
-+#define EPRM (1 << 7) /* Enable PRBS rx */
-+#define XPRBS (1 << 6) /* Enable PRBS tx */
-+#define FLLB (1 << 1) /* Framed line loop/Invert */
-+#define LLBP (1 << 0) /* Line Loopback Pattern */
-+#define TPC0_T 0xA8 /* Test Pattern Control Register */
-+#define FRA (1 << 6) /* Framed/Unframed Selection */
-+#define PRBS23 (3 << 4) /* Pattern selection (23 poly) */
-+#define PRM (1 << 2) /* Non framed mode */
-+#define FRS1_T 0x4D /* Framer Receive Status Reg 1 */
-+#define LLBDD (1 << 4)
-+#define LLBAD (1 << 3)
-+
-+#define MAX_T4_CARDS 64
-+
-+static void t4_isr_bh(unsigned long data);
-+
-+static struct t4 *cards[MAX_T4_CARDS];
-+
-+struct t8_firm_header {
-+ u8 header[6];
-+ __le32 chksum;
-+ u8 pad[18];
-+ __le32 version;
-+} __packed;
-+
-+#define MAX_TDM_CHAN 32
-+#define MAX_DTMF_DET 16
-+
-+#define HDLC_IMR0_MASK (FRMR_IMR0_RME | FRMR_IMR0_RPF)
-+#define HDLC_IMR1_MASK (FRMR_IMR1_XDU | FRMR_IMR1_XPR)
-+
-+static inline unsigned int __t4_pci_in(struct t4 *wc, const unsigned int addr)
-+{
-+ unsigned int res = readl(wc->membase + (addr * sizeof(u32)));
-+ return res;
-+}
-+
-+static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
-+{
-+#ifdef DEBUG
-+ unsigned int tmp;
-+#endif
-+ writel(value, wc->membase + (addr * sizeof(u32)));
-+#ifdef DEBUG
-+ tmp = __t4_pci_in(wc, WC_VERSION);
-+ if ((tmp & 0xffff0000) != 0xc01a0000)
-+ dev_notice(&wc->dev->dev,
-+ "Version Synchronization Error!\n");
-+#else
-+ __t4_pci_in(wc, WC_VERSION);
-+#endif
-+}
-+
-+static inline void __t4_gpio_set(struct t4 *wc, unsigned bits, unsigned int val)
-+{
-+ unsigned int newgpio;
-+ newgpio = wc->gpio & (~bits);
-+ newgpio |= val;
-+ if (newgpio != wc->gpio) {
-+ wc->gpio = newgpio;
-+ __t4_pci_out(wc, WC_GPIO, wc->gpio);
-+ }
-+}
-+
-+static inline void __t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val)
-+{
-+ unsigned int newgpioctl;
-+ newgpioctl = wc->gpioctl & (~bits);
-+ newgpioctl |= val;
-+ if (newgpioctl != wc->gpioctl) {
-+ wc->gpioctl = newgpioctl;
-+ __t4_pci_out(wc, WC_GPIOCTL, wc->gpioctl);
-+ }
-+}
-+
-+static inline void t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ __t4_gpio_setdir(wc, bits, val);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+static inline void t4_gpio_set(struct t4 *wc, unsigned int bits, unsigned int val)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ __t4_gpio_set(wc, bits, val);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ __t4_pci_out(wc, addr, value);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+static inline void __t4_set_led(struct t4 *wc, int span, int color)
-+{
-+ if (span <= 3) {
-+ int oldreg = wc->ledreg;
-+
-+ wc->ledreg &= ~(0x3 << (span << 1));
-+ wc->ledreg |= (color << (span << 1));
-+ if (oldreg != wc->ledreg)
-+ __t4_pci_out(wc, WC_LEDS, wc->ledreg);
-+ } else {
-+ int oldreg = wc->ledreg2;
-+
-+ span &= 3;
-+ wc->ledreg2 &= ~(0x3 << (span << 1));
-+ wc->ledreg2 |= (color << (span << 1));
-+ if (oldreg != wc->ledreg2)
-+ __t4_pci_out(wc, WC_LEDS2, wc->ledreg2);
-+ }
-+}
-+
-+static inline void t4_activate(struct t4 *wc)
-+{
-+ wc->ledreg |= WC_ACTIVATE;
-+ t4_pci_out(wc, WC_LEDS, wc->ledreg);
-+}
-+
-+static inline unsigned int t4_pci_in(struct t4 *wc, const unsigned int addr)
-+{
-+ unsigned int ret;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ ret = __t4_pci_in(wc, addr);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return ret;
-+}
-+
-+static unsigned int __t4_framer_in(const struct t4 *wc, int unit,
-+ const unsigned int addr)
-+{
-+ unsigned int ret;
-+ register u32 val;
-+ void __iomem *const wc_laddr = wc->membase + (WC_LADDR*sizeof(u32));
-+ void __iomem *const wc_version = wc->membase + (WC_VERSION*sizeof(u32));
-+ void __iomem *const wc_ldata = wc->membase + (WC_LDATA*sizeof(u32));
-+ int haddr = (((unit & 4) ? 0 : WC_LFRMR_CS2));
-+ unit &= 0x3;
-+
-+ val = ((unit & 0x3) << 8) | (addr & 0xff) | haddr;
-+ writel(val, wc_laddr);
-+ readl(wc_version);
-+ writel(val | WC_LFRMR_CS | WC_LREAD, wc_laddr);
-+ readl(wc_version);
-+ ret = readb(wc_ldata);
-+ writel(val, wc_laddr);
-+ readl(wc_version);
-+ return ret;
-+}
-+
-+static unsigned int
-+t4_framer_in(struct t4 *wc, int unit, const unsigned int addr)
-+{
-+ unsigned long flags;
-+ unsigned int ret;
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ ret = __t4_framer_in(wc, unit, addr);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return ret;
-+}
-+
-+static void __t4_framer_out(const struct t4 *wc, int unit, const u8 addr,
-+ const unsigned int value)
-+{
-+ register u32 val;
-+ void __iomem *const wc_laddr = wc->membase + (WC_LADDR*sizeof(u32));
-+ void __iomem *const wc_version = wc->membase + (WC_VERSION*sizeof(u32));
-+ void __iomem *const wc_ldata = wc->membase + (WC_LDATA*sizeof(u32));
-+ int haddr = (((unit & 4) ? 0 : WC_LFRMR_CS2));
-+
-+ val = ((unit & 0x3) << 8) | (addr & 0xff) | haddr;
-+ writel(val, wc_laddr);
-+ readl(wc_version);
-+ writel(value, wc_ldata);
-+ readl(wc_version);
-+ writel(val | WC_LFRMR_CS | WC_LWRITE, wc_laddr);
-+ readl(wc_version);
-+ writel(val, wc_laddr);
-+ readl(wc_version);
-+}
-+
-+static void t4_framer_out(struct t4 *wc, int unit,
-+ const unsigned int addr,
-+ const unsigned int value)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ __t4_framer_out(wc, unit, addr, value);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+#ifdef VPM_SUPPORT
-+
-+static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
-+{
-+ int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT;
-+ if (!octopt)
-+ __t4_gpio_set(wc, 0xff, (addr >> 8));
-+ __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff));
-+ if (!octopt)
-+ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE));
-+ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE));
-+ if (!octopt)
-+ __t4_gpio_set(wc, 0xff, (value >> 8));
-+ __t4_pci_out(wc, WC_LDATA, (value & 0xffff));
-+ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE | WC_LCS));
-+ __t4_pci_out(wc, WC_LADDR, (0));
-+}
-+
-+static inline unsigned int __t4_raw_oct_in(struct t4 *wc, const unsigned int addr)
-+{
-+ unsigned int ret;
-+ int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT;
-+ if (!octopt)
-+ __t4_gpio_set(wc, 0xff, (addr >> 8));
-+ __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff));
-+ if (!octopt)
-+ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE));
-+ __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE));
-+ __t4_pci_out(wc, WC_LADDR, (WC_LALE));
-+ if (!octopt) {
-+ __t4_gpio_setdir(wc, 0xff, 0x00);
-+ __t4_gpio_set(wc, 0xff, 0x00);
-+ }
-+ __t4_pci_out(wc, WC_LADDR, (WC_LREAD | WC_LALE | WC_LCS));
-+ if (octopt) {
-+ ret = __t4_pci_in(wc, WC_LDATA) & 0xffff;
-+ } else {
-+ ret = __t4_pci_in(wc, WC_LDATA) & 0xff;
-+ ret |= (__t4_pci_in(wc, WC_GPIO) & 0xff) << 8;
-+ }
-+ __t4_pci_out(wc, WC_LADDR, (0));
-+ if (!octopt)
-+ __t4_gpio_setdir(wc, 0xff, 0xff);
-+ return ret & 0xffff;
-+}
-+
-+static inline unsigned int __t4_oct_in(struct t4 *wc, unsigned int addr)
-+{
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ int count = 1000;
-+#endif
-+ __t4_raw_oct_out(wc, 0x0008, (addr >> 20));
-+ __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1));
-+ __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1));
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count);
-+ if (count != 1000)
-+ dev_notice(&wc->dev->dev, "Yah, read can be slow...\n");
-+ if (!count)
-+ dev_notice(&wc->dev->dev, "Read timed out!\n");
-+#endif
-+ return __t4_raw_oct_in(wc, 0x0004);
-+}
-+
-+static inline unsigned int t4_oct_in(struct t4 *wc, const unsigned int addr)
-+{
-+ unsigned long flags;
-+ unsigned int ret;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ ret = __t4_oct_in(wc, addr);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return ret;
-+}
-+
-+static inline void __t4_oct_out(struct t4 *wc, unsigned int addr, unsigned int value)
-+{
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ int count = 1000;
-+#endif
-+ __t4_raw_oct_out(wc, 0x0008, (addr >> 20));
-+ __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1));
-+ __t4_raw_oct_out(wc, 0x0004, value);
-+ __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1);
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count);
-+ if (count != 1000)
-+ dev_notice(&wc->dev->dev, "Yah, write can be slow\n");
-+ if (!count)
-+ dev_notice(&wc->dev->dev, "Write timed out!\n");
-+#endif
-+}
-+
-+static inline void t4_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ __t4_oct_out(wc, addr, value);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+static void t4_check_vpm(struct t4 *wc)
-+{
-+ int channel, tone, start, span;
-+
-+ if (vpm450m_checkirq(wc->vpm)) {
-+ while(vpm450m_getdtmf(wc->vpm, &channel, &tone, &start)) {
-+ span = channel & 0x3;
-+ channel >>= 2;
-+ if (!has_e1_span(wc))
-+ channel -= 5;
-+ else
-+ channel -= 1;
-+ if (unlikely(debug))
-+ dev_info(&wc->dev->dev, "Got tone %s of '%c' "
-+ "on channel %d of span %d\n",
-+ (start ? "START" : "STOP"),
-+ tone, channel, span + 1);
-+ if (test_bit(channel, &wc->tspans[span]->dtmfmask) && (tone != 'u')) {
-+ if (start) {
-+ /* The octasic is supposed to mute us, but... Yah, you
-+ guessed it. */
-+ if (test_bit(channel, &wc->tspans[span]->dtmfmutemask)) {
-+ unsigned long flags;
-+ struct dahdi_chan *chan = wc->tspans[span]->span.chans[channel];
-+ int y;
-+ spin_lock_irqsave(&chan->lock, flags);
-+ for (y=0;y<chan->numbufs;y++) {
-+ if ((chan->inreadbuf > -1) && (chan->readidx[y]))
-+ memset(chan->readbuf[chan->inreadbuf], DAHDI_XLAW(0, chan), chan->readidx[y]);
-+ }
-+ spin_unlock_irqrestore(&chan->lock, flags);
-+ }
-+ set_bit(channel, &wc->tspans[span]->dtmfactive);
-+ dahdi_qevent_lock(wc->tspans[span]->span.chans[channel], (DAHDI_EVENT_DTMFDOWN | tone));
-+ } else {
-+ clear_bit(channel, &wc->tspans[span]->dtmfactive);
-+ dahdi_qevent_lock(wc->tspans[span]->span.chans[channel], (DAHDI_EVENT_DTMFUP | tone));
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+#endif /* VPM_SUPPORT */
-+
-+static void hdlc_stop(struct t4 *wc, unsigned int span)
-+{
-+ struct t4_span *t = wc->tspans[span];
-+ unsigned char imr0, imr1, mode;
-+ unsigned long flags;
-+ int i = 0;
-+
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Stopping HDLC controller on span "
-+ "%d\n", span+1);
-+
-+ /* Clear receive and transmit timeslots */
-+ for (i = 0; i < 4; i++) {
-+ t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00);
-+ t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00);
-+ }
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ imr0 = __t4_framer_in(wc, span, FRMR_IMR0);
-+ imr1 = __t4_framer_in(wc, span, FRMR_IMR1);
-+
-+ /* Disable HDLC interrupts */
-+ imr0 |= HDLC_IMR0_MASK;
-+ __t4_framer_out(wc, span, FRMR_IMR0, imr0);
-+
-+ imr1 |= HDLC_IMR1_MASK;
-+ __t4_framer_out(wc, span, FRMR_IMR1, imr1);
-+
-+ mode = __t4_framer_in(wc, span, FRMR_MODE);
-+ mode &= ~FRMR_MODE_HRAC;
-+ __t4_framer_out(wc, span, FRMR_MODE, mode);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ t->sigactive = 0;
-+}
-+
-+static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd)
-+{
-+ __t4_framer_out(wc, span, FRMR_CMDR, cmd);
-+}
-+
-+static inline void t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd)
-+{
-+ int sis;
-+ int loops = 0;
-+
-+ /* XXX could be time consuming XXX */
-+ for (;;) {
-+ sis = t4_framer_in(wc, span, FRMR_SIS);
-+ if (!(sis & 0x04))
-+ break;
-+ if (!loops++ && (debug & DEBUG_FRAMER)) {
-+ dev_notice(&wc->dev->dev, "!!!SIS Waiting before cmd "
-+ "%02x\n", cmd);
-+ }
-+ }
-+ if (loops && (debug & DEBUG_FRAMER))
-+ dev_notice(&wc->dev->dev, "!!!SIS waited %d loops\n", loops);
-+
-+ t4_framer_out(wc, span, FRMR_CMDR, cmd);
-+}
-+
-+static int hdlc_start(struct t4 *wc, unsigned int span, struct dahdi_chan *chan, unsigned char mode)
-+{
-+ struct t4_span *t = wc->tspans[span];
-+ unsigned char imr0, imr1;
-+ int offset = chan->chanpos;
-+ unsigned long flags;
-+
-+ if (debug & DEBUG_FRAMER)
-+ dev_info(&wc->dev->dev, "Starting HDLC controller for channel "
-+ "%d span %d\n", offset, span+1);
-+
-+ if (mode != FRMR_MODE_NO_ADDR_CMP)
-+ return -1;
-+
-+ mode |= FRMR_MODE_HRAC;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ /* Make sure we're in the right mode */
-+ __t4_framer_out(wc, span, FRMR_MODE, mode);
-+ __t4_framer_out(wc, span, FRMR_TSEO, 0x00);
-+ __t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode);
-+
-+ /* Set the interframe gaps, etc */
-+ __t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
-+
-+ __t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
-+
-+ /* Set up the time slot that we want to tx/rx on */
-+ __t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
-+ __t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
-+
-+ imr0 = __t4_framer_in(wc, span, FRMR_IMR0);
-+ imr1 = __t4_framer_in(wc, span, FRMR_IMR1);
-+
-+ /* Enable our interrupts again */
-+ imr0 &= ~HDLC_IMR0_MASK;
-+ __t4_framer_out(wc, span, FRMR_IMR0, imr0);
-+
-+ imr1 &= ~HDLC_IMR1_MASK;
-+ __t4_framer_out(wc, span, FRMR_IMR1, imr1);
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ /* Reset the signaling controller */
-+ t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ t->sigchan = chan;
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ t->sigactive = 0;
-+
-+ return 0;
-+}
-+
-+static void __set_clear(struct t4 *wc, int span)
-+{
-+ int i,j;
-+ int oldnotclear;
-+ unsigned short val=0;
-+ struct t4_span *ts = wc->tspans[span];
-+
-+ oldnotclear = ts->notclear;
-+ if (E1 != ts->linemode) {
-+ for (i=0;i<24;i++) {
-+ j = (i/8);
-+ if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR) {
-+ val |= 1 << (7 - (i % 8));
-+ ts->notclear &= ~(1 << i);
-+ } else
-+ ts->notclear |= (1 << i);
-+ if ((i % 8)==7) {
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Putting %d "
-+ "in register %02x on span %d"
-+ "\n", val, 0x2f + j, span + 1);
-+ __t4_framer_out(wc, span, 0x2f + j, val);
-+ val = 0;
-+ }
-+ }
-+ } else {
-+ for (i=0;i<31;i++) {
-+ if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR)
-+ ts->notclear &= ~(1 << i);
-+ else
-+ ts->notclear |= (1 << i);
-+ }
-+ }
-+ if (ts->notclear != oldnotclear) {
-+ unsigned char reg;
-+ reg = __t4_framer_in(wc, span, FRMR_IMR0);
-+ if (ts->notclear)
-+ reg &= ~0x08;
-+ else
-+ reg |= 0x08;
-+ __t4_framer_out(wc, span, FRMR_IMR0, reg);
-+ }
-+}
-+
-+static int t4_dacs(struct dahdi_chan *dst, struct dahdi_chan *src)
-+{
-+ struct t4 *wc;
-+ struct t4_span *ts;
-+ wc = dst->pvt;
-+ ts = wc->tspans[dst->span->offset];
-+ if (src && (src->pvt != dst->pvt)) {
-+ if (ts->spanflags & FLAG_2NDGEN)
-+ t4_tsi_unassign(wc, dst->span->offset, dst->chanpos);
-+ wc = src->pvt;
-+ if (ts->spanflags & FLAG_2NDGEN)
-+ t4_tsi_unassign(wc, src->span->offset, src->chanpos);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Unassigning %d/%d by "
-+ "default and...\n", src->span->offset,
-+ src->chanpos);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Unassigning %d/%d by "
-+ "default\n", dst->span->offset, dst->chanpos);
-+ return -1;
-+ }
-+ if (src) {
-+ t4_tsi_assign(wc, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Assigning channel %d/%d -> "
-+ "%d/%d!\n", src->span->offset, src->chanpos,
-+ dst->span->offset, dst->chanpos);
-+ } else {
-+ t4_tsi_unassign(wc, dst->span->offset, dst->chanpos);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Unassigning channel %d/%d!"
-+ "\n", dst->span->offset, dst->chanpos);
-+ }
-+ return 0;
-+}
-+
-+#ifdef VPM_SUPPORT
-+
-+void oct_set_reg(void *data, unsigned int reg, unsigned int val)
-+{
-+ struct t4 *wc = data;
-+ t4_oct_out(wc, reg, val);
-+}
-+
-+unsigned int oct_get_reg(void *data, unsigned int reg)
-+{
-+ struct t4 *wc = data;
-+ unsigned int ret;
-+ ret = t4_oct_in(wc, reg);
-+ return ret;
-+}
-+
-+static const char *__t4_echocan_name(struct t4 *wc)
-+{
-+ if (wc->vpm) {
-+ if (wc->numspans == 2)
-+ return vpmoct064_name;
-+ else if (wc->numspans == 4)
-+ return vpmoct128_name;
-+ else if (wc->numspans == 1) //cem:1port change
-+ return vpmoct032_name; //cem:1port change
-+ else if (wc->numspans == 8)
-+ return vpmoct256_name;
-+ }
-+ return NULL;
-+}
-+
-+static const char *t4_echocan_name(const struct dahdi_chan *chan)
-+{
-+ struct t4 *wc = chan->pvt;
-+ return __t4_echocan_name(wc);
-+}
-+
-+static int t4_echocan_create(struct dahdi_chan *chan,
-+ struct dahdi_echocanparams *ecp,
-+ struct dahdi_echocanparam *p,
-+ struct dahdi_echocan_state **ec)
-+{
-+ struct t4 *wc = chan->pvt;
-+ struct t4_span *tspan = container_of(chan->span, struct t4_span, span);
-+ int channel;
-+ const bool alaw = (chan->span->deflaw == 2);
-+
-+ if (!vpmsupport || !wc->vpm)
-+ return -ENODEV;
-+
-+ if (ecp->param_count > 0) {
-+ dev_warn(&wc->dev->dev, "%s echo canceller does not support "
-+ "parameters; failing request\n",
-+ chan->ec_factory->get_name(chan));
-+ return -EINVAL;
-+ }
-+
-+ *ec = tspan->ec[chan->chanpos - 1];
-+ (*ec)->ops = &vpm_ec_ops;
-+ (*ec)->features = vpm_ec_features;
-+
-+ channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
-+
-+ if (is_octal(wc))
-+ channel = channel << 3;
-+ else
-+ channel = channel << 2;
-+ channel |= chan->span->offset;
-+ if (debug & DEBUG_ECHOCAN) {
-+ dev_notice(&wc->dev->dev,
-+ "echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n",
-+ wc->num, chan->chanpos, chan->span->offset,
-+ channel, ecp->tap_length);
-+ }
-+ vpm450m_set_alaw_companding(wc->vpm, channel, alaw);
-+ vpm450m_setec(wc->vpm, channel, ecp->tap_length);
-+ return 0;
-+}
-+
-+static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec)
-+{
-+ struct t4 *wc = chan->pvt;
-+ int channel;
-+
-+ if (!wc->vpm)
-+ return;
-+
-+ memset(ec, 0, sizeof(*ec));
-+ channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
-+
-+ if (is_octal(wc))
-+ channel = channel << 3;
-+ else
-+ channel = channel << 2;
-+ channel |= chan->span->offset;
-+ if (debug & DEBUG_ECHOCAN) {
-+ dev_notice(&wc->dev->dev,
-+ "echocan: Card is %d, Channel is %d, Span is %d, offset is %d length 0\n",
-+ wc->num, chan->chanpos, chan->span->offset, channel);
-+ }
-+ vpm450m_setec(wc->vpm, channel, 0);
-+}
-+#endif
-+
-+static int t4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data)
-+{
-+ struct t4_regs regs;
-+ struct t4_reg reg;
-+ int x;
-+ struct t4 *wc = chan->pvt;
-+#ifdef VPM_SUPPORT
-+ int j;
-+ int channel;
-+ struct t4_span *ts = wc->tspans[chan->span->offset];
-+#endif
-+
-+ switch(cmd) {
-+ case WCT4_SET_REG:
-+ if (copy_from_user(&reg, (struct t4_reg __user *)data,
-+ sizeof(reg)))
-+ return -EFAULT;
-+ t4_pci_out(wc, reg.reg, reg.val);
-+ break;
-+ case WCT4_GET_REG:
-+ if (copy_from_user(&reg, (struct t4_reg __user *)data,
-+ sizeof(reg)))
-+ return -EFAULT;
-+ reg.val = t4_pci_in(wc, reg.reg);
-+ if (copy_to_user((struct t4_reg __user *)data,
-+ &reg, sizeof(reg)))
-+ return -EFAULT;
-+ break;
-+ case WCT4_GET_REGS:
-+ for (x=0;x<NUM_PCI;x++)
-+ regs.pci[x] = t4_pci_in(wc, x);
-+ for (x=0;x<NUM_REGS;x++)
-+ regs.regs[x] = t4_framer_in(wc, chan->span->offset, x);
-+ if (copy_to_user((void __user *) data,
-+ &regs, sizeof(regs)))
-+ return -EFAULT;
-+ break;
-+#ifdef VPM_SUPPORT
-+ case DAHDI_TONEDETECT:
-+ if (get_user(j, (__user int *) data))
-+ return -EFAULT;
-+ if (!wc->vpm)
-+ return -ENOSYS;
-+ if (j && (vpmdtmfsupport == 0))
-+ return -ENOSYS;
-+ if (j & DAHDI_TONEDETECT_ON)
-+ set_bit(chan->chanpos - 1, &ts->dtmfmask);
-+ else
-+ clear_bit(chan->chanpos - 1, &ts->dtmfmask);
-+ if (j & DAHDI_TONEDETECT_MUTE)
-+ set_bit(chan->chanpos - 1, &ts->dtmfmutemask);
-+ else
-+ clear_bit(chan->chanpos - 1, &ts->dtmfmutemask);
-+
-+ channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
-+ if (is_octal(wc))
-+ channel = channel << 3;
-+ else
-+ channel = channel << 2;
-+ channel |= chan->span->offset;
-+ vpm450m_setdtmf(wc->vpm, channel, j & DAHDI_TONEDETECT_ON,
-+ j & DAHDI_TONEDETECT_MUTE);
-+ return 0;
-+#endif
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+}
-+
-+static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts)
-+{
-+ int res, i;
-+ unsigned int size = 32;
-+ unsigned char buf[32];
-+
-+ res = dahdi_hdlc_getbuf(ts->sigchan, buf, &size);
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Got buffer sized %d and res %d "
-+ "for %d\n", size, res, span);
-+ if (size > 0) {
-+ ts->sigactive = 1;
-+
-+ if (debug & DEBUG_FRAMER) {
-+ dev_notice(&wc->dev->dev, "TX(");
-+ for (i = 0; i < size; i++)
-+ dev_notice(&wc->dev->dev, "%s%02x",
-+ (i ? " " : ""), buf[i]);
-+ dev_notice(&wc->dev->dev, ")\n");
-+ }
-+
-+ for (i = 0; i < size; i++)
-+ t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]);
-+
-+ if (res) /* End of message */ {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev,
-+ "transmiting XHF|XME\n");
-+ t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME);
-+ ++ts->frames_out;
-+ if ((debug & DEBUG_FRAMER) && !(ts->frames_out & 0x0f))
-+ dev_notice(&wc->dev->dev, "Transmitted %d "
-+ "frames on span %d\n", ts->frames_out,
-+ span);
-+ } else { /* Still more to transmit */
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "transmiting XHF\n");
-+ t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF);
-+ }
-+ }
-+ else if (res < 0)
-+ ts->sigactive = 0;
-+}
-+
-+static void t4_hdlc_hard_xmit(struct dahdi_chan *chan)
-+{
-+ struct t4 *wc = chan->pvt;
-+ int span = chan->span->offset;
-+ struct t4_span *ts = wc->tspans[span];
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ if (!ts->sigchan) {
-+ dev_notice(&wc->dev->dev, "t4_hdlc_hard_xmit: Invalid (NULL) "
-+ "signalling channel\n");
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return;
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "t4_hdlc_hard_xmit on channel %s "
-+ "(sigchan %s), sigactive=%d\n", chan->name,
-+ ts->sigchan->name, ts->sigactive);
-+
-+ if ((ts->sigchan == chan) && !ts->sigactive)
-+ t4_hdlc_xmit_fifo(wc, span, ts);
-+}
-+
-+/**
-+ * t4_set_framer_bits - Atomically set bits in a framer register.
-+ */
-+static void t4_set_framer_bits(struct t4 *wc, unsigned int spanno,
-+ unsigned int const addr, u16 bits)
-+{
-+ unsigned long flags;
-+ unsigned int reg;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ reg = __t4_framer_in(wc, spanno, addr);
-+ __t4_framer_out(wc, spanno, addr, (reg | bits));
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+static int t4_maint(struct dahdi_span *span, int cmd)
-+{
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ struct t4 *wc = ts->owner;
-+ unsigned int reg;
-+ unsigned long flags;
-+
-+ if (E1 == ts->linemode) {
-+ switch(cmd) {
-+ case DAHDI_MAINT_NONE:
-+ dev_info(&wc->dev->dev, "Clearing all maint modes\n");
-+ t4_clear_maint(span);
-+ break;
-+ case DAHDI_MAINT_LOCALLOOP:
-+ dev_info(&wc->dev->dev,
-+ "Turning on local loopback\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, LIM0_T, LIM0_LL);
-+ break;
-+ case DAHDI_MAINT_NETWORKLINELOOP:
-+ dev_info(&wc->dev->dev,
-+ "Turning on network line loopback\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, LIM1_T, LIM1_RL);
-+ break;
-+ case DAHDI_MAINT_NETWORKPAYLOADLOOP:
-+ dev_info(&wc->dev->dev,
-+ "Turning on network payload loopback\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, FMR2_T, FMR2_PLB);
-+ break;
-+ case DAHDI_MAINT_LOOPUP:
-+ case DAHDI_MAINT_LOOPDOWN:
-+ dev_info(&wc->dev->dev,
-+ "Loopup & loopdown not supported in E1 mode\n");
-+ return -ENOSYS;
-+ case DAHDI_MAINT_FAS_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IFASE);
-+ break;
-+ case DAHDI_MAINT_MULTI_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IMFE);
-+ break;
-+ case DAHDI_MAINT_CRC_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, ICRCE);
-+ break;
-+ case DAHDI_MAINT_CAS_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, ICASE);
-+ break;
-+ case DAHDI_MAINT_PRBS_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IPE);
-+ break;
-+ case DAHDI_MAINT_BIPOLAR_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IBV);
-+ break;
-+ case DAHDI_RESET_COUNTERS:
-+ t4_reset_counters(span);
-+ break;
-+ case DAHDI_MAINT_ALARM_SIM:
-+ dev_info(&wc->dev->dev, "Invoking alarm state");
-+ t4_set_framer_bits(wc, span->offset, FMR0, FMR0_SIM);
-+ break;
-+ default:
-+ dev_info(&wc->dev->dev,
-+ "Unknown E1 maint command: %d\n", cmd);
-+ return -ENOSYS;
-+ }
-+ } else {
-+ switch(cmd) {
-+ case DAHDI_MAINT_NONE:
-+ dev_info(&wc->dev->dev, "Clearing all maint modes\n");
-+ t4_clear_maint(span);
-+ break;
-+ case DAHDI_MAINT_LOCALLOOP:
-+ dev_info(&wc->dev->dev,
-+ "Turning on local loopback\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, LIM0_T, LIM0_LL);
-+ break;
-+ case DAHDI_MAINT_NETWORKLINELOOP:
-+ dev_info(&wc->dev->dev,
-+ "Turning on network line loopback\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, LIM1_T, LIM1_RL);
-+ break;
-+ case DAHDI_MAINT_NETWORKPAYLOADLOOP:
-+ dev_info(&wc->dev->dev,
-+ "Turning on network payload loopback\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, FMR2_T, FMR2_PLB);
-+ break;
-+ case DAHDI_MAINT_LOOPUP:
-+ dev_info(&wc->dev->dev, "Transmitting loopup code\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, FMR5, FMR5_XLU);
-+ ts->span.maintstat = DAHDI_MAINT_REMOTELOOP;
-+ break;
-+ case DAHDI_MAINT_LOOPDOWN:
-+ dev_info(&wc->dev->dev, "Transmitting loopdown code\n");
-+ t4_clear_maint(span);
-+ t4_set_framer_bits(wc, span->offset, FMR5, FMR5_XLD);
-+ break;
-+ case DAHDI_MAINT_FAS_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IFASE);
-+ break;
-+ case DAHDI_MAINT_MULTI_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IMFE);
-+ break;
-+ case DAHDI_MAINT_CRC_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, ICRCE);
-+ break;
-+ case DAHDI_MAINT_CAS_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, ICASE);
-+ break;
-+ case DAHDI_MAINT_PRBS_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IPE);
-+ break;
-+ case DAHDI_MAINT_BIPOLAR_DEFECT:
-+ t4_framer_out(wc, span->offset, IERR_T, IBV);
-+ break;
-+ case DAHDI_MAINT_PRBS:
-+ dev_info(&wc->dev->dev, "PRBS not supported\n");
-+ return -ENOSYS;
-+ case DAHDI_RESET_COUNTERS:
-+ t4_reset_counters(span);
-+ break;
-+ case DAHDI_MAINT_ALARM_SIM:
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ reg = __t4_framer_in(wc, span->offset, FMR0);
-+
-+ /*
-+ * The alarm simulation state machine requires us to
-+ * bring this bit up and down for at least 1 clock cycle
-+ */
-+ __t4_framer_out(wc, span->offset,
-+ FMR0, (reg | FMR0_SIM));
-+ udelay(1);
-+ __t4_framer_out(wc, span->offset,
-+ FMR0, (reg & ~FMR0_SIM));
-+ udelay(1);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ reg = t4_framer_in(wc, span->offset, 0x4e);
-+ if (debug & DEBUG_MAIN) {
-+ dev_info(&wc->dev->dev,
-+ "FRS2(alarm state): %d\n",
-+ ((reg & 0xe0) >> 5));
-+ }
-+ break;
-+ default:
-+ dev_info(&wc->dev->dev, "Unknown T1 maint command:%d\n",
-+ cmd);
-+ break;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int t4_clear_maint(struct dahdi_span *span)
-+{
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ struct t4 *wc = ts->owner;
-+ unsigned int reg;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ /* Clear local loop */
-+ reg = __t4_framer_in(wc, span->offset, LIM0_T);
-+ __t4_framer_out(wc, span->offset, LIM0_T, (reg & ~LIM0_LL));
-+
-+ /* Clear Remote Loop */
-+ reg = __t4_framer_in(wc, span->offset, LIM1_T);
-+ __t4_framer_out(wc, span->offset, LIM1_T, (reg & ~LIM1_RL));
-+
-+ /* Clear Remote Payload Loop */
-+ reg = __t4_framer_in(wc, span->offset, FMR2_T);
-+ __t4_framer_out(wc, span->offset, FMR2_T, (reg & ~FMR2_PLB));
-+
-+ /* Clear PRBS */
-+ reg = __t4_framer_in(wc, span->offset, LCR1_T);
-+ __t4_framer_out(wc, span->offset, LCR1_T, (reg & ~(XPRBS | EPRM)));
-+
-+ /* Clear loopup/loopdown signals on the line */
-+ reg = __t4_framer_in(wc, span->offset, FMR5);
-+ __t4_framer_out(wc, span->offset, FMR5, (reg & ~(FMR5_XLU | FMR5_XLD)));
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ span->mainttimer = 0;
-+
-+ return 0;
-+}
-+
-+static int t4_reset_counters(struct dahdi_span *span)
-+{
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ memset(&ts->span.count, 0, sizeof(ts->span.count));
-+ return 0;
-+}
-+
-+static int t4_rbsbits(struct dahdi_chan *chan, int bits)
-+{
-+ u_char m,c;
-+ int k,n,b;
-+ struct t4 *wc = chan->pvt;
-+ struct t4_span *ts = wc->tspans[chan->span->offset];
-+ unsigned long flags;
-+
-+ if (debug & DEBUG_RBS)
-+ dev_notice(&wc->dev->dev, "Setting bits to %d on channel %s\n",
-+ bits, chan->name);
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ k = chan->span->offset;
-+ if (E1 == ts->linemode) {
-+ if (chan->chanpos == 16) {
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return 0;
-+ }
-+ n = chan->chanpos - 1;
-+ if (chan->chanpos > 15) n--;
-+ b = (n % 15);
-+ c = ts->txsigs[b];
-+ m = (n / 15) << 2; /* nibble selector */
-+ c &= (0xf << m); /* keep the other nibble */
-+ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
-+ ts->txsigs[b] = c;
-+ /* output them to the chip */
-+ __t4_framer_out(wc,k,0x71 + b,c);
-+ } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) {
-+ n = chan->chanpos - 1;
-+ b = (n/4);
-+ c = ts->txsigs[b];
-+ m = ((3 - (n % 4)) << 1); /* nibble selector */
-+ c &= ~(0x3 << m); /* keep the other nibble */
-+ c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */
-+ ts->txsigs[b] = c;
-+ /* output them to the chip */
-+ __t4_framer_out(wc,k,0x70 + b,c);
-+ __t4_framer_out(wc,k,0x70 + b + 6,c);
-+ } else if (ts->span.lineconfig & DAHDI_CONFIG_ESF) {
-+ n = chan->chanpos - 1;
-+ b = (n/2);
-+ c = ts->txsigs[b];
-+ m = ((n % 2) << 2); /* nibble selector */
-+ c &= (0xf << m); /* keep the other nibble */
-+ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
-+ ts->txsigs[b] = c;
-+ /* output them to the chip */
-+ __t4_framer_out(wc,k,0x70 + b,c);
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ if (debug & DEBUG_RBS)
-+ dev_notice(&wc->dev->dev, "Finished setting RBS bits\n");
-+ return 0;
-+}
-+
-+static int t4_shutdown(struct dahdi_span *span)
-+{
-+ int tspan;
-+ int wasrunning;
-+ unsigned long flags;
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ struct t4 *wc = ts->owner;
-+
-+ tspan = span->offset + 1;
-+ if (tspan < 0) {
-+ dev_notice(&wc->dev->dev, "T%dXXP: Span '%d' isn't us?\n",
-+ wc->numspans, span->spanno);
-+ return -1;
-+ }
-+
-+ if (debug & DEBUG_MAIN)
-+ dev_notice(&wc->dev->dev, "Shutting down span %d (%s)\n",
-+ span->spanno, span->name);
-+
-+ /* Stop HDLC controller if runned */
-+ if (ts->sigchan)
-+ hdlc_stop(wc, span->offset);
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ wasrunning = span->flags & DAHDI_FLAG_RUNNING;
-+
-+ span->flags &= ~DAHDI_FLAG_RUNNING;
-+ __t4_set_led(wc, span->offset, WC_OFF);
-+ if (((wc->numspans == 8) &&
-+ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[4]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[5]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[6]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[7]->span.flags & DAHDI_FLAG_RUNNING)))
-+ ||
-+ ((wc->numspans == 4) &&
-+ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)))
-+ ||
-+ ((wc->numspans == 1) && //cem:1port change
-+ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING))) //cem:1port change
-+ ||
-+ ((wc->numspans == 2) &&
-+ (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) &&
-+ (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)))) {
-+ /* No longer in use, disable interrupts */
-+ dev_info(&wc->dev->dev, "ALLO%dXXP: Disabling interrupts since "
-+ "there are no active spans\n", wc->numspans);
-+ set_bit(T4_STOP_DMA, &wc->checkflag);
-+ } else
-+ set_bit(T4_CHECK_TIMING, &wc->checkflag);
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ /* Wait for interrupt routine to shut itself down */
-+ msleep(10);
-+ if (wasrunning)
-+ wc->spansstarted--;
-+
-+ if (debug & DEBUG_MAIN)
-+ dev_notice(&wc->dev->dev, "Span %d (%s) shutdown\n",
-+ span->spanno, span->name);
-+ return 0;
-+}
-+
-+static void t4_chan_set_sigcap(struct dahdi_span *span, int x)
-+{
-+ struct t4_span *wc = container_of(span, struct t4_span, span);
-+ struct dahdi_chan *chan = wc->chans[x];
-+ chan->sigcap = DAHDI_SIG_CLEAR;
-+ /* E&M variant supported depends on span type */
-+ if (E1 == wc->linemode) {
-+ /* E1 sigcap setup */
-+ if (span->lineconfig & DAHDI_CONFIG_CCS) {
-+ /* CCS setup */
-+ chan->sigcap |= DAHDI_SIG_MTP2 | DAHDI_SIG_SF |
-+ DAHDI_SIG_HARDHDLC;
-+ return;
-+ }
-+ /* clear out sig and sigcap for channel 16 on E1 CAS
-+ * lines, otherwise, set it correctly */
-+ if (x == 15) {
-+ /* CAS signaling channel setup */
-+ wc->chans[15]->sigcap = 0;
-+ wc->chans[15]->sig = 0;
-+ return;
-+ }
-+ /* normal CAS setup */
-+ chan->sigcap |= DAHDI_SIG_EM_E1 | DAHDI_SIG_FXSLS |
-+ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_SF |
-+ DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS |
-+ DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS;
-+ } else {
-+ /* T1 sigcap setup */
-+ chan->sigcap |= DAHDI_SIG_EM | DAHDI_SIG_FXSLS |
-+ DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_MTP2 |
-+ DAHDI_SIG_SF | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS |
-+ DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_DACS_RBS |
-+ DAHDI_SIG_HARDHDLC;
-+ }
-+}
-+
-+static int
-+_t4_spanconfig(struct file *file, struct dahdi_span *span,
-+ struct dahdi_lineconfig *lc)
-+{
-+ int i;
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ struct t4 *wc = ts->owner;
-+
-+ if (debug)
-+ dev_info(&wc->dev->dev, "About to enter spanconfig!\n");
-+ if (debug & DEBUG_MAIN)
-+ dev_notice(&wc->dev->dev, "ALLO%dXXP: Configuring span %d\n",
-+ wc->numspans, span->spanno);
-+
-+ 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);
-+ lc->sync = 0;
-+ }
-+
-+ /* remove this span number from the current sync sources, if there */
-+ for(i = 0; i < wc->numspans; i++) {
-+ if (wc->tspans[i]->sync == span->spanno)
-+ wc->tspans[i]->sync = 0;
-+ }
-+ wc->tspans[span->offset]->syncpos = lc->sync;
-+ /* if a sync src, put it in proper place */
-+ if (lc->sync)
-+ wc->tspans[lc->sync - 1]->sync = span->spanno;
-+
-+ set_bit(T4_CHECK_TIMING, &wc->checkflag);
-+
-+ /* Make sure this is clear in case of multiple startup and shutdown
-+ * iterations */
-+ clear_bit(T4_STOP_DMA, &wc->checkflag);
-+
-+ /* make sure that sigcaps gets updated if necessary */
-+ for (i = 0; i < span->channels; i++)
-+ t4_chan_set_sigcap(span, i);
-+
-+ /* If we're already running, then go ahead and apply the changes */
-+ if (span->flags & DAHDI_FLAG_RUNNING)
-+ return _t4_startup(file, span);
-+
-+ if (debug)
-+ dev_info(&wc->dev->dev, "Done with spanconfig!\n");
-+ return 0;
-+}
-+
-+static int
-+t4_spanconfig(struct file *file, struct dahdi_span *span,
-+ struct dahdi_lineconfig *lc)
-+{
-+ int ret;
-+ struct dahdi_device *const ddev = span->parent;
-+ struct dahdi_span *s;
-+
-+ ret = _t4_spanconfig(file, span, lc);
-+
-+ /* Make sure all the spans have a basic configuration in case they are
-+ * not all specified in the configuration files. */
-+ lc->sync = 0;
-+ list_for_each_entry(s, &ddev->spans, device_node) {
-+ WARN_ON(!s->channels);
-+ if (!s->channels)
-+ continue;
-+ if (!s->chans[0]->sigcap)
-+ _t4_spanconfig(file, s, lc);
-+ }
-+ return ret;
-+}
-+
-+static int
-+t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
-+{
-+ int alreadyrunning;
-+ unsigned long flags;
-+ struct t4 *wc = chan->pvt;
-+ struct t4_span *ts = wc->tspans[chan->span->offset];
-+
-+ alreadyrunning = ts->span.flags & DAHDI_FLAG_RUNNING;
-+ if (debug & DEBUG_MAIN) {
-+ if (alreadyrunning)
-+ dev_notice(&wc->dev->dev, "ALLO%dXXP: Reconfigured "
-+ "channel %d (%s) sigtype %d\n", wc->numspans,
-+ chan->channo, chan->name, sigtype);
-+ else
-+ dev_notice(&wc->dev->dev, "ALLO%dXXP: Configured channel"
-+ " %d (%s) sigtype %d\n", wc->numspans,
-+ chan->channo, chan->name, sigtype);
-+ }
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ if (alreadyrunning)
-+ __set_clear(wc, chan->span->offset);
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ /* (re)configure signalling channel */
-+ if ((sigtype == DAHDI_SIG_HARDHDLC) || (ts->sigchan == chan)) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "%sonfiguring hardware HDLC "
-+ "on %s\n",
-+ ((sigtype == DAHDI_SIG_HARDHDLC) ? "C" : "Unc"),
-+ chan->name);
-+ if (alreadyrunning) {
-+ if (ts->sigchan)
-+ hdlc_stop(wc, ts->sigchan->span->offset);
-+ if (sigtype == DAHDI_SIG_HARDHDLC) {
-+ if (hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) {
-+ dev_notice(&wc->dev->dev, "Error "
-+ "initializing signalling "
-+ "controller\n");
-+ return -1;
-+ }
-+ } else {
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ ts->sigchan = NULL;
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ }
-+
-+ }
-+ else {
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ ts->sigchan = (sigtype == DAHDI_SIG_HARDHDLC) ? chan : NULL;
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ ts->sigactive = 0;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int t4_open(struct dahdi_chan *chan)
-+{
-+ return 0;
-+}
-+
-+static int t4_close(struct dahdi_chan *chan)
-+{
-+ return 0;
-+}
-+
-+static int set_span_devicetype(struct t4 *wc)
-+{
-+#ifdef VPM_SUPPORT
-+ const char *vpmstring = __t4_echocan_name(wc);
-+
-+ if (vpmstring) {
-+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, "%s (%s)",
-+ wc->devtype->desc, vpmstring);
-+ } else {
-+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc);
-+ }
-+#else
-+ wc->ddev->devicetype = kasprintf(GFP_KERNEL, wc->devtype->desc);
-+#endif
-+
-+ if (!wc->ddev->devicetype)
-+ return -ENOMEM;
-+ return 0;
-+}
-+
-+/* The number of cards we have seen with each
-+ possible 'order' switch setting.
-+*/
-+static unsigned int order_index[16];
-+
-+static void setup_chunks(struct t4 *wc, int which)
-+{
-+ struct t4_span *ts;
-+ int offset = 1;
-+ int x, y;
-+ int gen2;
-+ int basesize = T4_BASE_SIZE(wc) >> 2;
-+
-+ if (!has_e1_span(wc))
-+ offset += 4;
-+
-+ gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN);
-+
-+ for (x = 0; x < wc->numspans; x++) {
-+ ts = wc->tspans[x];
-+ ts->writechunk = (void *)(wc->writechunk + (x * 32 * 2) + (which * (basesize)));
-+ ts->readchunk = (void *)(wc->readchunk + (x * 32 * 2) + (which * (basesize)));
-+ for (y=0;y<wc->tspans[x]->span.channels;y++) {
-+ struct dahdi_chan *mychans = ts->chans[y];
-+ if (gen2) {
-+ mychans->writechunk = (void *)(wc->writechunk + ((x * 32 + y + offset) * 2) + (which * (basesize)));
-+ mychans->readchunk = (void *)(wc->readchunk + ((x * 32 + y + offset) * 2) + (which * (basesize)));
-+ }
-+ }
-+ }
-+}
-+
-+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.
-+ *
-+ */
-+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,
-+ "ALLO%dXXP: Setting up global serial parameters\n",
-+ wc->numspans);//cEM:
-+ }
-+
-+ 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 */
-+ __t4_framer_out(wc, 0, 0x85, 0xe0);
-+ if (is_octal(wc))
-+ __t4_framer_out(wc, 0, FRMR_GPC2, 0x00);
-+
-+ /* IPC: Interrupt push/pull active low */
-+ __t4_framer_out(wc, 0, 0x08, 0x01);
-+
-+ if (is_octal(wc)) {
-+ /* Global clocks (16.384 Mhz CLK) */
-+ __t4_framer_out(wc, 0, 0x92, 0x00); /* GCM1 */
-+ __t4_framer_out(wc, 0, 0x93, 0x18);
-+ __t4_framer_out(wc, 0, 0x94, 0xfb);
-+ __t4_framer_out(wc, 0, 0x95, 0x0b);
-+ __t4_framer_out(wc, 0, 0x96, 0x01);
-+ __t4_framer_out(wc, 0, 0x97, 0x0b);
-+ __t4_framer_out(wc, 0, 0x98, 0xdb);
-+ __t4_framer_out(wc, 0, 0x99, 0xdf);
-+ } else {
-+ /* Global clocks (8.192 Mhz CLK) */
-+ __t4_framer_out(wc, 0, 0x92, 0x00);
-+ __t4_framer_out(wc, 0, 0x93, 0x18);
-+ __t4_framer_out(wc, 0, 0x94, 0xfb);
-+ __t4_framer_out(wc, 0, 0x95, 0x0b);
-+ __t4_framer_out(wc, 0, 0x96, 0x00);
-+ __t4_framer_out(wc, 0, 0x97, 0x0b);
-+ __t4_framer_out(wc, 0, 0x98, 0xdb);
-+ __t4_framer_out(wc, 0, 0x99, 0xdf);
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ for (unit = 0; unit < ports_on_framer(wc); ++unit) {
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ /* Configure interrupts */
-+ /* GCR: Interrupt on Activation/Deactivation of each */
-+ __t4_framer_out(wc, unit, FRMR_GCR, 0x00);
-+
-+ /* Configure system interface */
-+ if (is_octal(wc)) {
-+ /* SIC1: 16.384 Mhz clock/bus, double buffer receive /
-+ * transmit, byte interleaved */
-+ __t4_framer_out(wc, unit, FRMR_SIC1, 0xc2 | 0x08);
-+ } else {
-+ /* SIC1: 8.192 Mhz clock/bus, double buffer receive /
-+ * transmit, byte interleaved */
-+ __t4_framer_out(wc, unit, FRMR_SIC1, 0xc2);
-+ }
-+ /* SIC2: No FFS, no center receive eliastic buffer, phase */
-+ __t4_framer_out(wc, unit, FRMR_SIC2, 0x20 | (unit << 1));
-+ /* SIC3: Edges for capture */
-+ if (is_octal(wc)) {
-+ __t4_framer_out(wc, unit, FRMR_SIC3, 0x04 | (1 << 4));
-+ } else {
-+ __t4_framer_out(wc, unit, FRMR_SIC3, 0x04);
-+ }
-+ /* CMR2: We provide sync and clock for tx and rx. */
-+ __t4_framer_out(wc, unit, FRMR_CMR2, 0x00);
-+
-+ if (is_octal(wc)) {
-+ /* Set RCLK to 16 MHz */
-+ __t4_framer_out(wc, unit, FRMR_CMR4, 0x5);
-+
-+ if (!has_e1_span(wc)) { /* T1/J1 mode */
-+ __t4_framer_out(wc, unit, FRMR_XC0, 0x07);
-+ __t4_framer_out(wc, unit, FRMR_XC1, 0x04);
-+ if (wc->tspans[unit]->linemode == J1)
-+ __t4_framer_out(wc, unit, FRMR_RC0, 0x87);
-+ else
-+ __t4_framer_out(wc, unit, FRMR_RC0, 0x07);
-+ __t4_framer_out(wc, unit, FRMR_RC1, 0x04);
-+ } else { /* E1 mode */
-+ __t4_framer_out(wc, unit, FRMR_XC0, 0x00);
-+ __t4_framer_out(wc, unit, FRMR_XC1, 0x04);
-+ __t4_framer_out(wc, unit, FRMR_RC0, 0x00);
-+ __t4_framer_out(wc, unit, FRMR_RC1, 0x04);
-+ }
-+
-+ } else {
-+ if (!has_e1_span(wc)) { /* T1/J1 mode */
-+ __t4_framer_out(wc, unit, FRMR_XC0, 0x03);
-+ __t4_framer_out(wc, unit, FRMR_XC1, 0x84);
-+ if (J1 == wc->tspans[unit]->linemode)
-+ __t4_framer_out(wc, unit, FRMR_RC0, 0x83);
-+ else
-+ __t4_framer_out(wc, unit, FRMR_RC0, 0x03);
-+ __t4_framer_out(wc, unit, FRMR_RC1, 0x84);
-+ } else { /* E1 mode */
-+ __t4_framer_out(wc, unit, FRMR_XC0, 0x00);
-+ __t4_framer_out(wc, unit, FRMR_XC1, 0x04);
-+ __t4_framer_out(wc, unit, FRMR_RC0, 0x04);
-+ __t4_framer_out(wc, unit, FRMR_RC1, 0x04);
-+ }
-+ }
-+
-+ /* Configure ports */
-+
-+ /* PC1: SPYR/SPYX input on RPA/XPA */
-+ __t4_framer_out(wc, unit, 0x80, 0x00);
-+
-+ /* PC2: RMFB/XSIG output/input on RPB/XPB */
-+ /* PC3: Some unused stuff */
-+ /* PC4: Some more unused stuff */
-+ if (is_octal(wc)) {
-+ __t4_framer_out(wc, unit, 0x81, 0xBB);
-+ __t4_framer_out(wc, unit, 0x82, 0xf5);
-+ __t4_framer_out(wc, unit, 0x83, 0x35);
-+ } else if (wc->falc31) {
-+ __t4_framer_out(wc, unit, 0x81, 0xBB);
-+ __t4_framer_out(wc, unit, 0x82, 0xBB);
-+ __t4_framer_out(wc, unit, 0x83, 0xBB);
-+ } else {
-+ __t4_framer_out(wc, unit, 0x81, 0x22);
-+ __t4_framer_out(wc, unit, 0x82, 0x65);
-+ __t4_framer_out(wc, unit, 0x83, 0x35);
-+ }
-+
-+ /* PC5: XMFS active low, SCLKR is input, RCLK is output */
-+ __t4_framer_out(wc, unit, 0x84, 0x01);
-+
-+ if (debug & DEBUG_MAIN) {
-+ dev_notice(&wc->dev->dev,
-+ "Successfully initialized serial bus "
-+ "for unit %d\n", unit);
-+ }
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ }
-+}
-+
-+/**
-+ * t4_span_assigned - Called when the span is assigned by DAHDI.
-+ * @span: Span that has been assigned.
-+ *
-+ * When this function is called, the span has a valid spanno and all the
-+ * channels on the span have valid channel numbers assigned.
-+ *
-+ * This function is necessary because a device may be registered, and
-+ * then user space may then later decide to assign span numbers and the
-+ * channel numbers.
-+ *
-+ */
-+static void t4_span_assigned(struct dahdi_span *span)
-+{
-+ struct t4_span *tspan = container_of(span, struct t4_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. */
-+ list_for_each_entry(pos, &wc->ddev->spans, device_node) {
-+ if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &pos->flags))
-+ ++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)
-+{
-+ unsigned int x, y;
-+
-+ for (x = 0; x < ARRAY_SIZE(wc->tspans); x++) {
-+ if (!wc->tspans[x])
-+ continue;
-+ for (y = 0; y < ARRAY_SIZE(wc->tspans[x]->chans); y++) {
-+ kfree(wc->tspans[x]->chans[y]);
-+ kfree(wc->tspans[x]->ec[y]);
-+ }
-+ kfree(wc->tspans[x]);
-+ }
-+
-+ kfree(wc->ddev->devicetype);
-+ kfree(wc->ddev->location);
-+ kfree(wc->ddev->hardware_id);
-+ dahdi_free_device(wc->ddev);
-+ kfree(wc);
-+}
-+
-+/**
-+ * t4_alloc_channels - Allocate the channels on a span.
-+ * @wc: The board we're allocating for.
-+ * @ts: The span we're allocating for.
-+ * @linemode: Which mode (T1/E1/J1) to use for this span.
-+ *
-+ * This function must only be called before the span is assigned it's
-+ * possible for user processes to have an open reference to the
-+ * channels.
-+ *
-+ */
-+static int t4_alloc_channels(struct t4 *wc, struct t4_span *ts,
-+ enum linemode linemode)
-+{
-+ int i;
-+
-+ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &ts->span.flags)) {
-+ dev_dbg(&wc->dev->dev,
-+ "Cannot allocate channels on a span that is already "
-+ "assigned.\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Cleanup any previously allocated channels. */
-+ for (i = 0; i < ARRAY_SIZE(ts->chans); ++i) {
-+ kfree(ts->chans[i]);
-+ kfree(ts->ec[i]);
-+ ts->chans[i] = NULL;
-+ ts->ec[i] = NULL;
-+ }
-+
-+ ts->linemode = linemode;
-+ for (i = 0; i < ((E1 == ts->linemode) ? 31 : 24); i++) {
-+ struct dahdi_chan *chan;
-+ struct dahdi_echocan_state *ec;
-+
-+ chan = kzalloc(sizeof(*chan), GFP_KERNEL);
-+ if (!chan) {
-+ free_wc(wc);
-+ return -ENOMEM;
-+ }
-+ ts->chans[i] = chan;
-+
-+ ec = kzalloc(sizeof(*ec), GFP_KERNEL);
-+ if (!ec) {
-+ free_wc(wc);
-+ return -ENOMEM;
-+ }
-+ ts->ec[i] = ec;
-+ }
-+
-+ return 0;
-+}
-+
-+static void t4_init_one_span(struct t4 *wc, struct t4_span *ts)
-+{
-+ unsigned long flags;
-+ unsigned int reg;
-+ int i;
-+ if(wc->numspans != 1) {
-+ snprintf(ts->span.name, sizeof(ts->span.name) - 1,
-+ "ALLO%d/%d/%d", wc->numspans, wc->num, ts->span.offset + 1);
-+ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
-+ "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num,
-+ ts->span.offset + 1);
-+ }
-+ else {
-+ snprintf(ts->span.name, sizeof(ts->span.name) - 1,
-+ "ALLO4/%d/%d", wc->num, ts->span.offset + 1); //cem:1port change
-+ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,"T4XXP (PCI) Card %d Span %d",
-+ wc->num, ts->span.offset + 1);
-+ }
-+ switch (ts->linemode) {
-+ case T1:
-+ ts->span.spantype = SPANTYPE_DIGITAL_T1;
-+ break;
-+ case E1:
-+ ts->span.spantype = SPANTYPE_DIGITAL_E1;
-+ break;
-+ case J1:
-+ ts->span.spantype = SPANTYPE_DIGITAL_J1;
-+ break;
-+ }
-+
-+ /* HDLC Specific init */
-+ ts->sigchan = NULL;
-+ ts->sigmode = sigmode;
-+ ts->sigactive = 0;
-+
-+ if (E1 != ts->linemode) {
-+ ts->span.channels = 24;
-+ ts->span.deflaw = DAHDI_LAW_MULAW;
-+ ts->span.linecompat = DAHDI_CONFIG_AMI |
-+ DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 |
-+ DAHDI_CONFIG_ESF;
-+ } else {
-+ ts->span.channels = 31;
-+ ts->span.deflaw = DAHDI_LAW_ALAW;
-+ ts->span.linecompat = DAHDI_CONFIG_AMI |
-+ DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS |
-+ DAHDI_CONFIG_CRC4;
-+ }
-+ ts->span.chans = ts->chans;
-+ ts->span.flags = DAHDI_FLAG_RBS;
-+
-+ for (i = 0; i < ts->span.channels; i++) {
-+ struct dahdi_chan *const chan = ts->chans[i];
-+ chan->pvt = wc;
-+ snprintf(chan->name, sizeof(chan->name) - 1,
-+ "%s/%d", ts->span.name, i + 1);
-+ t4_chan_set_sigcap(&ts->span, i);
-+ chan->chanpos = i + 1;
-+ }
-+
-+ /* Enable 1sec timer interrupt */
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ reg = __t4_framer_in(wc, ts->span.offset, FMR1_T);
-+ __t4_framer_out(wc, ts->span.offset, FMR1_T, (reg | FMR1_ECM));
-+
-+ /* Enable Errored Second interrupt */
-+ __t4_framer_out(wc, ts->span.offset, ESM, 0);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ t4_reset_counters(&ts->span);
-+}
-+
-+/**
-+ * t4_set_linemode - Allows user space to change the linemode before spans are assigned.
-+ * @span: span on which to change the linemode.
-+ * @linemode: A value from enumerated spantypes
-+ *
-+ * This callback is used to override the E1/T1 mode jumper settings and set
-+ * the linemode on for each span. Called when the "spantype" attribute
-+ * is written in sysfs under the dahdi_device.
-+ *
-+ */
-+static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
-+{
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ struct t4 *wc = ts->owner;
-+ int res = 0;
-+ 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));
-+
-+ 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);
-+ switch (linemode) {
-+ case SPANTYPE_DIGITAL_T1:
-+ dev_info(&wc->dev->dev,
-+ "Changing from %s to T1 line mode.\n", old_name);
-+ mode = T1;
-+ wc->t1e1 &= ~(1 << span->offset);
-+ break;
-+ case SPANTYPE_DIGITAL_E1:
-+ dev_info(&wc->dev->dev,
-+ "Changing from %s to E1 line mode.\n", old_name);
-+ mode = E1;
-+ wc->t1e1 |= (1 << span->offset);
-+ break;
-+ case SPANTYPE_DIGITAL_J1:
-+ dev_info(&wc->dev->dev,
-+ "Changing from %s to J1 line mode.\n", old_name);
-+ mode = J1;
-+ wc->t1e1 &= ~(1 << span->offset);
-+ break;
-+ default:
-+ dev_err(&wc->dev->dev,
-+ "Got invalid linemode %d from dahdi\n", linemode);
-+ res = -EINVAL;
-+ }
-+
-+ if (!res) {
-+ t4_alloc_channels(wc, ts, mode);
-+ t4_init_one_span(wc, ts);
-+ dahdi_init_span(span);
-+ }
-+
-+ mutex_unlock(&linemode_lock);
-+ return res;
-+}
-+
-+static const struct dahdi_span_ops t4_gen1_span_ops = {
-+ .owner = THIS_MODULE,
-+ .spanconfig = t4_spanconfig,
-+ .chanconfig = t4_chanconfig,
-+ .startup = t4_startup,
-+ .shutdown = t4_shutdown,
-+ .rbsbits = t4_rbsbits,
-+ .maint = t4_maint,
-+ .open = t4_open,
-+ .close = t4_close,
-+ .ioctl = t4_ioctl,
-+ .hdlc_hard_xmit = t4_hdlc_hard_xmit,
-+ .assigned = t4_span_assigned,
-+ .set_spantype = t4_set_linemode,
-+};
-+
-+static const struct dahdi_span_ops t4_gen2_span_ops = {
-+ .owner = THIS_MODULE,
-+ .spanconfig = t4_spanconfig,
-+ .chanconfig = t4_chanconfig,
-+ .startup = t4_startup,
-+ .shutdown = t4_shutdown,
-+ .rbsbits = t4_rbsbits,
-+ .maint = t4_maint,
-+ .open = t4_open,
-+ .close = t4_close,
-+ .ioctl = t4_ioctl,
-+ .hdlc_hard_xmit = t4_hdlc_hard_xmit,
-+ .dacs = t4_dacs,
-+ .assigned = t4_span_assigned,
-+ .set_spantype = t4_set_linemode,
-+#ifdef VPM_SUPPORT
-+ .echocan_create = t4_echocan_create,
-+ .echocan_name = t4_echocan_name,
-+#endif
-+};
-+
-+/**
-+ * init_spans - Do first initialization on all the spans
-+ * @wc: Card to initialize the spans on.
-+ *
-+ * This function is called *before* the dahdi_device is first registered
-+ * with the system. What happens in t4_init_one_span can happen between
-+ * when the device is registered and when the spans are assigned via
-+ * sysfs (or automatically).
-+ *
-+ */
-+static void init_spans(struct t4 *wc)
-+{
-+ int x, y;
-+ int gen2;
-+ struct t4_span *ts;
-+ unsigned int reg;
-+ unsigned long flags;
-+
-+ gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN);
-+ for (x = 0; x < wc->numspans; x++) {
-+ ts = wc->tspans[x];
-+ if(wc->numspans != 1) {
-+ sprintf(ts->span.name, "ALLO%d/%d/%d", wc->numspans, wc->num, x + 1);
-+ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
-+ "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
-+ }
-+ else {
-+ sprintf(ts->span.name, "ALLO4/%d/%d", wc->num, x + 1); //cem:1port change
-+ snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
-+ "T4XXP (PCI) Card %d Span %d", wc->num, x+1);
-+ }
-+ switch (ts->linemode) {
-+ case T1:
-+ ts->span.spantype = SPANTYPE_DIGITAL_T1;
-+ break;
-+ case E1:
-+ ts->span.spantype = SPANTYPE_DIGITAL_E1;
-+ break;
-+ case J1:
-+ ts->span.spantype = SPANTYPE_DIGITAL_J1;
-+ break;
-+ }
-+
-+ /* HDLC Specific init */
-+ ts->sigchan = NULL;
-+ ts->sigmode = sigmode;
-+ ts->sigactive = 0;
-+
-+ if (E1 != ts->linemode) {
-+ ts->span.channels = 24;
-+ ts->span.deflaw = DAHDI_LAW_MULAW;
-+ ts->span.linecompat = DAHDI_CONFIG_AMI |
-+ DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 |
-+ DAHDI_CONFIG_ESF;
-+ } else {
-+ ts->span.channels = 31;
-+ ts->span.deflaw = DAHDI_LAW_ALAW;
-+ ts->span.linecompat = DAHDI_CONFIG_AMI |
-+ DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS |
-+ DAHDI_CONFIG_CRC4;
-+ }
-+ ts->span.chans = ts->chans;
-+ ts->span.flags = DAHDI_FLAG_RBS;
-+
-+ ts->owner = wc;
-+ ts->span.offset = x;
-+ ts->writechunk = (void *)(wc->writechunk + x * 32 * 2);
-+ ts->readchunk = (void *)(wc->readchunk + x * 32 * 2);
-+
-+ if (gen2) {
-+ ts->span.ops = &t4_gen2_span_ops;
-+ } else {
-+ ts->span.ops = &t4_gen1_span_ops;
-+ }
-+
-+ for (y=0;y<wc->tspans[x]->span.channels;y++) {
-+ struct dahdi_chan *mychans = ts->chans[y];
-+ sprintf(mychans->name, "ALLO4/%d/%d/%d", wc->num, x + 1, y + 1);//cem:1port change, v002
-+ t4_chan_set_sigcap(&ts->span, x);
-+ mychans->pvt = wc;
-+ mychans->chanpos = y + 1;
-+ }
-+
-+ /* Start checking for alarms in 250 ms */
-+ ts->alarmcheck_time = jiffies + msecs_to_jiffies(250);
-+
-+ /* Enable 1sec timer interrupt */
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ reg = __t4_framer_in(wc, x, FMR1_T);
-+ __t4_framer_out(wc, x, FMR1_T, (reg | FMR1_ECM));
-+
-+ /* Enable Errored Second interrupt */
-+ __t4_framer_out(wc, x, ESM, 0);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ t4_reset_counters(&ts->span);
-+
-+ }
-+
-+ set_span_devicetype(wc);
-+ setup_chunks(wc, 0);
-+ wc->lastindex = 0;
-+}
-+
-+static int syncsrc = 0;
-+static int syncnum = 0 /* -1 */;
-+static int syncspan = 0;
-+static DEFINE_SPINLOCK(synclock);
-+
-+static void __t4_set_rclk_src(struct t4 *wc, int span)
-+{
-+ if (is_octal(wc)) {
-+ int cmr5 = 0x00 | (span << 5);
-+ int cmr1 = 0x38; /* Clock Mode: RCLK sourced by DCO-R1
-+ by default, Disable Clock-Switching */
-+
-+ __t4_framer_out(wc, 0, 0x44, cmr1);
-+ __t4_framer_out(wc, 0, FRMR_CMR5, cmr5);
-+ } else {
-+ int cmr1 = 0x38; /* Clock Mode: RCLK sourced by DCO-R1
-+ by default, Disable Clock-Switching */
-+ cmr1 |= (span << 6);
-+ __t4_framer_out(wc, 0, 0x44, cmr1);
-+ }
-+
-+ dev_info(&wc->dev->dev, "RCLK source set to span %d\n", span+1);
-+}
-+
-+static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave)
-+{
-+ if (slave) {
-+ wc->dmactrl |= (1 << 25);
-+ dev_info(&wc->dev->dev, "SCLK is slaved to timing cable\n");
-+ } else {
-+ wc->dmactrl &= ~(1 << 25);
-+ }
-+
-+ if (master) {
-+ wc->dmactrl |= (1 << 24);
-+ dev_info(&wc->dev->dev, "SCLK is master to timing cable\n");
-+ } else {
-+ wc->dmactrl &= ~(1 << 24);
-+ }
-+
-+ if (mode == WC_RECOVER)
-+ wc->dmactrl |= (1 << 29); /* Recover timing from RCLK */
-+
-+ if (mode == WC_SELF)
-+ wc->dmactrl &= ~(1 << 29);/* Provide timing from MCLK */
-+
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+}
-+
-+static ssize_t t4_timing_master_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct t4 *wc = dev_get_drvdata(dev);
-+ if (wc->dmactrl & (1 << 29))
-+ return sprintf(buf, "%d\n", wc->syncsrc);
-+ else
-+ return sprintf(buf, "%d\n", -1);
-+}
-+
-+static DEVICE_ATTR(timing_master, 0400, t4_timing_master_show, NULL);
-+
-+static void create_sysfs_files(struct t4 *wc)
-+{
-+ int ret;
-+ ret = device_create_file(&wc->dev->dev,
-+ &dev_attr_timing_master);
-+ if (ret) {
-+ dev_info(&wc->dev->dev,
-+ "Failed to create device attributes.\n");
-+ }
-+}
-+
-+static void remove_sysfs_files(struct t4 *wc)
-+{
-+ device_remove_file(&wc->dev->dev,
-+ &dev_attr_timing_master);
-+}
-+
-+static inline void __t4_update_timing(struct t4 *wc)
-+{
-+ int i;
-+ /* update sync src info */
-+ if (wc->syncsrc != syncsrc) {
-+ dev_info(&wc->dev->dev, "Swapping card %d from %d to %d\n",
-+ wc->num, wc->syncsrc, syncsrc);
-+ wc->syncsrc = syncsrc;
-+ /* Update sync sources */
-+ for (i = 0; i < wc->numspans; i++) {
-+ wc->tspans[i]->span.syncsrc = wc->syncsrc;
-+ }
-+ if (syncnum == wc->num) {
-+ __t4_set_rclk_src(wc, syncspan-1);
-+ __t4_set_sclk_src(wc, WC_RECOVER, 1, 0);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Card %d, using sync "
-+ "span %d, master\n", wc->num, syncspan);
-+ } else {
-+ __t4_set_sclk_src(wc, WC_RECOVER, 0, 1);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "Card %d, using "
-+ "Timing Bus, NOT master\n", wc->num);
-+ }
-+ }
-+}
-+
-+static int __t4_findsync(struct t4 *wc)
-+{
-+ int i;
-+ int x;
-+ unsigned long flags;
-+ int p;
-+ int nonzero;
-+ int newsyncsrc = 0; /* DAHDI span number */
-+ int newsyncnum = 0; /* allo4xxp card number */
-+ int newsyncspan = 0; /* span on given allo4xxp card */
-+ spin_lock_irqsave(&synclock, flags);
-+ if (!wc->num) {
-+ /* If we're the first card, go through all the motions, up to 8 levels
-+ of sync source */
-+ p = 1;
-+ while (p < 8) {
-+ nonzero = 0;
-+ for (x=0;cards[x];x++) {
-+ for (i = 0; i < cards[x]->numspans; i++) {
-+ if (cards[x]->tspans[i]->syncpos) {
-+ nonzero = 1;
-+ if ((cards[x]->tspans[i]->syncpos == p) &&
-+ !(cards[x]->tspans[i]->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_LOOPBACK)) &&
-+ (cards[x]->tspans[i]->span.flags & DAHDI_FLAG_RUNNING)) {
-+ /* This makes a good sync source */
-+ newsyncsrc = cards[x]->tspans[i]->span.spanno;
-+ newsyncnum = x;
-+ newsyncspan = i + 1;
-+ /* Jump out */
-+ goto found;
-+ }
-+ }
-+ }
-+ }
-+ if (nonzero)
-+ p++;
-+ else
-+ break;
-+ }
-+found:
-+ if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) {
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "New syncnum: %d "
-+ "(was %d), syncsrc: %d (was %d), "
-+ "syncspan: %d (was %d)\n", newsyncnum,
-+ syncnum, newsyncsrc, syncsrc,
-+ newsyncspan, syncspan);
-+ syncnum = newsyncnum;
-+ syncsrc = newsyncsrc;
-+ syncspan = newsyncspan;
-+ for (x=0;cards[x];x++) {
-+ __t4_update_timing(cards[x]);
-+ }
-+ }
-+ }
-+ __t4_update_timing(wc);
-+ spin_unlock_irqrestore(&synclock, flags);
-+ return 0;
-+}
-+
-+static void __t4_set_timing_source_auto(struct t4 *wc)
-+{
-+ int x, i;
-+ int firstprio, secondprio;
-+ firstprio = secondprio = 4;
-+
-+ if (debug)
-+ dev_info(&wc->dev->dev, "timing source auto\n");
-+ clear_bit(T4_CHECK_TIMING, &wc->checkflag);
-+ if (timingcable) {
-+ __t4_findsync(wc);
-+ } else {
-+ if (debug)
-+ dev_info(&wc->dev->dev, "Evaluating spans for timing "
-+ "source\n");
-+ for (x=0;x<wc->numspans;x++) {
-+ if ((wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) &&
-+ !(wc->tspans[x]->span.alarms & (DAHDI_ALARM_RED |
-+ DAHDI_ALARM_BLUE))) {
-+ if (debug)
-+ dev_info(&wc->dev->dev, "span %d is "
-+ "green : syncpos %d\n", x+1,
-+ wc->tspans[x]->syncpos);
-+ if (wc->tspans[x]->syncpos) {
-+ /* Valid rsync source in recovered
-+ timing mode */
-+ if (firstprio == 4)
-+ firstprio = x;
-+ else if (wc->tspans[x]->syncpos <
-+ wc->tspans[firstprio]->syncpos)
-+ firstprio = x;
-+ } else {
-+ /* Valid rsync source in system timing
-+ mode */
-+ if (secondprio == 4)
-+ secondprio = x;
-+ }
-+ }
-+ }
-+ if (firstprio != 4) {
-+ wc->syncsrc = firstprio;
-+ __t4_set_rclk_src(wc, firstprio);
-+ __t4_set_sclk_src(wc, WC_RECOVER, 0, 0);
-+ dev_info(&wc->dev->dev, "Recovered timing mode, "\
-+ "RCLK set to span %d\n",
-+ firstprio+1);
-+ } else if (secondprio != 4) {
-+ wc->syncsrc = -1;
-+ __t4_set_rclk_src(wc, secondprio);
-+ __t4_set_sclk_src(wc, WC_SELF, 0, 0);
-+ dev_info(&wc->dev->dev, "System timing mode, "\
-+ "RCLK set to span %d\n",
-+ secondprio+1);
-+ } else {
-+ wc->syncsrc = -1;
-+ dev_info(&wc->dev->dev, "All spans in alarm : No valid"\
-+ "span to source RCLK from\n");
-+ /* Default rclk to lock with span 1 */
-+ __t4_set_rclk_src(wc, 0);
-+ __t4_set_sclk_src(wc, WC_SELF, 0, 0);
-+ }
-+
-+ /* Propagate sync selection to dahdi_span struct
-+ * this is read by dahdi_tool to display the span's
-+ * master/slave sync information */
-+ for (i = 0; i < wc->numspans; i++) {
-+ wc->tspans[i]->span.syncsrc = wc->syncsrc + 1;
-+ }
-+ }
-+}
-+
-+static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlevel)
-+{
-+ unsigned int fmr4, fmr2, fmr1, fmr0, lim2;
-+ char *framing, *line;
-+ int mytxlevel;
-+ if ((txlevel > 7) || (txlevel < 4))
-+ mytxlevel = 0;
-+ else
-+ mytxlevel = txlevel - 4;
-+
-+ if (is_octal(wc))
-+ fmr1 = 0x9c | 0x02; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */
-+ else
-+ fmr1 = 0x9c; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */
-+
-+ fmr2 = 0x20; /* FMR2: no payload loopback, don't auto yellow */
-+ fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */
-+ lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */
-+ lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */
-+ __t4_framer_out(wc, unit, 0x1d, fmr1);
-+ __t4_framer_out(wc, unit, 0x1e, fmr2);
-+
-+ /* Configure line interface */
-+ if (lineconfig & DAHDI_CONFIG_AMI) {
-+ line = "AMI";
-+ /* workaround for errata #2 in ES v3 09-10-16 */
-+ fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
-+ } else {
-+ line = "B8ZS";
-+ fmr0 = 0xf0;
-+ }
-+ if (lineconfig & DAHDI_CONFIG_D4) {
-+ framing = "D4";
-+ } else {
-+ framing = "ESF";
-+ fmr4 |= 0x2;
-+ fmr2 |= 0xc0;
-+ }
-+ __t4_framer_out(wc, unit, 0x1c, fmr0);
-+ __t4_framer_out(wc, unit, 0x20, fmr4);
-+ __t4_framer_out(wc, unit, FMR5, FMR5_EIBR); /* FMR5: Enable RBS mode */
-+
-+ __t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */
-+ __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */
-+
-+ __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */
-+ __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */
-+
-+ if (wc->falc31) {
-+ if (debug)
-+ dev_info(&wc->dev->dev, "card %d span %d: setting Rtx "
-+ "to 0ohm for T1\n", wc->num, unit);
-+ __t4_framer_out(wc, unit, 0x86, 0x00); /* PC6: set Rtx to 0ohm for T1 */
-+
-+ // Hitting the bugfix register to fix errata #3
-+ __t4_framer_out(wc, unit, 0xbd, 0x05);
-+ }
-+
-+ __t4_framer_out(wc, unit, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */
-+ __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */
-+ __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */
-+
-+ /* Generate pulse mask for T1 */
-+ switch(mytxlevel) {
-+ case 3:
-+ __t4_framer_out(wc, unit, 0x26, 0x07); /* XPM0 */
-+ __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */
-+ __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
-+ break;
-+ case 2:
-+ __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */
-+ __t4_framer_out(wc, unit, 0x27, 0x11); /* XPM1 */
-+ __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */
-+ break;
-+ case 1:
-+ __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */
-+ __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */
-+ __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
-+ break;
-+ case 0:
-+ default:
-+ __t4_framer_out(wc, unit, 0x26, 0xd7); /* XPM0 */
-+ __t4_framer_out(wc, unit, 0x27, 0x22); /* XPM1 */
-+ __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */
-+ break;
-+ }
-+
-+ /* Don't mask framer interrupts if hardware HDLC is in use */
-+ __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CAS changes, etc */
-+ __t4_framer_out(wc, unit, FRMR_IMR1, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about nothing */
-+ __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: All the alarm stuff! */
-+ __t4_framer_out(wc, unit, 0x17, 0x34); /* IMR3: AIS and friends */
-+ __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: Slips on transmit */
-+
-+ dev_info(&wc->dev->dev, "Span %d configured for %s/%s\n", unit + 1,
-+ framing, line);
-+}
-+
-+static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
-+{
-+ unsigned int fmr2, fmr1, fmr0;
-+ unsigned int cas = 0;
-+ unsigned int imr3extra=0;
-+ char *crc4 = "";
-+ char *framing, *line;
-+ if (is_octal(wc)) {
-+ /* 16 MHz */
-+ fmr1 = 0x44 | 0x02; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */
-+ } else {
-+ /* 8 MHz */
-+ fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */
-+ }
-+ fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */
-+ if (lineconfig & DAHDI_CONFIG_CRC4) {
-+ fmr1 |= 0x08; /* CRC4 transmit */
-+ fmr2 |= 0xc0; /* CRC4 receive */
-+ crc4 = "/CRC4";
-+ }
-+ __t4_framer_out(wc, unit, 0x1d, fmr1);
-+ __t4_framer_out(wc, unit, 0x1e, fmr2);
-+
-+ /* Configure line interface */
-+ if (lineconfig & DAHDI_CONFIG_AMI) {
-+ line = "AMI";
-+ /* workaround for errata #2 in ES v3 09-10-16 */
-+ fmr0 = (wc->falc31) ? 0xb0 : 0xa0;
-+ } else {
-+ line = "HDB3";
-+ fmr0 = 0xf0;
-+ }
-+ if (lineconfig & DAHDI_CONFIG_CCS) {
-+ framing = "CCS";
-+ imr3extra = 0x28;
-+ } else {
-+ framing = "CAS";
-+ cas = 0x40;
-+ }
-+ __t4_framer_out(wc, unit, 0x1c, fmr0);
-+
-+ __t4_framer_out(wc, unit, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */
-+ __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */
-+
-+ __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */
-+ __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */
-+
-+ if (wc->falc31) {
-+ if (debug)
-+ dev_info(&wc->dev->dev,
-+ "setting Rtx to 7.5ohm for E1\n");
-+ __t4_framer_out(wc, unit, 0x86, 0x40); /* PC6: turn on 7.5ohm Rtx for E1 */
-+ }
-+
-+ /* Condition receive line interface for E1 after reset */
-+ __t4_framer_out(wc, unit, 0xbb, 0x17);
-+ __t4_framer_out(wc, unit, 0xbc, 0x55);
-+ __t4_framer_out(wc, unit, 0xbb, 0x97);
-+ __t4_framer_out(wc, unit, 0xbb, 0x11);
-+ __t4_framer_out(wc, unit, 0xbc, 0xaa);
-+ __t4_framer_out(wc, unit, 0xbb, 0x91);
-+ __t4_framer_out(wc, unit, 0xbb, 0x12);
-+ __t4_framer_out(wc, unit, 0xbc, 0x55);
-+ __t4_framer_out(wc, unit, 0xbb, 0x92);
-+ __t4_framer_out(wc, unit, 0xbb, 0x0c);
-+ __t4_framer_out(wc, unit, 0xbb, 0x00);
-+ __t4_framer_out(wc, unit, 0xbb, 0x8c);
-+
-+ __t4_framer_out(wc, unit, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */
-+ __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */
-+ __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */
-+
-+ __t4_framer_out(wc, unit, 0x20, 0x9f); /* XSW: Spare bits all to 1 */
-+ __t4_framer_out(wc, unit, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */
-+
-+
-+ /* Generate pulse mask for E1 */
-+ __t4_framer_out(wc, unit, 0x26, 0x54); /* XPM0 */
-+ __t4_framer_out(wc, unit, 0x27, 0x02); /* XPM1 */
-+ __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
-+
-+ /* Don't mask framer interrupts if hardware HDLC is in use */
-+ __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CRC errors, CAS changes, etc */
-+ __t4_framer_out(wc, unit, FRMR_IMR1, 0x3f & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about loopup / loopdown */
-+ __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */
-+ __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, "ALLO%dXXP: Span %d configured for %s/%s%s\n",
-+ wc->numspans, unit + 1, framing, line, crc4);
-+}
-+
-+/**
-+ * t4_check_for_interrupts - Return 0 if the card is generating interrupts.
-+ * @wc: The card to check.
-+ *
-+ * If the card is not generating interrupts, this function will also place all
-+ * the spans on the card into red alarm.
-+ *
-+ */
-+static int t4_check_for_interrupts(struct t4 *wc)
-+{
-+ unsigned int starting_intcount = wc->intcount;
-+ unsigned long stop_time = jiffies + HZ*2;
-+ unsigned long flags;
-+ int x;
-+
-+ msleep(20);
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ while (starting_intcount == wc->intcount) {
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ if (time_after(jiffies, stop_time)) {
-+ for (x = 0; x < wc->numspans; x++)
-+ wc->tspans[x]->span.alarms = DAHDI_ALARM_RED;
-+ dev_err(&wc->dev->dev, "Interrupts not detected.\n");
-+ return -EIO;
-+ }
-+ msleep(100);
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ return 0;
-+}
-+
-+static int _t4_startup(struct file *file, struct dahdi_span *span)
-+{
-+#ifdef SUPPORT_GEN1
-+ int i;
-+#endif
-+ int tspan;
-+ unsigned long flags;
-+ int alreadyrunning;
-+ struct t4_span *ts = container_of(span, struct t4_span, span);
-+ struct t4 *wc = ts->owner;
-+
-+ set_bit(T4_IGNORE_LATENCY, &wc->checkflag);
-+ if (debug)
-+ dev_info(&wc->dev->dev, "About to enter startup!\n");
-+
-+ tspan = span->offset + 1;
-+ if (tspan < 0) {
-+ dev_info(&wc->dev->dev, "ALLO%dXXP: Span '%d' isn't us?\n",
-+ wc->numspans, span->spanno);
-+ return -1;
-+ }
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ alreadyrunning = span->flags & DAHDI_FLAG_RUNNING;
-+
-+#ifdef SUPPORT_GEN1
-+ /* initialize the start value for the entire chunk of last ec buffer */
-+ for(i = 0; i < span->channels; i++)
-+ {
-+ memset(ts->ec_chunk1[i],
-+ DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE);
-+ memset(ts->ec_chunk2[i],
-+ DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE);
-+ }
-+#endif
-+ /* Force re-evaluation of timing source */
-+ wc->syncsrc = -1;
-+ set_bit(T4_CHECK_TIMING, &wc->checkflag);
-+
-+ if (E1 == ts->linemode)
-+ __t4_configure_e1(wc, span->offset, span->lineconfig);
-+ else
-+ __t4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel);
-+
-+ /* Note clear channel status */
-+ wc->tspans[span->offset]->notclear = 0;
-+ __set_clear(wc, span->offset);
-+
-+ if (!alreadyrunning) {
-+ span->flags |= DAHDI_FLAG_RUNNING;
-+ wc->spansstarted++;
-+
-+ if (wc->devtype->flags & FLAG_5THGEN)
-+ __t4_pci_out(wc, 5, (ms_per_irq << 16) | wc->numbufs);
-+ else
-+ __t4_pci_out(wc, 5, (1 << 16) | 1);
-+ /* enable interrupts */
-+ /* Start DMA, enabling DMA interrupts on read only */
-+ wc->dmactrl |= (ts->spanflags & FLAG_2NDGEN) ? 0xc0000000 : 0xc0000003;
-+#ifdef VPM_SUPPORT
-+ wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0;
-+#endif
-+ /* Seed interrupt register */
-+ __t4_pci_out(wc, WC_INTR, 0x0c);
-+ if (noburst || !(ts->spanflags & FLAG_BURST))
-+ wc->dmactrl |= (1 << 26);
-+ else
-+ wc->dmactrl &= ~(1 << 26);
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+
-+ /* Startup HDLC controller too */
-+ }
-+
-+ if (ts->sigchan) {
-+ struct dahdi_chan *sigchan = ts->sigchan;
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ if (hdlc_start(wc, span->offset, sigchan, ts->sigmode)) {
-+ dev_notice(&wc->dev->dev, "Error initializing "
-+ "signalling controller\n");
-+ return -1;
-+ }
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ }
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ local_irq_save(flags);
-+ t4_check_alarms(wc, span->offset);
-+ t4_check_sigbits(wc, span->offset);
-+ local_irq_restore(flags);
-+ if (wc->numspans >= 1) { /*cem:1port change, v002*/
-+ if (wc->tspans[0]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Primary Sync Source\n",
-+ span->spanno);
-+ }
-+ if (wc->tspans[1]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Secondary Sync Source\n",
-+ span->spanno);
-+ if (wc->numspans >= 4) {
-+ if (wc->tspans[2]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Tertiary Sync Source"
-+ "\n", span->spanno);
-+ if (wc->tspans[3]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Quaternary Sync "
-+ "Source\n", span->spanno);
-+ }
-+ if (wc->numspans == 8) {
-+ if (wc->tspans[4]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Quinary Sync "
-+ "Source\n", span->spanno);
-+ if (wc->tspans[5]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Senary Sync "
-+ "Source\n", span->spanno);
-+ if (wc->tspans[6]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Septenary Sync "
-+ "Source\n", span->spanno);
-+ if (wc->tspans[7]->sync == span->spanno)
-+ dev_info(&wc->dev->dev, "SPAN %d: Octonary Sync "
-+ "Source\n", span->spanno);
-+ }
-+
-+ if (!alreadyrunning) {
-+ if (t4_check_for_interrupts(wc))
-+ return -EIO;
-+ }
-+
-+ if (debug)
-+ dev_info(&wc->dev->dev, "Completed startup!\n");
-+ clear_bit(T4_IGNORE_LATENCY, &wc->checkflag);
-+ return 0;
-+}
-+
-+static int t4_startup(struct file *file, struct dahdi_span *span)
-+{
-+ int ret;
-+ struct dahdi_device *const ddev = span->parent;
-+ struct dahdi_span *s;
-+
-+ ret = _t4_startup(file, span);
-+ list_for_each_entry(s, &ddev->spans, device_node) {
-+ if (!test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags)) {
-+ _t4_startup(file, s);
-+ }
-+ }
-+ return ret;
-+}
-+
-+#ifdef SUPPORT_GEN1
-+static inline void e1_check(struct t4 *wc, int span, int val)
-+{
-+ struct t4_span *ts = wc->tspans[span];
-+ if ((ts->span.channels > 24) &&
-+ (ts->span.flags & DAHDI_FLAG_RUNNING) &&
-+ !(ts->span.alarms) &&
-+ (!wc->e1recover)) {
-+ if (val != 0x1b) {
-+ ts->e1check++;
-+ } else
-+ ts->e1check = 0;
-+ if (ts->e1check > 100) {
-+ /* Wait 1000 ms */
-+ wc->e1recover = 1000 * 8;
-+ wc->tspans[0]->e1check = wc->tspans[1]->e1check = 0;
-+ if (wc->numspans == 4)
-+ wc->tspans[2]->e1check = wc->tspans[3]->e1check = 0;
-+ if (debug & DEBUG_MAIN)
-+ dev_notice(&wc->dev->dev, "Detected loss of "
-+ "E1 alignment on span %d!\n", span);
-+ t4_reset_dma(wc);
-+ }
-+ }
-+}
-+
-+static void t4_receiveprep(struct t4 *wc, int irq)
-+{
-+ unsigned int *readchunk;
-+ int dbl = 0;
-+ int x,y,z;
-+ unsigned int tmp;
-+ int offset=0;
-+ if (!has_e1_span(wc))
-+ offset = 4;
-+ if (irq & 1) {
-+ /* First part */
-+ readchunk = wc->readchunk;
-+ if (!wc->last0)
-+ dbl = 1;
-+ wc->last0 = 0;
-+ } else {
-+ readchunk = wc->readchunk + DAHDI_CHUNKSIZE * 32;
-+ if (wc->last0)
-+ dbl = 1;
-+ wc->last0 = 1;
-+ }
-+ if (unlikely(dbl && (debug & DEBUG_MAIN)))
-+ dev_notice(&wc->dev->dev, "Double/missed interrupt detected\n");
-+
-+ for (x=0;x<DAHDI_CHUNKSIZE;x++) {
-+ for (z=0;z<24;z++) {
-+ /* All T1/E1 channels */
-+ tmp = readchunk[z+1+offset];
-+ if (wc->numspans == 4) {
-+ wc->tspans[3]->span.chans[z]->readchunk[x] = tmp & 0xff;
-+ wc->tspans[2]->span.chans[z]->readchunk[x] = (tmp & 0xff00) >> 8;
-+ }
-+ if (wc->numspans == 2) { /*cem:1port change, v002*/
-+ wc->tspans[1]->span.chans[z]->readchunk[x] = (tmp & 0xff0000) >> 16;
-+ }
-+ wc->tspans[0]->span.chans[z]->readchunk[x] = tmp >> 24;
-+ }
-+ if (has_e1_span(wc)) {
-+ if (wc->e1recover > 0)
-+ wc->e1recover--;
-+ tmp = readchunk[0];
-+ if (wc->numspans == 4) {
-+ e1_check(wc, 3, (tmp & 0x7f));
-+ e1_check(wc, 2, (tmp & 0x7f00) >> 8);
-+ }
-+ if (wc->numspans >=2) //cem:1port change
-+ e1_check(wc, 1, (tmp & 0x7f0000) >> 16);
-+ e1_check(wc, 0, (tmp & 0x7f000000) >> 24);
-+ for (z=24;z<31;z++) {
-+ /* Only E1 channels now */
-+ tmp = readchunk[z+1];
-+ if (wc->numspans == 4) {
-+ if (wc->tspans[3]->span.channels > 24)
-+ wc->tspans[3]->span.chans[z]->readchunk[x] = tmp & 0xff;
-+ if (wc->tspans[2]->span.channels > 24)
-+ wc->tspans[2]->span.chans[z]->readchunk[x] = (tmp & 0xff00) >> 8;
-+ }
-+ if (wc->numspans == 2) {/*cem:1port change, v002*/
-+ if (wc->tspans[1]->span.channels > 24)
-+ wc->tspans[1]->span.chans[z]->readchunk[x] = (tmp & 0xff0000) >> 16;
-+ }
-+ if (wc->tspans[0]->span.channels > 24)
-+ wc->tspans[0]->span.chans[z]->readchunk[x] = tmp >> 24;
-+ }
-+ }
-+ /* Advance pointer by 4 TDM frame lengths */
-+ readchunk += 32;
-+ }
-+ for (x=0;x<wc->numspans;x++) {
-+ if (wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) {
-+ for (y=0;y<wc->tspans[x]->span.channels;y++) {
-+ /* Echo cancel double buffered data */
-+ dahdi_ec_chunk(wc->tspans[x]->span.chans[y],
-+ wc->tspans[x]->span.chans[y]->readchunk,
-+ wc->tspans[x]->ec_chunk2[y]);
-+ memcpy(wc->tspans[x]->ec_chunk2[y],wc->tspans[x]->ec_chunk1[y],
-+ DAHDI_CHUNKSIZE);
-+ memcpy(wc->tspans[x]->ec_chunk1[y],
-+ wc->tspans[x]->span.chans[y]->writechunk,
-+ DAHDI_CHUNKSIZE);
-+ }
-+ _dahdi_receive(&wc->tspans[x]->span);
-+ }
-+ }
-+}
-+#endif
-+
-+#if (DAHDI_CHUNKSIZE != 8)
-+#error Sorry, nextgen does not support chunksize != 8
-+#endif
-+
-+static void __receive_span(struct t4_span *ts)
-+{
-+#ifdef VPM_SUPPORT
-+ int y;
-+ unsigned long merged;
-+ merged = ts->dtmfactive & ts->dtmfmutemask;
-+ if (merged) {
-+ for (y=0;y<ts->span.channels;y++) {
-+ /* Mute any DTMFs which are supposed to be muted */
-+ if (test_bit(y, &merged)) {
-+ memset(ts->span.chans[y]->readchunk, DAHDI_XLAW(0, ts->span.chans[y]), DAHDI_CHUNKSIZE);
-+ }
-+ }
-+ }
-+#endif
-+ _dahdi_ec_span(&ts->span);
-+ _dahdi_receive(&ts->span);
-+}
-+
-+static inline void __transmit_span(struct t4_span *ts)
-+{
-+ _dahdi_transmit(&ts->span);
-+}
-+
-+#ifdef ENABLE_WORKQUEUES
-+static void workq_handlespan(void *data)
-+{
-+ struct t4_span *ts = data;
-+ struct t4 *wc = ts->owner;
-+
-+ __receive_span(ts);
-+ __transmit_span(ts);
-+ atomic_dec(&wc->worklist);
-+ if (!atomic_read(&wc->worklist))
-+ t4_pci_out(wc, WC_INTR, 0);
-+}
-+#else
-+static void t4_prep_gen2(struct t4 *wc)
-+{
-+ int x;
-+ for (x=0;x<wc->numspans;x++) {
-+ if (wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) {
-+ __receive_span(wc->tspans[x]);
-+ __transmit_span(wc->tspans[x]);
-+ }
-+ }
-+}
-+
-+#endif
-+#ifdef SUPPORT_GEN1
-+static void t4_transmitprep(struct t4 *wc, int irq)
-+{
-+ u32 *writechunk;
-+ int x, y, z;
-+ unsigned int tmp;
-+ int offset = 0;
-+ if (!has_e1_span(wc))
-+ offset = 4;
-+ if (irq & 1) {
-+ /* First part */
-+ writechunk = wc->writechunk + 1;
-+ } else {
-+ writechunk = wc->writechunk + DAHDI_CHUNKSIZE * 32 + 1;
-+ }
-+ for (y=0;y<wc->numspans;y++) {
-+ if (wc->tspans[y]->span.flags & DAHDI_FLAG_RUNNING)
-+ _dahdi_transmit(&wc->tspans[y]->span);
-+ }
-+
-+ for (x=0;x<DAHDI_CHUNKSIZE;x++) {
-+ /* Once per chunk */
-+ for (z=0;z<24;z++) {
-+ /* All T1/E1 channels */
-+ tmp = (wc->tspans[3]->span.chans[z]->writechunk[x]) |
-+ (wc->tspans[2]->span.chans[z]->writechunk[x] << 8) |
-+ (wc->tspans[1]->span.chans[z]->writechunk[x] << 16) |
-+ (wc->tspans[0]->span.chans[z]->writechunk[x] << 24);
-+ writechunk[z+offset] = tmp;
-+ }
-+ if (has_e1_span(wc)) {
-+ for (z=24;z<31;z++) {
-+ /* Only E1 channels now */
-+ tmp = 0;
-+ if (wc->numspans == 4) {
-+ if (wc->tspans[3]->span.channels > 24)
-+ tmp |= wc->tspans[3]->span.chans[z]->writechunk[x];
-+ if (wc->tspans[2]->span.channels > 24)
-+ tmp |= (wc->tspans[2]->span.chans[z]->writechunk[x] << 8);
-+ }
-+ if (wc->numspans == 2) { /*cem:1port change, v002*/
-+ if (wc->tspans[1]->span.channels > 24)
-+ tmp |= (wc->tspans[1]->span.chans[z]->writechunk[x] << 16);
-+ }
-+ if (wc->tspans[0]->span.channels > 24)
-+ tmp |= (wc->tspans[0]->span.chans[z]->writechunk[x] << 24);
-+ writechunk[z] = tmp;
-+ }
-+ }
-+ /* Advance pointer by 4 TDM frame lengths */
-+ writechunk += 32;
-+ }
-+
-+}
-+#endif
-+
-+static void t4_dahdi_rbsbits(struct dahdi_chan *const chan, int rxs)
-+{
-+ if ((debug & DEBUG_RBS) && printk_ratelimit()) {
-+ const struct t4_span *tspan = container_of(chan->span,
-+ struct t4_span,
-+ span);
-+ const struct t4 *const wc = tspan->owner;
-+ dev_notice(&wc->dev->dev, "Detected sigbits change on " \
-+ "channel %s to %04x\n", chan->name, rxs);
-+ }
-+ dahdi_rbsbits(chan, rxs);
-+}
-+
-+static void t4_check_sigbits(struct t4 *wc, int span)
-+{
-+ int a,i,rxs;
-+ struct t4_span *ts = wc->tspans[span];
-+
-+ if (debug & DEBUG_RBS)
-+ dev_notice(&wc->dev->dev, "Checking sigbits on span %d\n",
-+ span + 1);
-+
-+ if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
-+ return;
-+ if (E1 == ts->linemode) {
-+ for (i = 0; i < 15; i++) {
-+ a = t4_framer_in(wc, span, 0x71 + i);
-+ /* Get high channel in low bits */
-+ rxs = (a & 0xf);
-+ if (!(ts->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) {
-+ if (ts->span.chans[i+16]->rxsig != rxs)
-+ t4_dahdi_rbsbits(ts->span.chans[i+16], rxs);
-+ }
-+ rxs = (a >> 4) & 0xf;
-+ if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
-+ if (ts->span.chans[i]->rxsig != rxs)
-+ t4_dahdi_rbsbits(ts->span.chans[i], rxs);
-+ }
-+ }
-+ } else if (ts->span.lineconfig & DAHDI_CONFIG_D4) {
-+ for (i = 0; i < 24; i+=4) {
-+ a = t4_framer_in(wc, span, 0x70 + (i>>2));
-+ /* Get high channel in low bits */
-+ rxs = (a & 0x3) << 2;
-+ if (!(ts->span.chans[i+3]->sig & DAHDI_SIG_CLEAR)) {
-+ if (ts->span.chans[i+3]->rxsig != rxs)
-+ t4_dahdi_rbsbits(ts->span.chans[i+3], rxs);
-+ }
-+ rxs = (a & 0xc);
-+ if (!(ts->span.chans[i+2]->sig & DAHDI_SIG_CLEAR)) {
-+ if (ts->span.chans[i+2]->rxsig != rxs)
-+ t4_dahdi_rbsbits(ts->span.chans[i+2], rxs);
-+ }
-+ rxs = (a >> 2) & 0xc;
-+ if (!(ts->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) {
-+ if (ts->span.chans[i+1]->rxsig != rxs)
-+ t4_dahdi_rbsbits(ts->span.chans[i+1], rxs);
-+ }
-+ rxs = (a >> 4) & 0xc;
-+ if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
-+ if (ts->span.chans[i]->rxsig != rxs)
-+ t4_dahdi_rbsbits(ts->span.chans[i], rxs);
-+ }
-+ }
-+ } else {
-+ for (i = 0; i < 24; i+=2) {
-+ a = t4_framer_in(wc, span, 0x70 + (i>>1));
-+ /* Get high channel in low bits */
-+ rxs = (a & 0xf);
-+ if (!(ts->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) {
-+ /* XXX Not really reset on every trans! XXX */
-+ if (ts->span.chans[i+1]->rxsig != rxs) {
-+ t4_dahdi_rbsbits(ts->span.chans[i+1], rxs);
-+ }
-+ }
-+ rxs = (a >> 4) & 0xf;
-+ if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
-+ /* XXX Not really reset on every trans! XXX */
-+ if (ts->span.chans[i]->rxsig != rxs) {
-+ t4_dahdi_rbsbits(ts->span.chans[i], rxs);
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+/* Must be called from within hardirq context. */
-+static void t4_check_alarms(struct t4 *wc, int span)
-+{
-+ unsigned char c, d, e;
-+ int alarms;
-+ int x,j;
-+ struct t4_span *ts = wc->tspans[span];
-+
-+ if (time_before(jiffies, ts->alarmcheck_time))
-+ return;
-+
-+ if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
-+ return;
-+
-+ spin_lock(&wc->reglock);
-+
-+ c = __t4_framer_in(wc, span, 0x4c);
-+ d = __t4_framer_in(wc, span, 0x4d);
-+
-+ /* Assume no alarms */
-+ alarms = 0;
-+
-+ /* And consider only carrier alarms */
-+ ts->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN);
-+
-+ if (E1 == ts->linemode) {
-+ if (c & 0x04) {
-+ /* No multiframe found, force RAI high after 400ms only if
-+ we haven't found a multiframe since last loss
-+ of frame */
-+ if (!(ts->spanflags & FLAG_NMF)) {
-+ __t4_framer_out(wc, span, 0x20, 0x9f | 0x20); /* LIM0: Force RAI High */
-+ ts->spanflags |= FLAG_NMF;
-+ dev_notice(&wc->dev->dev,
-+ "Lost crc4-multiframe alignment\n");
-+ }
-+ __t4_framer_out(wc, span, 0x1e, 0xc3); /* Reset to CRC4 mode */
-+ __t4_framer_out(wc, span, 0x1c, 0xf2); /* Force Resync */
-+ __t4_framer_out(wc, span, 0x1c, 0xf0); /* Force Resync */
-+ } else if (!(c & 0x02)) {
-+ if ((ts->spanflags & FLAG_NMF)) {
-+ __t4_framer_out(wc, span, 0x20, 0x9f); /* LIM0: Clear forced RAI */
-+ ts->spanflags &= ~FLAG_NMF;
-+ dev_notice(&wc->dev->dev,
-+ "Obtained crc4-multiframe alignment\n");
-+ }
-+ }
-+ } else {
-+ /* Detect loopup code if we're not sending one */
-+ if ((!ts->span.mainttimer) && (d & 0x08)) {
-+ /* Loop-up code detected */
-+ if ((ts->loopupcnt++ > 80) && (ts->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
-+ dev_notice(&wc->dev->dev,
-+ "span %d: Loopup detected,"\
-+ " enabling remote loop\n",
-+ span+1);
-+ __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */
-+ __t4_framer_out(wc, span, 0x37, 0xf6 ); /* LIM1: Enable remote loop */
-+ ts->span.maintstat = DAHDI_MAINT_REMOTELOOP;
-+ }
-+ } else
-+ ts->loopupcnt = 0;
-+ /* Same for loopdown code */
-+ if ((!ts->span.mainttimer) && (d & 0x10)) {
-+ /* Loop-down code detected */
-+ if ((ts->loopdowncnt++ > 80) && (ts->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
-+ dev_notice(&wc->dev->dev,
-+ "span %d: Loopdown detected,"\
-+ " disabling remote loop\n",
-+ span+1);
-+ __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */
-+ __t4_framer_out(wc, span, 0x37, 0xf0 ); /* LIM1: Disable remote loop */
-+ ts->span.maintstat = DAHDI_MAINT_NONE;
-+ }
-+ } else
-+ ts->loopdowncnt = 0;
-+ }
-+
-+ if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
-+ for (x=0,j=0;x < ts->span.channels;x++)
-+ if ((ts->span.chans[x]->flags & DAHDI_FLAG_OPEN) ||
-+ dahdi_have_netdev(ts->span.chans[x]))
-+ j++;
-+ if (!j)
-+ alarms |= DAHDI_ALARM_NOTOPEN;
-+ }
-+
-+ /* Loss of Frame Alignment */
-+ if (c & 0x20) {
-+ if (!ts->alarm_time) {
-+ if (unlikely(debug)) {
-+ /* starting to debounce LOF/LFA */
-+ dev_info(&wc->dev->dev, "allo%dxxp: LOF/LFA "
-+ "detected on span %d but debouncing "
-+ "for %d ms\n", wc->numspans, span + 1,
-+ alarmdebounce);
-+ }
-+ ts->alarm_time = jiffies +
-+ msecs_to_jiffies(alarmdebounce);
-+ } else if (time_after(jiffies, ts->alarm_time)) {
-+ /* Disable Slip Interrupts */
-+ e = __t4_framer_in(wc, span, 0x17);
-+ __t4_framer_out(wc, span, 0x17, (e|0x03));
-+
-+ alarms |= DAHDI_ALARM_RED;
-+ }
-+ } else {
-+ ts->alarm_time = 0;
-+ }
-+
-+ /* Loss of Signal */
-+ if (c & 0x80) {
-+ if (!ts->losalarm_time) {
-+ if (unlikely(debug)) {
-+ /* starting to debounce LOS */
-+ dev_info(&wc->dev->dev, "allo%dxxp: LOS "
-+ "detected on span %d but debouncing "
-+ "for %d ms\n", wc->numspans,
-+ span + 1, losalarmdebounce);
-+ }
-+ ts->losalarm_time = jiffies +
-+ msecs_to_jiffies(losalarmdebounce);
-+ } else if (time_after(jiffies, ts->losalarm_time)) {
-+ /* Disable Slip Interrupts */
-+ e = __t4_framer_in(wc, span, 0x17);
-+ __t4_framer_out(wc, span, 0x17, (e|0x03));
-+
-+ alarms |= DAHDI_ALARM_RED;
-+ }
-+ } else {
-+ ts->losalarm_time = 0;
-+ }
-+
-+ /* Alarm Indication Signal */
-+ if (c & 0x40) {
-+ if (!ts->aisalarm_time) {
-+ if (unlikely(debug)) {
-+ /* starting to debounce AIS */
-+ dev_info(&wc->dev->dev, "allo%dxxp: AIS "
-+ "detected on span %d but debouncing "
-+ "for %d ms\n", wc->numspans,
-+ span + 1, aisalarmdebounce);
-+ }
-+ ts->aisalarm_time = jiffies +
-+ msecs_to_jiffies(aisalarmdebounce);
-+ } else if (time_after(jiffies, ts->aisalarm_time)) {
-+ alarms |= DAHDI_ALARM_BLUE;
-+ }
-+ } else {
-+ ts->aisalarm_time = 0;
-+ }
-+
-+ /* Add detailed alarm status information to a red alarm state */
-+ if (alarms & DAHDI_ALARM_RED) {
-+ if (c & FRS0_LOS)
-+ alarms |= DAHDI_ALARM_LOS;
-+ if (c & FRS0_LFA)
-+ alarms |= DAHDI_ALARM_LFA;
-+ if (c & FRS0_LMFA)
-+ alarms |= DAHDI_ALARM_LMFA;
-+ }
-+
-+ if (unlikely(debug)) {
-+ /* Check to ensure the xmit line isn't shorted */
-+ if (unlikely(d & FRS1_XLS)) {
-+ dev_info(&wc->dev->dev,
-+ "Detected a possible hardware malfunction"\
-+ " this card may need servicing\n");
-+ }
-+ }
-+
-+ if (((!ts->span.alarms) && alarms) ||
-+ (ts->span.alarms && (!alarms)))
-+ set_bit(T4_CHECK_TIMING, &wc->checkflag);
-+
-+ /* Keep track of recovering */
-+ if ((!alarms) && ts->span.alarms)
-+ ts->alarmtimer = DAHDI_ALARMSETTLE_TIME;
-+ if (ts->alarmtimer)
-+ alarms |= DAHDI_ALARM_RECOVER;
-+
-+ /* If receiving alarms, go into Yellow alarm state */
-+ if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) {
-+ /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */
-+ unsigned char fmr4;
-+ fmr4 = __t4_framer_in(wc, span, 0x20);
-+ __t4_framer_out(wc, span, 0x20, fmr4 | 0x20);
-+ dev_info(&wc->dev->dev, "Setting yellow alarm span %d\n",
-+ span+1);
-+ ts->spanflags |= FLAG_SENDINGYELLOW;
-+ } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) {
-+ unsigned char fmr4;
-+ /* We manually do yellow alarm to handle RECOVER */
-+ fmr4 = __t4_framer_in(wc, span, 0x20);
-+ __t4_framer_out(wc, span, 0x20, fmr4 & ~0x20);
-+ dev_info(&wc->dev->dev, "Clearing yellow alarm span %d\n",
-+ span+1);
-+
-+ /* Re-enable timing slip interrupts */
-+ e = __t4_framer_in(wc, span, 0x17);
-+
-+ __t4_framer_out(wc, span, 0x17, (e & ~(0x03)));
-+
-+ ts->spanflags &= ~FLAG_SENDINGYELLOW;
-+ }
-+
-+ /* Re-check the timing source when we enter/leave alarm, not withstanding
-+ yellow alarm */
-+ if (c & 0x10) { /* receiving yellow (RAI) */
-+ if (!ts->yelalarm_time) {
-+ if (unlikely(debug)) {
-+ /* starting to debounce AIS */
-+ dev_info(&wc->dev->dev, "allo%dxxp: yellow "
-+ "(RAI) detected on span %d but "
-+ "debouncing for %d ms\n",
-+ wc->numspans, span + 1,
-+ yelalarmdebounce);
-+ }
-+ ts->yelalarm_time = jiffies +
-+ msecs_to_jiffies(yelalarmdebounce);
-+ } else if (time_after(jiffies, ts->yelalarm_time)) {
-+ alarms |= DAHDI_ALARM_YELLOW;
-+ }
-+ } else {
-+ ts->yelalarm_time = 0;
-+ }
-+
-+ if (alarms)
-+ ts->alarmcheck_time = jiffies + msecs_to_jiffies(100);
-+ else
-+ ts->alarmcheck_time = jiffies + msecs_to_jiffies(50);
-+
-+ if (ts->span.mainttimer || ts->span.maintstat)
-+ alarms |= DAHDI_ALARM_LOOPBACK;
-+ ts->span.alarms = alarms;
-+
-+ spin_unlock(&wc->reglock);
-+ dahdi_alarm_notify(&ts->span);
-+}
-+
-+static void t4_do_counters(struct t4 *wc)
-+{
-+ int span;
-+ for (span = 0; span < wc->numspans; span++) {
-+ struct t4_span *ts = wc->tspans[span];
-+
-+ spin_lock(&wc->reglock);
-+ if (ts->alarmtimer && (0 == (--ts->alarmtimer)))
-+ ts->span.alarms &= ~(DAHDI_ALARM_RECOVER);
-+ spin_unlock(&wc->reglock);
-+
-+ t4_check_alarms(wc, span);
-+ }
-+}
-+
-+static inline void __handle_leds(struct t4 *wc)
-+{
-+ int x;
-+
-+ wc->blinktimer++;
-+ for (x=0;x<wc->numspans;x++) {
-+ struct t4_span *ts = wc->tspans[x];
-+ if (ts->span.flags & DAHDI_FLAG_RUNNING) {
-+ if ((ts->span.alarms & (DAHDI_ALARM_RED |
-+ DAHDI_ALARM_BLUE)) ||
-+ ts->losalarm_time) {
-+#ifdef FANCY_ALARM
-+ if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {
-+ __t4_set_led(wc, x, WC_RED);
-+ }
-+ if (wc->blinktimer == 0xf) {
-+ __t4_set_led(wc, x, WC_OFF);
-+ }
-+#else
-+ if (wc->blinktimer == 160) {
-+ __t4_set_led(wc, x, WC_RED);
-+ } else if (wc->blinktimer == 480) {
-+ __t4_set_led(wc, x, WC_OFF);
-+ }
-+#endif
-+ } else if (ts->span.alarms & DAHDI_ALARM_YELLOW) {
-+ /* Yellow Alarm */
-+ __t4_set_led(wc, x, WC_YELLOW);
-+ } else if (ts->span.mainttimer || ts->span.maintstat) {
-+#ifdef FANCY_ALARM
-+ if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {
-+ __t4_set_led(wc, x, WC_GREEN);
-+ }
-+ if (wc->blinktimer == 0xf) {
-+ __t4_set_led(wc, x, WC_OFF);
-+ }
-+#else
-+ if (wc->blinktimer == 160) {
-+ __t4_set_led(wc, x, WC_GREEN);
-+ } else if (wc->blinktimer == 480) {
-+ __t4_set_led(wc, x, WC_OFF);
-+ }
-+#endif
-+ } else {
-+ /* No Alarm */
-+ __t4_set_led(wc, x, WC_GREEN);
-+ }
-+ } else
-+ __t4_set_led(wc, x, WC_OFF);
-+
-+ }
-+#ifdef FANCY_ALARM
-+ if (wc->blinktimer == 0xf) {
-+ wc->blinktimer = -1;
-+ wc->alarmpos++;
-+ if (wc->alarmpos >= ARRAY_SIZE(altab))
-+ wc->alarmpos = 0;
-+ }
-+#else
-+ if (wc->blinktimer == 480)
-+ wc->blinktimer = 0;
-+#endif
-+}
-+
-+static inline void t4_framer_interrupt(struct t4 *wc, int span)
-+{
-+ /* Check interrupts for a given span */
-+ unsigned char gis, isr0, isr1, isr2, isr3, isr4;
-+ int readsize = -1;
-+ struct t4_span *ts = wc->tspans[span];
-+ struct dahdi_chan *sigchan;
-+ unsigned long flags;
-+
-+
-+ /* 1st gen cards isn't used interrupts */
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ gis = __t4_framer_in(wc, span, FRMR_GIS);
-+ isr0 = (gis & FRMR_GIS_ISR0) ? __t4_framer_in(wc, span, FRMR_ISR0) : 0;
-+ isr1 = (gis & FRMR_GIS_ISR1) ? __t4_framer_in(wc, span, FRMR_ISR1) : 0;
-+ isr2 = (gis & FRMR_GIS_ISR2) ? __t4_framer_in(wc, span, FRMR_ISR2) : 0;
-+ isr3 = (gis & FRMR_GIS_ISR3) ? __t4_framer_in(wc, span, FRMR_ISR3) : 0;
-+ isr4 = (gis & FRMR_GIS_ISR4) ? __t4_framer_in(wc, span, FRMR_ISR4) : 0;
-+
-+ if ((debug & DEBUG_FRAMER) && !(isr3 & ISR3_SEC)) {
-+ dev_info(&wc->dev->dev, "gis: %02x, isr0: %02x, isr1: %02x, "\
-+ "isr2: %02x, isr3: %08x, isr4: %02x, intcount=%u\n",
-+ gis, isr0, isr1, isr2, isr3, isr4, wc->intcount);
-+ }
-+
-+ /* Collect performance counters once per second */
-+ if (isr3 & ISR3_SEC) {
-+ ts->span.count.fe += __t4_framer_in(wc, span, FECL_T);
-+ ts->span.count.crc4 += __t4_framer_in(wc, span, CEC1L_T);
-+ ts->span.count.cv += __t4_framer_in(wc, span, CVCL_T);
-+ ts->span.count.ebit += __t4_framer_in(wc, span, EBCL_T);
-+ ts->span.count.be += __t4_framer_in(wc, span, BECL_T);
-+ ts->span.count.prbs = __t4_framer_in(wc, span, FRS1_T);
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ /* Collect errored second counter once per second */
-+ if (isr3 & ISR3_ES) {
-+ ts->span.count.errsec += 1;
-+ }
-+
-+ if (isr0)
-+ t4_check_sigbits(wc, span);
-+
-+ if (E1 == ts->linemode) {
-+ /* E1 checks */
-+ if ((isr3 & 0x38) || isr2 || isr1)
-+ t4_check_alarms(wc, span);
-+ } else {
-+ /* T1 checks */
-+ if (isr2 || (isr3 & 0x08))
-+ t4_check_alarms(wc, span);
-+ }
-+ if (!ts->span.alarms) {
-+ if ((isr3 & 0x3) || (isr4 & 0xc0))
-+ ts->span.count.timingslips++;
-+
-+ if (debug & DEBUG_MAIN) {
-+ if (isr3 & 0x02)
-+ dev_notice(&wc->dev->dev, "ALLO%d10P: RECEIVE "
-+ "slip NEGATIVE on span %d\n",
-+ wc->numspans, span + 1);
-+ if (isr3 & 0x01)
-+ dev_notice(&wc->dev->dev, "ALLO%d10P: RECEIVE "
-+ "slip POSITIVE on span %d\n",
-+ wc->numspans, span + 1);
-+ if (isr4 & 0x80)
-+ dev_notice(&wc->dev->dev, "ALLO%dXXP: TRANSMIT "
-+ "slip POSITIVE on span %d\n",
-+ wc->numspans, span + 1);
-+ if (isr4 & 0x40)
-+ dev_notice(&wc->dev->dev, "ALLO%d10P: TRANSMIT "
-+ "slip NEGATIVE on span %d\n",
-+ wc->numspans, span + 1);
-+ }
-+ } else
-+ ts->span.count.timingslips = 0;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ /* HDLC controller checks - receive side */
-+ if (!ts->sigchan) {
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return;
-+ }
-+
-+ sigchan = ts->sigchan;
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ if (isr0 & FRMR_ISR0_RME) {
-+ readsize = (t4_framer_in(wc, span, FRMR_RBCH) << 8) | t4_framer_in(wc, span, FRMR_RBCL);
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Received data length is %d "
-+ "(%d)\n", readsize,
-+ readsize & FRMR_RBCL_MAX_SIZE);
-+ /* RPF isn't set on last part of frame */
-+ if ((readsize > 0) && ((readsize &= FRMR_RBCL_MAX_SIZE) == 0))
-+ readsize = FRMR_RBCL_MAX_SIZE + 1;
-+ } else if (isr0 & FRMR_ISR0_RPF)
-+ readsize = FRMR_RBCL_MAX_SIZE + 1;
-+
-+ if (readsize > 0) {
-+ int i;
-+ unsigned char readbuf[FRMR_RBCL_MAX_SIZE + 1];
-+
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Framer %d: Got RPF/RME! "
-+ "readsize is %d\n", sigchan->span->offset,
-+ readsize);
-+
-+ for (i = 0; i < readsize; i++)
-+ readbuf[i] = t4_framer_in(wc, span, FRMR_RXFIFO);
-+
-+ /* Tell the framer to clear the RFIFO */
-+ t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC);
-+
-+ if (debug & DEBUG_FRAMER) {
-+ dev_notice(&wc->dev->dev, "RX(");
-+ for (i = 0; i < readsize; i++)
-+ dev_notice(&wc->dev->dev, "%s%02x",
-+ (i ? " " : ""), readbuf[i]);
-+ dev_notice(&wc->dev->dev, ")\n");
-+ }
-+
-+ if (isr0 & FRMR_ISR0_RME) {
-+ /* Do checks for HDLC problems */
-+ unsigned char rsis = readbuf[readsize-1];
-+ unsigned char rsis_reg = t4_framer_in(wc, span, FRMR_RSIS);
-+
-+ ++ts->frames_in;
-+ if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f))
-+ dev_notice(&wc->dev->dev, "Received %d frames "
-+ "on span %d\n", ts->frames_in, span);
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Received HDLC frame"
-+ " %d. RSIS = 0x%x (%x)\n",
-+ ts->frames_in, rsis, rsis_reg);
-+ if (!(rsis & FRMR_RSIS_CRC16)) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "CRC check "
-+ "failed %d\n", span);
-+ //dahdi_hdlc_abort(sigchan, DAHDI_EVENT_BADFCS);
-+ } else if (rsis & FRMR_RSIS_RAB) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "ABORT of "
-+ "current frame due to "
-+ "overflow %d\n", span);
-+ //dahdi_hdlc_abort(sigchan, DAHDI_EVENT_ABORT);
-+ } else if (rsis & FRMR_RSIS_RDO) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "HDLC "
-+ "overflow occured %d\n",
-+ span);
-+ dahdi_hdlc_abort(sigchan, DAHDI_EVENT_OVERRUN);
-+ } else if (!(rsis & FRMR_RSIS_VFR)) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Valid Frame"
-+ " check failed on span %d\n",
-+ span);
-+ //dahdi_hdlc_abort(sigchan, DAHDI_EVENT_ABORT);
-+ } else {
-+ dahdi_hdlc_putbuf(sigchan, readbuf, readsize - 1);
-+ dahdi_hdlc_finish(sigchan);
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Received "
-+ "valid HDLC frame on span %d"
-+ "\n", span);
-+ }
-+ } else if (isr0 & FRMR_ISR0_RPF)
-+ dahdi_hdlc_putbuf(sigchan, readbuf, readsize);
-+ }
-+
-+ /* Transmit side */
-+ if (isr1 & FRMR_ISR1_XDU) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "XDU: Resetting signal "
-+ "controller!\n");
-+ t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
-+ } else if (isr1 & FRMR_ISR1_XPR) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Sigchan %d is %p\n",
-+ sigchan->chanpos, sigchan);
-+
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "Framer %d: Got XPR!\n",
-+ sigchan->span->offset);
-+ t4_hdlc_xmit_fifo(wc, span, ts);
-+ }
-+
-+ if (isr1 & FRMR_ISR1_ALLS) {
-+ if (debug & DEBUG_FRAMER)
-+ dev_notice(&wc->dev->dev, "ALLS received\n");
-+ }
-+}
-+
-+#ifdef SUPPORT_GEN1
-+static irqreturn_t _t4_interrupt(int irq, void *dev_id)
-+{
-+ struct t4 *wc = dev_id;
-+ unsigned long flags;
-+ int x;
-+
-+ unsigned int status;
-+ unsigned int status2;
-+
-+ /* Make sure it's really for us */
-+ status = __t4_pci_in(wc, WC_INTR);
-+
-+ /* Process framer interrupts */
-+ status2 = t4_framer_in(wc, 0, FRMR_CIS);
-+ if (status2 & 0x0f) {
-+ for (x = 0; x < wc->numspans; ++x) {
-+ if (status2 & (1 << x))
-+ t4_framer_interrupt(wc, x);
-+ }
-+ }
-+
-+ /* Ignore if it's not for us */
-+ if (!status)
-+ return IRQ_NONE;
-+
-+ __t4_pci_out(wc, WC_INTR, 0);
-+
-+ if (!wc->spansstarted) {
-+ dev_notice(&wc->dev->dev, "Not prepped yet!\n");
-+ return IRQ_NONE;
-+ }
-+
-+ wc->intcount++;
-+
-+ if (status & 0x3) {
-+ t4_receiveprep(wc, status);
-+ t4_transmitprep(wc, status);
-+ }
-+
-+ t4_do_counters(wc);
-+
-+ x = wc->intcount & 15 /* 63 */;
-+ switch(x) {
-+ case 0:
-+ case 1:
-+ case 2:
-+ case 3:
-+ t4_check_sigbits(wc, x);
-+ break;
-+ case 4:
-+ case 5:
-+ case 6:
-+ case 7:
-+ t4_check_alarms(wc, x - 4);
-+ break;
-+ }
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ __handle_leds(wc);
-+
-+ if (test_bit(T4_CHECK_TIMING, &wc->checkflag))
-+ __t4_set_timing_source_auto(wc);
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ return IRQ_RETVAL(1);
-+}
-+
-+DAHDI_IRQ_HANDLER(t4_interrupt)
-+{
-+ irqreturn_t ret;
-+ unsigned long flags;
-+ local_irq_save(flags);
-+ ret = _t4_interrupt(irq, dev_id);
-+ local_irq_restore(flags);
-+ return ret;
-+}
-+#endif
-+
-+static int t4_allocate_buffers(struct t4 *wc, int numbufs,
-+ void **oldalloc, dma_addr_t *oldwritedma)
-+{
-+ void *alloc;
-+ dma_addr_t writedma;
-+
-+ /* 32 channels, Double-buffer, Read/Write, 4 spans */
-+ alloc = pci_alloc_consistent(wc->dev, numbufs * T4_BASE_SIZE(wc) * 2,
-+ &writedma);
-+
-+ if (!alloc) {
-+ dev_notice(&wc->dev->dev, "allo%dxxp: Unable to allocate "
-+ "DMA-able memory\n", wc->numspans);
-+ return -ENOMEM;
-+ }
-+
-+ if (oldwritedma)
-+ *oldwritedma = wc->writedma;
-+ if (oldalloc)
-+ *oldalloc = wc->writechunk;
-+
-+ wc->writechunk = alloc;
-+ wc->writedma = writedma;
-+
-+ /* Read is after the whole write piece (in words) */
-+ wc->readchunk = wc->writechunk + (T4_BASE_SIZE(wc) * numbufs) / 4;
-+
-+ /* Same thing but in bytes... */
-+ wc->readdma = wc->writedma + (T4_BASE_SIZE(wc) * numbufs);
-+
-+ wc->numbufs = numbufs;
-+
-+ /* Initialize Write/Buffers to all blank data */
-+ memset(wc->writechunk, 0x00, T4_BASE_SIZE(wc) * numbufs);
-+ memset(wc->readchunk, 0xff, T4_BASE_SIZE(wc) * numbufs);
-+
-+ if (debug) {
-+ dev_notice(&wc->dev->dev, "DMA memory base of size %d at " \
-+ "%p. Read: %p and Write %p\n",
-+ numbufs * T4_BASE_SIZE(wc) * 2, wc->writechunk,
-+ wc->readchunk, wc->writechunk);
-+ }
-+
-+ return 0;
-+}
-+
-+static void t4_increase_latency(struct t4 *wc, int newlatency)
-+{
-+ unsigned long flags;
-+ void *oldalloc;
-+ dma_addr_t oldaddr;
-+ int oldbufs;
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+
-+ __t4_pci_out(wc, WC_DMACTRL, 0x00000000);
-+ /* Acknowledge any pending interrupts */
-+ __t4_pci_out(wc, WC_INTR, 0x00000000);
-+
-+ __t4_pci_in(wc, WC_VERSION);
-+
-+ oldbufs = wc->numbufs;
-+
-+ if (t4_allocate_buffers(wc, newlatency, &oldalloc, &oldaddr)) {
-+ dev_info(&wc->dev->dev, "Error allocating latency buffers for "
-+ "latency of %d\n", newlatency);
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+ return;
-+ }
-+
-+ __t4_pci_out(wc, WC_RDADDR, wc->readdma);
-+ __t4_pci_out(wc, WC_WRADDR, wc->writedma);
-+
-+ __t4_pci_in(wc, WC_VERSION);
-+
-+ __t4_pci_out(wc, 5, (ms_per_irq << 16) | newlatency);
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+
-+ __t4_pci_in(wc, WC_VERSION);
-+
-+ wc->rxident = 0;
-+ wc->lastindex = 0;
-+
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ pci_free_consistent(wc->dev, T4_BASE_SIZE(wc) * oldbufs * 2,
-+ oldalloc, oldaddr);
-+
-+ dev_info(&wc->dev->dev, "Increased latency to %d\n", newlatency);
-+
-+}
-+
-+static void t4_isr_bh(unsigned long data)
-+{
-+ struct t4 *wc = (struct t4 *)data;
-+
-+ if (test_bit(T4_CHANGE_LATENCY, &wc->checkflag)) {
-+ if (wc->needed_latency != wc->numbufs) {
-+ t4_increase_latency(wc, wc->needed_latency);
-+ clear_bit(T4_CHANGE_LATENCY, &wc->checkflag);
-+ }
-+ }
-+#ifdef VPM_SUPPORT
-+ if (wc->vpm) {
-+ if (test_and_clear_bit(T4_CHECK_VPM, &wc->checkflag)) {
-+ /* How stupid is it that the octasic can't generate an
-+ * interrupt when there's a tone, in spite of what
-+ * their documentation says? */
-+ t4_check_vpm(wc);
-+ }
-+ }
-+#endif
-+}
-+
-+static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
-+{
-+ struct t4 *wc = dev_id;
-+ unsigned int status;
-+ unsigned char rxident, expected;
-+
-+ /* Check this first in case we get a spurious interrupt */
-+ if (unlikely(test_bit(T4_STOP_DMA, &wc->checkflag))) {
-+ /* Stop DMA cleanly if requested */
-+ wc->dmactrl = 0x0;
-+ t4_pci_out(wc, WC_DMACTRL, 0x00000000);
-+ /* Acknowledge any pending interrupts */
-+ t4_pci_out(wc, WC_INTR, 0x00000000);
-+ spin_lock(&wc->reglock);
-+ __t4_set_sclk_src(wc, WC_SELF, 0, 0);
-+ spin_unlock(&wc->reglock);
-+ return IRQ_RETVAL(1);
-+ }
-+
-+ /* Make sure it's really for us */
-+ status = __t4_pci_in(wc, WC_INTR);
-+
-+ /* Ignore if it's not for us */
-+ if (!(status & 0x7)) {
-+ return IRQ_NONE;
-+ }
-+
-+#ifdef ENABLE_WORKQUEUES
-+ __t4_pci_out(wc, WC_INTR, status & 0x00000008);
-+#endif
-+
-+ if (unlikely(!wc->spansstarted)) {
-+ dev_info(&wc->dev->dev, "Not prepped yet!\n");
-+ return IRQ_NONE;
-+ }
-+
-+ wc->intcount++;
-+ if ((wc->devtype->flags & FLAG_5THGEN) && (status & 0x2)) {
-+ rxident = (status >> 16) & 0x7f;
-+ expected = (wc->rxident + ms_per_irq) % 128;
-+
-+ if ((rxident != expected) && !test_bit(T4_IGNORE_LATENCY, &wc->checkflag)) {
-+ int needed_latency;
-+ int smallest_max;
-+
-+ if (debug & DEBUG_MAIN)
-+ dev_warn(&wc->dev->dev, "Missed interrupt. "
-+ "Expected ident of %d and got ident "
-+ "of %d\n", expected, rxident);
-+
-+ if (test_bit(T4_IGNORE_LATENCY, &wc->checkflag)) {
-+ dev_info(&wc->dev->dev,
-+ "Should have ignored latency\n");
-+ }
-+ if (rxident > wc->rxident) {
-+ needed_latency = rxident - wc->rxident;
-+ } else {
-+ needed_latency = (128 - wc->rxident) + rxident;
-+ }
-+
-+ needed_latency += 1;
-+
-+ smallest_max = (max_latency >= GEN5_MAX_LATENCY) ? GEN5_MAX_LATENCY : max_latency;
-+
-+ if (needed_latency > smallest_max) {
-+ dev_info(&wc->dev->dev, "Truncating latency "
-+ "request to %d instead of %d\n",
-+ smallest_max, needed_latency);
-+ needed_latency = smallest_max;
-+ }
-+
-+ if (needed_latency > wc->numbufs) {
-+ dev_info(&wc->dev->dev, "Need to increase "
-+ "latency. Estimated latency should "
-+ "be %d\n", needed_latency);
-+ wc->ddev->irqmisses++;
-+ wc->needed_latency = needed_latency;
-+ __t4_pci_out(wc, WC_DMACTRL, 0x00000000);
-+ set_bit(T4_CHANGE_LATENCY, &wc->checkflag);
-+ goto out;
-+ }
-+ }
-+
-+ wc->rxident = rxident;
-+ }
-+
-+#ifdef DEBUG
-+ if (unlikely((wc->intcount < 20)))
-+ dev_dbg(&wc->dev->dev, "2G: Got interrupt, status = %08x, "
-+ "CIS = %04x\n", status, t4_framer_in(wc, 0, FRMR_CIS));
-+#endif
-+
-+ if (likely(status & 0x2)) {
-+#ifdef ENABLE_WORKQUEUES
-+ int cpus = num_online_cpus();
-+ atomic_set(&wc->worklist, wc->numspans);
-+ if (wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)
-+ t4_queue_work(wc->workq, &wc->tspans[0]->swork, 0);
-+ else
-+ atomic_dec(&wc->worklist);
-+ if (wc->numspans >= 2) { //cem:1port change
-+ if (wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)
-+ t4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus);
-+ else
-+ atomic_dec(&wc->worklist);
-+ }
-+ if (wc->numspans == 4) {
-+ if (wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)
-+ t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus);
-+ else
-+ atomic_dec(&wc->worklist);
-+ if (wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)
-+ t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus);
-+ else
-+ atomic_dec(&wc->worklist);
-+ }
-+#else
-+ unsigned int reg5 = __t4_pci_in(wc, 5);
-+
-+#ifdef DEBUG
-+ if (wc->intcount < 20)
-+ dev_info(&wc->dev->dev, "Reg 5 is %08x\n", reg5);
-+#endif
-+
-+ if (wc->devtype->flags & FLAG_5THGEN) {
-+ unsigned int current_index = (reg5 >> 8) & 0x7f;
-+
-+ while (((wc->lastindex + 1) % wc->numbufs) != current_index) {
-+ wc->lastindex = (wc->lastindex + 1) % wc->numbufs;
-+ setup_chunks(wc, wc->lastindex);
-+ t4_prep_gen2(wc);
-+ }
-+ } else {
-+ t4_prep_gen2(wc);
-+ }
-+
-+#endif
-+ t4_do_counters(wc);
-+ spin_lock(&wc->reglock);
-+ __handle_leds(wc);
-+ spin_unlock(&wc->reglock);
-+
-+ }
-+
-+ if (unlikely(status & 0x1)) {
-+ unsigned char cis;
-+
-+ cis = t4_framer_in(wc, 0, FRMR_CIS);
-+ if (cis & FRMR_CIS_GIS1)
-+ t4_framer_interrupt(wc, 0);
-+ if (cis & FRMR_CIS_GIS2)
-+ t4_framer_interrupt(wc, 1);
-+ if (cis & FRMR_CIS_GIS3)
-+ t4_framer_interrupt(wc, 2);
-+ if (cis & FRMR_CIS_GIS4)
-+ t4_framer_interrupt(wc, 3);
-+
-+ if (is_octal(wc)) {
-+ if (cis & FRMR_CIS_GIS5)
-+ t4_framer_interrupt(wc, 4);
-+ if (cis & FRMR_CIS_GIS6)
-+ t4_framer_interrupt(wc, 5);
-+ if (cis & FRMR_CIS_GIS7)
-+ t4_framer_interrupt(wc, 6);
-+ if (cis & FRMR_CIS_GIS8)
-+ t4_framer_interrupt(wc, 7);
-+ }
-+ }
-+
-+#ifdef VPM_SUPPORT
-+ if (wc->vpm && vpmdtmfsupport) {
-+ /* How stupid is it that the octasic can't generate an
-+ * interrupt when there's a tone, in spite of what their
-+ * documentation says? */
-+ if (!(wc->intcount & 0xf))
-+ set_bit(T4_CHECK_VPM, &wc->checkflag);
-+ }
-+#endif
-+
-+ spin_lock(&wc->reglock);
-+
-+ if (unlikely(test_bit(T4_CHECK_TIMING, &wc->checkflag))) {
-+ __t4_set_timing_source_auto(wc);
-+ }
-+
-+ spin_unlock(&wc->reglock);
-+
-+out:
-+ if (unlikely(test_bit(T4_CHANGE_LATENCY, &wc->checkflag) || test_bit(T4_CHECK_VPM, &wc->checkflag)))
-+ tasklet_schedule(&wc->t4_tlet);
-+
-+#ifndef ENABLE_WORKQUEUES
-+ __t4_pci_out(wc, WC_INTR, 0);
-+#endif
-+
-+ return IRQ_RETVAL(1);
-+}
-+
-+DAHDI_IRQ_HANDLER(t4_interrupt_gen2)
-+{
-+ irqreturn_t ret;
-+ unsigned long flags;
-+ local_irq_save(flags);
-+ ret = _t4_interrupt_gen2(irq, dev_id);
-+ local_irq_restore(flags);
-+ return ret;
-+}
-+
-+#ifdef SUPPORT_GEN1
-+static int t4_reset_dma(struct t4 *wc)
-+{
-+ /* Turn off DMA and such */
-+ wc->dmactrl = 0x0;
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ t4_pci_out(wc, WC_COUNT, 0);
-+ t4_pci_out(wc, WC_RDADDR, 0);
-+ t4_pci_out(wc, WC_WRADDR, 0);
-+ t4_pci_out(wc, WC_INTR, 0);
-+ /* Turn it all back on */
-+ t4_pci_out(wc, WC_RDADDR, wc->readdma);
-+ t4_pci_out(wc, WC_WRADDR, wc->writedma);
-+ t4_pci_out(wc, WC_COUNT, ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 2));
-+ t4_pci_out(wc, WC_INTR, 0);
-+#ifdef VPM_SUPPORT
-+ wc->dmactrl = 0xc0000000 | (1 << 29) |
-+ ((wc->vpm) ? T4_VPM_PRESENT : 0);
-+#else
-+ wc->dmactrl = 0xc0000000 | (1 << 29);
-+#endif
-+ if (noburst)
-+ wc->dmactrl |= (1 << 26);
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ return 0;
-+}
-+#endif
-+
-+#ifdef VPM_SUPPORT
-+static void t4_vpm_init(struct t4 *wc)
-+{
-+ int laws[8] = { 0, };
-+ int x;
-+ unsigned int vpm_capacity;
-+ struct firmware embedded_firmware;
-+ const struct firmware *firmware = &embedded_firmware;
-+#if !defined(HOTPLUG_FIRMWARE)
-+ extern void _binary_dahdi_fw_oct6114_032_bin_size; //cem:1port change
-+ extern void _binary_dahdi_fw_oct6114_064_bin_size;
-+ extern void _binary_dahdi_fw_oct6114_128_bin_size;
-+ extern void _binary_dahdi_fw_oct6114_256_bin_size;
-+ extern u8 _binary_dahdi_fw_oct6114_032_bin_start[]; //cem:1port change
-+ extern u8 _binary_dahdi_fw_oct6114_064_bin_start[];
-+ extern u8 _binary_dahdi_fw_oct6114_128_bin_start[];
-+ extern u8 _binary_dahdi_fw_oct6114_256_bin_start[];
-+#else
-+ static const char oct032_firmware[] = "dahdi-fw-oct6114-032.bin"; //cem:1port change
-+ static const char oct064_firmware[] = "dahdi-fw-oct6114-064.bin";
-+ static const char oct128_firmware[] = "dahdi-fw-oct6114-128.bin";
-+ static const char oct256_firmware[] = "dahdi-fw-oct6114-256.bin";
-+#endif
-+
-+ if (!vpmsupport) {
-+ dev_info(&wc->dev->dev, "VPM450: Support Disabled\n");
-+ return;
-+ }
-+
-+ /* Turn on GPIO/DATA mux if supported */
-+ t4_gpio_setdir(wc, (1 << 24), (1 << 24));
-+ __t4_raw_oct_out(wc, 0x000a, 0x5678);
-+ __t4_raw_oct_out(wc, 0x0004, 0x1234);
-+ __t4_raw_oct_in(wc, 0x0004);
-+ __t4_raw_oct_in(wc, 0x000a);
-+ if (debug)
-+ dev_notice(&wc->dev->dev, "OCT Result: %04x/%04x\n",
-+ __t4_raw_oct_in(wc, 0x0004),
-+ __t4_raw_oct_in(wc, 0x000a));
-+ if (__t4_raw_oct_in(wc, 0x0004) != 0x1234) {
-+ dev_notice(&wc->dev->dev, "VPM450: Not Present\n");
-+ return;
-+ }
-+
-+ /* Setup alaw vs ulaw rules */
-+ for (x = 0;x < wc->numspans; x++) {
-+ if (wc->tspans[x]->span.channels > 24)
-+ laws[x] = 1;
-+ }
-+
-+ vpm_capacity = get_vpm450m_capacity(&wc->dev->dev);
-+ if (vpm_capacity != wc->numspans * 32) {
-+ dev_info(&wc->dev->dev, "Disabling VPMOCT%03d. ALLO%dXXP"\
-+ " requires a VPMOCT%03d", vpm_capacity,
-+ wc->numspans, wc->numspans*32);
-+ return;
-+ }
-+
-+ switch (vpm_capacity) {
-+ case 32:/*cem:1port change, v002*/
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct032_firmware, &wc->dev->dev) != 0) ||
-+ !firmware) {
-+ dev_notice(&wc->dev->dev, "VPM450: firmware %s not "
-+ "available from userspace\n", oct032_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_032_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_032_bin_size;
-+#endif
-+ break;
-+
-+ case 64:
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct064_firmware, &wc->dev->dev) != 0) ||
-+ !firmware) {
-+ dev_notice(&wc->dev->dev, "VPM450: firmware %s not "
-+ "available from userspace\n", oct064_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_064_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_064_bin_size;
-+#endif
-+ break;
-+ case 128:
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct128_firmware, &wc->dev->dev) != 0) ||
-+ !firmware) {
-+ dev_notice(&wc->dev->dev, "VPM450: firmware %s not "
-+ "available from userspace\n", oct128_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_128_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_128_bin_size;
-+#endif
-+ break;
-+ case 256:
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct256_firmware, &wc->dev->dev) != 0) ||
-+ !firmware) {
-+ dev_notice(&wc->dev->dev, "VPM450: firmware %s not "
-+ "available from userspace\n", oct256_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_256_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_256_bin_size;
-+#endif
-+ break;
-+ default:
-+ dev_notice(&wc->dev->dev, "Unsupported channel capacity found "
-+ "on VPM module (%d).\n", vpm_capacity);
-+ return;
-+ }
-+
-+ wc->vpm = init_vpm450m(&wc->dev->dev, laws, wc->numspans, firmware);
-+ if (!wc->vpm) {
-+ dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n");
-+ if (firmware != &embedded_firmware)
-+ release_firmware(firmware);
-+ return;
-+ }
-+
-+ if (firmware != &embedded_firmware)
-+ release_firmware(firmware);
-+
-+ if (vpmdtmfsupport == -1) {
-+ dev_info(&wc->dev->dev, "VPM450: hardware DTMF disabled.\n");
-+ vpmdtmfsupport = 0;
-+ }
-+
-+ dev_info(&wc->dev->dev, "VPM450: Present and operational servicing %d "
-+ "span(s)\n", wc->numspans);
-+
-+}
-+#endif /* VPM_SUPPORT */
-+
-+static void t4_tsi_reset(struct t4 *wc)
-+{
-+ int x;
-+ if (is_octal(wc)) {
-+ for (x = 0; x < 256; x++) {
-+ wc->dmactrl &= ~0x0001ffff;
-+ wc->dmactrl |= (0x00004000 | ((x & 0x7f) << 7) | ((x >> 7) << 15));
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ }
-+ wc->dmactrl &= ~0x0001ffff;
-+ } else {
-+ for (x = 0; x < 128; x++) {
-+ wc->dmactrl &= ~0x00007fff;
-+ wc->dmactrl |= (0x00004000 | (x << 7));
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ }
-+ wc->dmactrl &= ~0x00007fff;
-+ }
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+}
-+
-+/* Note that channels here start from 1 */
-+static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan)
-+{
-+ unsigned long flags;
-+ int fromts, tots;
-+
-+ fromts = (fromspan << 5) |(fromchan);
-+ tots = (tospan << 5) | (tochan);
-+
-+ if (!has_e1_span(wc)) {
-+ fromts += 4;
-+ tots += 4;
-+ }
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ if (is_octal(wc)) {
-+ int fromts_b = fromts & 0x7f;
-+ int fromts_t = fromts >> 7;
-+ int tots_b = tots & 0x7f;
-+ int tots_t = tots >> 7;
-+
-+ wc->dmactrl &= ~0x0001ffff;
-+ wc->dmactrl |= ((fromts_t << 16) | (tots_t << 15) | 0x00004000 | (tots_b << 7) | (fromts_b));
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ wc->dmactrl &= ~0x0001ffff;
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ } else {
-+ wc->dmactrl &= ~0x00007fff;
-+ wc->dmactrl |= (0x00004000 | (tots << 7) | (fromts));
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ wc->dmactrl &= ~0x00007fff;
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan)
-+{
-+ unsigned long flags;
-+ int tots;
-+
-+ tots = (tospan << 5) | (tochan);
-+
-+ if (!has_e1_span(wc))
-+ tots += 4;
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ if (is_octal(wc)) {
-+ int tots_b = tots & 0x7f;
-+ int tots_t = tots >> 7;
-+
-+ wc->dmactrl &= ~0x0001ffff;
-+ wc->dmactrl |= ((tots_t << 15) | 0x00004000 | (tots_b << 7));
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ if (debug & DEBUG_TSI)
-+ dev_notice(&wc->dev->dev, "Sending '%08x\n", wc->dmactrl);
-+ wc->dmactrl &= ~0x0001ffff;
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ } else {
-+ wc->dmactrl &= ~0x00007fff;
-+ wc->dmactrl |= (0x00004000 | (tots << 7));
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ if (debug & DEBUG_TSI)
-+ dev_notice(&wc->dev->dev, "Sending '%08x\n", wc->dmactrl);
-+ wc->dmactrl &= ~0x00007fff;
-+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ }
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+}
-+
-+#ifndef CONFIG_NOEXTENDED_RESET
-+static void t4_extended_reset(struct t4 *wc)
-+{
-+ unsigned int oldreg = t4_pci_in(wc, 0x4);
-+
-+ udelay(1000);
-+
-+ t4_pci_out(wc, 0x4, 0x42000000);
-+ t4_pci_out(wc, 0xa, 0x42000000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00180000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00180000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00180000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00180000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00180000);
-+ t4_pci_out(wc, 0xa, 0x00080000);
-+ t4_pci_out(wc, 0xa, 0x00180000);
-+ t4_pci_out(wc, 0x4, oldreg);
-+
-+ udelay(1000);
-+}
-+#endif
-+
-+#define SPI_CS (0)
-+#define SPI_CLK (1)
-+#define SPI_IO0 (2)
-+#define SPI_IO1 (3)
-+#define SPI_IO3 (4)
-+#define SPI_IO2 (5)
-+#define SPI_IN (0)
-+#define SPI_OUT (1)
-+#define ESPI_REG 13
-+
-+static void t8_clear_bit(struct t4 *wc, int whichb)
-+{
-+ wc->st.wrreg &= ~(1 << whichb);
-+}
-+
-+static void t8_set_bit(struct t4 *wc, int whichb, int val)
-+{
-+ t8_clear_bit(wc, whichb);
-+ wc->st.wrreg |= (val << whichb);
-+}
-+
-+static int t8_get_bit(struct t4 *wc, int whichb)
-+{
-+ return (wc->st.rdreg >> whichb) & 1;
-+}
-+
-+static void set_iodir(struct t4 *wc, int whichb, int dir)
-+{
-+ whichb += 16;
-+ t8_clear_bit(wc, whichb);
-+ t8_set_bit(wc, whichb, dir);
-+}
-+
-+static void write_hwreg(struct t4 *wc)
-+{
-+ t4_pci_out(wc, ESPI_REG, wc->st.wrreg);
-+}
-+
-+static void read_hwreg(struct t4 *wc)
-+{
-+ wc->st.rdreg = t4_pci_in(wc, ESPI_REG);
-+}
-+
-+static void set_cs(struct t4 *wc, int state)
-+{
-+ t8_set_bit(wc, SPI_CS, state);
-+ write_hwreg(wc);
-+}
-+
-+static void set_clk(struct t4 *wc, int clk)
-+{
-+ t8_set_bit(wc, SPI_CLK, clk);
-+ write_hwreg(wc);
-+}
-+
-+static void clk_bit_out(struct t4 *wc, int val)
-+{
-+ t8_set_bit(wc, SPI_IO0, val & 1);
-+ set_clk(wc, 0);
-+ set_clk(wc, 1);
-+}
-+
-+static void shift_out(struct t4 *wc, int val)
-+{
-+ int i;
-+ for (i = 7; i >= 0; i--)
-+ clk_bit_out(wc, (val >> i) & 1);
-+}
-+
-+static int clk_bit_in(struct t4 *wc)
-+{
-+ int ret;
-+ set_clk(wc, 0);
-+ read_hwreg(wc);
-+ ret = t8_get_bit(wc, SPI_IO1);
-+ set_clk(wc, 1);
-+ return ret;
-+}
-+
-+static int shift_in(struct t4 *wc)
-+{
-+ int ret = 0;
-+ int i;
-+ int bit;
-+
-+ for (i = 7; i >= 0; i--) {
-+ bit = clk_bit_in(wc);
-+ ret |= ((bit & 1) << i);
-+ }
-+ return ret;
-+}
-+
-+static void write_enable(struct t4 *wc)
-+{
-+ int cmd = 0x06;
-+ set_cs(wc, 0);
-+ shift_out(wc, cmd);
-+ set_cs(wc, 1);
-+}
-+
-+static int read_sr1(struct t4 *wc)
-+{
-+ int cmd = 0x05;
-+ int ret;
-+ set_cs(wc, 0);
-+ shift_out(wc, cmd);
-+ ret = shift_in(wc);
-+ set_cs(wc, 1);
-+ return ret;
-+}
-+
-+static void clear_busy(struct t4 *wc)
-+{
-+ static const int SR1_BUSY = (1 << 0);
-+ unsigned long stop;
-+
-+ stop = jiffies + 2*HZ;
-+ while (read_sr1(wc) & SR1_BUSY) {
-+ if (time_after(jiffies, stop)) {
-+ if (printk_ratelimit()) {
-+ dev_err(&wc->dev->dev,
-+ "Lockup in %s\n", __func__);
-+ }
-+ break;
-+ }
-+ cond_resched();
-+ }
-+}
-+
-+static void sector_erase(struct t4 *wc, uint32_t addr)
-+{
-+ int cmd = 0x20;
-+ write_enable(wc);
-+ set_cs(wc, 0);
-+ shift_out(wc, cmd);
-+ shift_out(wc, (addr >> 16) & 0xff);
-+ shift_out(wc, (addr >> 8) & 0xff);
-+ shift_out(wc, (addr >> 0) & 0xff);
-+ set_cs(wc, 1);
-+ clear_busy(wc);
-+}
-+
-+static void erase_half(struct t4 *wc)
-+{
-+ uint32_t addr = 0x00010000;
-+ uint32_t primary_firmware = 0x00250000;
-+ uint32_t i;
-+
-+ if(wc->devtype->flags & FLAG_2PORT | wc->devtype->flags & FLAG_1PORT)
-+ primary_firmware = 0x000E0000;
-+ dev_info(&wc->dev->dev, "Erasing fpag primary firmware from Address:%x\n",primary_firmware);
-+
-+ for (i = addr; i < (addr + primary_firmware); i += 4096)
-+ sector_erase(wc, i);
-+}
-+
-+
-+#define T8_FLASH_PAGE_SIZE 256UL
-+
-+static void t8_update_firmware_page(struct t4 *wc, u32 address,
-+ const u8 *page_data, size_t size)
-+{
-+ int i;
-+
-+ write_enable(wc);
-+ set_cs(wc, 0);
-+ shift_out(wc, 0x02);
-+ shift_out(wc, (address >> 16) & 0xff);
-+ shift_out(wc, (address >> 8) & 0xff);
-+ shift_out(wc, (address >> 0) & 0xff);
-+
-+ for (i = 0; i < size; ++i)
-+ shift_out(wc, page_data[i]);
-+
-+ set_cs(wc, 1);
-+ clear_busy(wc);
-+}
-+
-+static int t8_update_firmware(struct t4 *wc, const struct firmware *fw,
-+ const char *t8_firmware)
-+{
-+ int res;
-+ size_t offset = 0;
-+ const u32 BASE_ADDRESS = 0x00010000;
-+ const u8 *data, *end;
-+ size_t size = 0;
-+
-+ /* Erase flash */
-+ erase_half(wc);
-+
-+ dev_info(&wc->dev->dev,
-+ "Uploading %s. This can take up to 30 seconds.\n", t8_firmware);
-+
-+ data = &fw->data[sizeof(struct t8_firm_header)];
-+ end = &fw->data[fw->size];
-+
-+ while (data < end) {
-+ /* Calculate the tail end of data that's shorter than a page */
-+ size = min(T8_FLASH_PAGE_SIZE, (unsigned long)(end - data));
-+
-+ t8_update_firmware_page(wc, BASE_ADDRESS + offset,
-+ data, size);
-+ data += T8_FLASH_PAGE_SIZE;
-+ offset += T8_FLASH_PAGE_SIZE;
-+
-+ cond_resched();
-+ }
-+
-+ /* Reset te820 fpga after loading firmware */
-+#if 0
-+ dev_info(&wc->dev->dev, "Firmware load complete. Reseting device.\n");
-+/*allo:*/
-+ res = pci_save_state(wc->dev);
-+ if (res)
-+ goto error_exit;
-+ /* Set the fpga reset bits and clobber the remainder of the
-+ * register, device will be reset anyway */
-+ t4_pci_out(wc, WC_LEDS, 0xe0000000);
-+ msleep(1000);
-+
-+ pci_restore_state(wc->dev);
-+#endif
-+
-+ /* Signal the driver to restart initialization.
-+ * This will back out all initialization so far and
-+ * restart the driver load process */
-+ return -EAGAIN;
-+
-+error_exit:
-+ return res;
-+}
-+
-+static char read_flash_byte(struct t4 *wc, unsigned int addr)
-+{
-+ int cmd = 0x03;
-+ char data;
-+
-+ set_cs(wc, 0);
-+
-+ shift_out(wc, cmd);
-+
-+ shift_out(wc, (addr >> 16) & 0xff);
-+ shift_out(wc, (addr >> 8) & 0xff);
-+ shift_out(wc, (addr >> 0) & 0xff);
-+
-+ data = shift_in(wc) & 0xff;
-+
-+ set_cs(wc, 1);
-+
-+ return data;
-+}
-+
-+/**
-+ * t8_read_serial - Returns the serial number of the board.
-+ * @wc: The board whos serial number we are reading.
-+ *
-+ * The buffer returned is dynamically allocated and must be kfree'd by the
-+ * caller. If memory could not be allocated, NULL is returned.
-+ *
-+ * Must be called in process context.
-+ *
-+ */
-+static char *t8_read_serial(struct t4 *wc)
-+{
-+ int i;
-+ static const int MAX_SERIAL = 16;
-+ static const u32 base_addr = 0x00000000;
-+ unsigned char c;
-+ unsigned char *serial = kzalloc(MAX_SERIAL + 1, GFP_KERNEL);
-+
-+ if (!serial)
-+ return NULL;
-+
-+ for (i = 0; i < MAX_SERIAL; ++i) {
-+ c = read_flash_byte(wc, base_addr+i);
-+ if ((c >= 'a' && c <= 'z') ||
-+ (c >= 'A' && c <= 'Z') ||
-+ (c >= '0' && c <= '9'))
-+ serial[i] = c;
-+ else
-+ break;
-+
-+ }
-+
-+ if (!i) {
-+ kfree(serial);
-+ serial = NULL;
-+ }
-+
-+ return serial;
-+}
-+
-+
-+static void setup_spi(struct t4 *wc)
-+{
-+ wc->st.rdreg = wc->st.wrreg = 0;
-+
-+ set_iodir(wc, SPI_IO0, SPI_OUT);
-+ set_iodir(wc, SPI_IO1, SPI_IN);
-+ set_iodir(wc, SPI_CS, SPI_OUT);
-+ set_iodir(wc, SPI_CLK, SPI_OUT);
-+
-+ t8_set_bit(wc, SPI_CS, 1);
-+ t8_set_bit(wc, SPI_CLK, 1);
-+
-+ write_hwreg(wc);
-+}
-+
-+static int t8_check_firmware(struct t4 *wc, unsigned int version)
-+{
-+ int res = 0;
-+ u32 crc;
-+ const struct t8_firm_header *header;
-+ const struct firmware *fw;
-+ static const char *t8_firmware;
-+ static char t8_firm[128] = "allo-dahdi-fw-2aCP4.bin";
-+
-+ if (is_octal(wc)){
-+ strcpy(t8_firm,"allo-dahdi-fw-2aCP8e.bin");
-+ }
-+ else if(wc->devtype->flags & FLAG_2PORT){
-+ strcpy(t8_firm, "allo-dahdi-fw-2aCP2e.bin");
-+ }
-+ else if(wc->devtype->flags & FLAG_1PORT){
-+ strcpy(t8_firm, "allo-dahdi-fw-2aCP1e.bin");
-+ }
-+ else if (wc->devtype->flags & FLAG_EXPRESS){
-+ strcpy(t8_firm,"allo-dahdi-fw-2aCP4e.bin");
-+ }
-+
-+
-+ t8_firmware = (const char *)t8_firm;
-+
-+ res = request_firmware(&fw, t8_firmware, &wc->dev->dev);
-+ if (res) {
-+ dev_info(&wc->dev->dev, "firmware %s not "
-+ "available from userspace\n", t8_firmware);
-+ goto cleanup;
-+ }
-+
-+ header = (const struct t8_firm_header *)fw->data;
-+
-+/* Check the crc before anything else */
-+ crc = crc32(~0, &fw->data[10], fw->size - 10) ^ ~0;
-+ if (memcmp("CEMBLR", header->header, sizeof(header->header)) ||
-+ (le32_to_cpu(header->chksum) != crc)) {
-+ dev_info(&wc->dev->dev,
-+ "%s is invalid. Please reinstall.:%08X %08X\n", t8_firmware, le32_to_cpu(header->chksum), crc);
-+ goto cleanup;
-+ }
-+
-+ /* Spi struct must be setup before any access to flash memory */
-+ setup_spi(wc);
-+
-+ /* Check the two firmware versions */
-+ if (le32_to_cpu(header->version) == version)
-+ goto cleanup;
-+
-+ dev_info(&wc->dev->dev, "%s Version: %08x available for flash\n",
-+ t8_firmware, header->version);
-+
-+ res = t8_update_firmware(wc, fw, t8_firmware);
-+ if (res && res != -EAGAIN) {
-+ dev_info(&wc->dev->dev, "Failed to load firmware %s\n",
-+ t8_firmware);
-+ }
-+/*allo:*/
-+#if 1
-+ release_firmware(fw);
-+ return 0;
-+#endif
-+cleanup:
-+ release_firmware(fw);
-+ return res;
-+}
-+
-+static int
-+__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
-+{
-+ unsigned int version;
-+ int res;
-+
-+ version = t4_pci_in(wc, WC_VERSION);
-+ if (is_octal(wc) && first_time) {
-+ dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n",
-+ (version & 0xf00) >> 8,
-+ version & 0xff);
-+ } else if (first_time) {
-+ dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version);
-+ }
-+ if (debug) {
-+ dev_info(&wc->dev->dev, "Burst Mode: %s\n",
-+ (!(cardflags & FLAG_BURST) && noburst) ? "Off" : "On");
-+#ifdef ENABLE_WORKQUEUES
-+ dev_info(&wc->dev->dev, "Work Queues: Enabled\n");
-+#endif
-+ }
-+
-+ /* Check the field updatable firmware for the wcte820 */
-+ res = t8_check_firmware(wc, version);
-+ if (res)
-+ return res;
-+ wc->ddev->hardware_id = t8_read_serial(wc);
-+
-+#if defined(CONFIG_FORCE_EXTENDED_RESET)
-+ t4_extended_reset(wc);
-+#elif !defined(CONFIG_NOEXTENDED_RESET)
-+ if (wc->devtype->flags & FLAG_EXPRESS)
-+ t4_extended_reset(wc);
-+#endif
-+
-+ /* Make sure DMA engine is not running and interrupts are acknowledged */
-+ wc->dmactrl = 0x0;
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ /* Reset Framer and friends */
-+ t4_pci_out(wc, WC_LEDS, 0x00000000);
-+
-+ /* Set DMA addresses */
-+ t4_pci_out(wc, WC_RDADDR, wc->readdma);
-+ t4_pci_out(wc, WC_WRADDR, wc->writedma);
-+
-+ /* Setup counters, interrupt flags (ignored in Gen2) */
-+ if (cardflags & FLAG_2NDGEN) {
-+ t4_tsi_reset(wc);
-+ } else {
-+ t4_pci_out(wc, WC_COUNT, ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((DAHDI_MAX_CHUNKSIZE * 2 * 32 - 1) << 2));
-+ }
-+
-+ /* Reset pending interrupts */
-+ 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;
-+ }
-+ } 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;
-+ order_index[wc->order]++;
-+
-+ /* TE820 Auth Check */
-+ if (is_octal(wc)) {
-+ unsigned long stop = jiffies + HZ;
-+ uint32_t donebit;
-+
-+ t4_pci_out(wc, WC_LEDS2, WC_SET_AUTH);
-+ donebit = t4_pci_in(wc, WC_LEDS2);
-+ while (!(donebit & WC_GET_AUTH)) {
-+ if (time_after(jiffies, stop)) {
-+ /* Encryption check failed, stop operation */
-+ dev_info(&wc->dev->dev,
-+ "Failed encryption check. "
-+ "Unloading driver.\n");
-+ return -EIO;
-+ }
-+ msleep(20);
-+ donebit = t4_pci_in(wc, WC_LEDS2);
-+ }
-+ }
-+
-+ 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)
-+{
-+ int x;
-+ unsigned int regval;
-+ unsigned long flags;
-+
-+ if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) {
-+ wc->tspans[0]->spanflags |= FLAG_OCTOPT;
-+ }
-+ /* Setup LEDS, take out of reset */
-+ t4_pci_out(wc, WC_LEDS, 0x000000ff);
-+ udelay(100);
-+ t4_activate(wc);
-+ udelay(100);
-+
-+ /* In order to find out the QFALC framer version, we have to
-+ * temporarily turn off compat mode and take a peak at VSTR. We turn
-+ * compat back on when we are done.
-+ *
-+ */
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ regval = __t4_framer_in(wc, 0, 0xd6);
-+ if (is_octal(wc))
-+ regval |= (1 << 4); /* SSI16 - For 16 MHz multiplex mode with comp = 1 */
-+ else
-+ regval |= (1 << 5); /* set COMP_DIS*/
-+
-+ __t4_framer_out(wc, 0, 0xd6, regval);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ if (!is_octal(wc)) {
-+ regval = t4_framer_in(wc, 0, 0x4a);
-+ if (first_time && 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");
-+ wc->falc31 = 1;
-+ } else if (first_time) {
-+ dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
-+ "(VSTR = 0x%02x)\n", regval);
-+ }
-+ }
-+
-+ spin_lock_irqsave(&wc->reglock, flags);
-+ regval = __t4_framer_in(wc, 0, 0xd6);
-+ regval &= ~(1 << 5); /* clear COMP_DIS*/
-+ __t4_framer_out(wc, 0, 0xd6, regval);
-+ __t4_framer_out(wc, 0, 0x4a, 0xaa);
-+ spin_unlock_irqrestore(&wc->reglock, flags);
-+
-+ if (debug) {
-+ dev_info(&wc->dev->dev, "Board ID: %02x\n", wc->order);
-+ for (x = 0; x < 11; x++) {
-+ dev_info(&wc->dev->dev, "Reg %d: 0x%08x\n", x,
-+ 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;
-+
-+ if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
-+ return 0;
-+
-+ if (debug) {
-+ dev_info(&wc->dev->dev,
-+ "ALLO%dXXP: Launching card: %d\n", wc->numspans,
-+ wc->order);
-+ }
-+
-+ wc->ddev->manufacturer = "Allo";
-+ if (!ignore_rotary && (1 == order_index[wc->order])) {
-+ wc->ddev->location = kasprintf(GFP_KERNEL,
-+ "Board ID Switch %d", wc->order);
-+ } else {
-+ bool express = ((wc->tspans[0]->spanflags & FLAG_EXPRESS) > 0);
-+ wc->ddev->location = kasprintf(GFP_KERNEL,
-+ "PCI%s Bus %02d Slot %02d",
-+ (express) ? " Express" : "",
-+ wc->dev->bus->number,
-+ PCI_SLOT(wc->dev->devfn) + 1);
-+ }
-+
-+ if (!wc->ddev->location)
-+ return -ENOMEM;
-+
-+ for (x = 0; x < wc->numspans; ++x) {
-+ list_add_tail(&wc->tspans[x]->span.device_node,
-+ &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;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * allo4xxp_sort_cards - Sort the cards in card array by rotary switch settings.
-+ *
-+ */
-+static void allo4xxp_sort_cards(void)
-+{
-+ int x;
-+
-+ /* get the current number of probed cards and run a slice of a tail
-+ * insertion sort */
-+ for (x = 0; x < MAX_T4_CARDS; x++) {
-+ if (!cards[x+1])
-+ break;
-+ }
-+ for ( ; x > 0; x--) {
-+ if (cards[x]->order < cards[x-1]->order) {
-+ struct t4 *tmp = cards[x];
-+ cards[x] = cards[x-1];
-+ cards[x-1] = tmp;
-+ } else {
-+ /* if we're not moving it, we won't move any more
-+ * since all cards are sorted on addition */
-+ break;
-+ }
-+ }
-+}
-+
-+static int __devinit
-+t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-+{
-+ int res;
-+ struct t4 *wc;
-+ unsigned int x;
-+ int init_latency;
-+
-+ if (pci_enable_device(pdev)) {
-+ return -EIO;
-+ }
-+
-+ wc = kzalloc(sizeof(*wc), GFP_KERNEL);
-+ if (!wc)
-+ return -ENOMEM;
-+
-+ wc->ddev = dahdi_create_device();
-+ if (!wc->ddev) {
-+ kfree(wc);
-+ return -ENOMEM;
-+ }
-+
-+ spin_lock_init(&wc->reglock);
-+ wc->devtype = (const struct devtype *)(ent->driver_data);
-+
-+#ifdef CONFIG_WCT4XXP_DISABLE_ASPM
-+ if (is_pcie(wc)) {
-+ pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S |
-+ PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
-+ };
-+#endif
-+
-+ if (is_octal(wc))
-+ wc->numspans = 8;
-+ else if (wc->devtype->flags & FLAG_2PORT)
-+ wc->numspans = 2;
-+ else if (wc->devtype->flags & FLAG_1PORT)/*cem:1port change, v002*/
-+ wc->numspans = 1;
-+ else
-+ wc->numspans = 4;
-+
-+ wc->membase = pci_iomap(pdev, 0, 0);
-+ /* This rids of the Double missed interrupt message after loading */
-+ wc->last0 = 1;
-+ if (pci_request_regions(pdev, wc->devtype->desc))
-+ dev_info(&pdev->dev, "allo%dxxp: Unable to request regions\n",
-+ wc->numspans);
-+
-+ if (debug)
-+ dev_info(&pdev->dev, "Found ALLO%dXXP\n", wc->numspans);
-+
-+ wc->dev = pdev;
-+
-+ /* Enable bus mastering */
-+ pci_set_master(pdev);
-+
-+ /* Keep track of which device we are */
-+ pci_set_drvdata(pdev, wc);
-+
-+ if (wc->devtype->flags & FLAG_5THGEN) {
-+ if ((ms_per_irq > 1) && (latency <= ((ms_per_irq) << 1))) {
-+ init_latency = ms_per_irq << 1;
-+ } else {
-+ if (latency > 2)
-+ init_latency = latency;
-+ else
-+ init_latency = 2;
-+ }
-+/*ALLO:*/
-+ dev_info(&wc->dev->dev, "2nd gen card with initial latency of "
-+ "%d and %d ms per IRQ\n", init_latency, ms_per_irq);
-+ } else {
-+ if (wc->devtype->flags & FLAG_2NDGEN)
-+ init_latency = 1;
-+ else
-+ init_latency = 2;
-+ }
-+
-+ if (max_latency < init_latency) {
-+ printk(KERN_INFO "maxlatency must be set to something greater than %d ms, increasing it to %d\n", init_latency, init_latency);
-+ max_latency = init_latency;
-+ }
-+
-+ if (t4_allocate_buffers(wc, init_latency, NULL, NULL)) {
-+ return -ENOMEM;
-+ }
-+
-+ /* Initialize hardware */
-+ res = t4_hardware_init_1(wc, wc->devtype->flags);
-+ if (res) {
-+ /* If this function returns -EAGAIN, we expect
-+ * to attempt another driver load. Clean everything
-+ * up first */
-+ pci_iounmap(wc->dev, wc->membase);
-+ pci_release_regions(wc->dev);
-+ pci_free_consistent(wc->dev, T4_BASE_SIZE(wc) * wc->numbufs * 2,
-+ wc->writechunk, wc->writedma);
-+ pci_set_drvdata(wc->dev, NULL);
-+ free_wc(wc);
-+ return res;
-+ }
-+
-+ for(x = 0; x < MAX_T4_CARDS; x++) {
-+ if (!cards[x])
-+ break;
-+ }
-+
-+ if (x >= MAX_T4_CARDS) {
-+ dev_notice(&wc->dev->dev, "No cards[] slot available!!\n");
-+ kfree(wc);
-+ return -ENOMEM;
-+ }
-+
-+ wc->num = x;
-+ cards[x] = wc;
-+
-+#ifdef ENABLE_WORKQUEUES
-+ if (wc->devtype->flags & FLAG_2NDGEN) {
-+ char tmp[20];
-+
-+ sprintf(tmp, "te%dxxp[%d]", wc->numspans, wc->num);
-+ wc->workq = create_workqueue(tmp);
-+ }
-+#endif
-+
-+ /* Allocate pieces we need here */
-+ for (x = 0; x < ports_on_framer(wc); x++) {
-+ struct t4_span *ts;
-+ enum linemode linemode;
-+
-+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
-+ if (!ts) {
-+ free_wc(wc);
-+ return -ENOMEM;
-+ }
-+ wc->tspans[x] = ts;
-+
-+#ifdef ENABLE_WORKQUEUES
-+ INIT_WORK(&ts->swork, workq_handlespan, ts);
-+#endif
-+ ts->spanflags |= wc->devtype->flags;
-+ linemode = (wc->t1e1 & (1 << x)) ? E1 : ((j1mode) ? J1 : T1);
-+ t4_alloc_channels(wc, wc->tspans[x], linemode);
-+ }
-+
-+ /* Continue hardware intiialization */
-+ t4_hardware_init_2(wc);
-+
-+#ifdef SUPPORT_GEN1
-+ if (request_irq(pdev->irq, (wc->devtype->flags & FLAG_2NDGEN) ?
-+ t4_interrupt_gen2 : t4_interrupt,
-+ DAHDI_IRQ_SHARED,
-+ (wc->numspans == 8) ? "allo8xxp" :
-+ (wc->numspans == 2) ? "allo2xxp" :
-+ (wc->numspans == 1)? "allo1xxp" :
-+ "allo4xxp",
-+ wc)) {
-+#else
-+ if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) {
-+ dev_notice(&wc->dev->dev, "This driver does not "
-+ "support 1st gen modules\n");
-+ free_wc(wc);
-+ return -ENODEV;
-+ }
-+
-+ if (request_irq(pdev->irq, t4_interrupt_gen2,
-+ DAHDI_IRQ_SHARED, "t4xxp", wc)) {
-+#endif
-+ dev_notice(&wc->dev->dev, "Unable to request IRQ %d\n",
-+ pdev->irq);
-+ free_wc(wc);
-+ return -EIO;
-+ }
-+
-+ init_spans(wc);
-+
-+ if (!ignore_rotary)
-+ allo4xxp_sort_cards();
-+
-+ if (wc->ddev->hardware_id) {
-+ dev_info(&wc->dev->dev,
-+ "Found a Allocard: %s (SN: %s)\n", wc->devtype->desc,
-+ wc->ddev->hardware_id);
-+ } else {
-+ dev_info(&wc->dev->dev,
-+ "Found a Allocard: %s\n", wc->devtype->desc);
-+ }
-+
-+#ifdef VPM_SUPPORT
-+ if (!wc->vpm) {
-+ t4_vpm_init(wc);
-+ wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0;
-+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
-+ if (wc->vpm)
-+ set_span_devicetype(wc);
-+ }
-+#endif
-+
-+ create_sysfs_files(wc);
-+
-+ res = 0;
-+ if (ignore_rotary)
-+ res = t4_launch(wc);
-+
-+ return res;
-+}
-+
-+static int t4_hardware_stop(struct t4 *wc)
-+{
-+
-+ /* Turn off DMA, leave interrupts enabled */
-+ set_bit(T4_STOP_DMA, &wc->checkflag);
-+
-+ /* Wait for interrupts to stop */
-+ msleep(25);
-+
-+ /* Turn off counter, address, etc */
-+ if (wc->tspans[0]->spanflags & FLAG_2NDGEN) {
-+ t4_tsi_reset(wc);
-+ } else {
-+ t4_pci_out(wc, WC_COUNT, 0x000000);
-+ }
-+ t4_pci_out(wc, WC_RDADDR, 0x0000000);
-+ t4_pci_out(wc, WC_WRADDR, 0x0000000);
-+ wc->gpio = 0x00000000;
-+ t4_pci_out(wc, WC_GPIO, wc->gpio);
-+ t4_pci_out(wc, WC_LEDS, 0x00000000);
-+
-+ if (debug) {
-+ dev_notice(&wc->dev->dev, "Stopped ALLO%dXXP, Turned off DMA\n",
-+ wc->numspans);
-+ }
-+ return 0;
-+}
-+
-+static int __devinit
-+t4_init_one_retry(struct pci_dev *pdev, const struct pci_device_id *ent)
-+{
-+ int res;
-+ res = t4_init_one(pdev, ent);
-+
-+ /* If the driver was reset by a firmware load,
-+ * try to load once again */
-+ if (-EAGAIN == res) {
-+ res = t4_init_one(pdev, ent);
-+ if (-EAGAIN == res) {
-+ dev_err(&pdev->dev, "Failed to update firmware.\n");
-+ res = -EIO;
-+ }
-+ }
-+
-+ return res;
-+}
-+
-+static void _t4_remove_one(struct t4 *wc)
-+{
-+ int basesize;
-+
-+ if (!wc)
-+ return;
-+
-+ dahdi_unregister_device(wc->ddev);
-+
-+ remove_sysfs_files(wc);
-+
-+ /* Stop hardware */
-+ t4_hardware_stop(wc);
-+
-+#ifdef VPM_SUPPORT
-+ /* Release vpm */
-+ if (wc->vpm)
-+ release_vpm450m(wc->vpm);
-+ wc->vpm = NULL;
-+#endif
-+ /* Unregister spans */
-+
-+ basesize = DAHDI_MAX_CHUNKSIZE * 32 * 4;
-+ if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN))
-+ basesize = basesize * 2;
-+
-+#ifdef ENABLE_WORKQUEUES
-+ if (wc->workq) {
-+ flush_workqueue(wc->workq);
-+ destroy_workqueue(wc->workq);
-+ }
-+#endif
-+
-+ free_irq(wc->dev->irq, wc);
-+
-+ if (wc->membase)
-+ pci_iounmap(wc->dev, wc->membase);
-+
-+ pci_release_regions(wc->dev);
-+
-+ /* Immediately free resources */
-+ pci_free_consistent(wc->dev, T4_BASE_SIZE(wc) * wc->numbufs * 2,
-+ wc->writechunk, wc->writedma);
-+
-+ order_index[wc->order]--;
-+
-+ cards[wc->num] = NULL;
-+ pci_set_drvdata(wc->dev, NULL);
-+ free_wc(wc);
-+}
-+
-+static void __devexit t4_remove_one(struct pci_dev *pdev)
-+{
-+ struct t4 *wc = pci_get_drvdata(pdev);
-+ if (!wc)
-+ return;
-+
-+ _t4_remove_one(wc);
-+}
-+
-+
-+static DEFINE_PCI_DEVICE_TABLE(t4_pci_tbl) =
-+{
-+
-+/*ALLO:*/
-+ { 0x1d21, 0x1280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&allo1280p2 },
-+ { 0x1d21, 0x1240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&allo1240p2 },
-+ { 0x1d21, 0x1241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&allo1241p2 },
-+ { 0x1d21, 0x1220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&allo1220p2 },
-+ { 0x1d21, 0x1210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&allo1210p2 },
-+ { 0, }
-+};
-+
-+static void _t4_shutdown(struct pci_dev *pdev)
-+{
-+ struct t4 *wc = pci_get_drvdata(pdev);
-+ t4_hardware_stop(wc);
-+}
-+
-+static int t4_suspend(struct pci_dev *pdev, pm_message_t state)
-+{
-+ return -ENOSYS;
-+}
-+
-+static struct pci_driver t4_driver = {
-+ .name = "allo4xxp",
-+ .probe = t4_init_one_retry,
-+ .remove = __devexit_p(t4_remove_one),
-+ .shutdown = _t4_shutdown,
-+ .suspend = t4_suspend,
-+ .id_table = t4_pci_tbl,
-+};
-+
-+static int __init t4_init(void)
-+{
-+ int i;
-+ int res;
-+
-+ if (-1 != t1e1override) {
-+ pr_info("'t1e1override' module parameter is deprecated. "
-+ "Please use 'default_linemode' instead.\n");
-+ }
-+
-+ res = dahdi_pci_module(&t4_driver);
-+ if (res)
-+ return -ENODEV;
-+
-+ /* If we're ignoring the rotary switch settings, then we've already
-+ * registered in the context of .probe */
-+ if (!ignore_rotary) {
-+
-+ /* Initialize cards since we have all of them. Warn for
-+ * missing zero and duplicate numbers. */
-+
-+ if (cards[0] && cards[0]->order != 0) {
-+ printk(KERN_NOTICE "allo4xxp: Ident of first card is not zero (%d)\n",
-+ cards[0]->order);
-+ }
-+
-+ for (i = 0; cards[i]; i++) {
-+ /* warn the user of duplicate ident values it is
-+ * probably unintended */
-+ if (debug && res < 15 && cards[i+1] &&
-+ cards[res]->order == cards[i+1]->order) {
-+ printk(KERN_NOTICE "allo4xxp: Duplicate ident "
-+ "value found (%d)\n", cards[i]->order);
-+ }
-+ res = t4_launch(cards[i]);
-+ if (res) {
-+ int j;
-+ for (j = 0; j < i; ++j)
-+ _t4_remove_one(cards[j]);
-+ break;
-+ }
-+ }
-+ }
-+ return res;
-+}
-+
-+static void __exit t4_cleanup(void)
-+{
-+ pci_unregister_driver(&t4_driver);
-+}
-+
-+MODULE_AUTHOR("Allo Incorporated <support@allo.com>");
-+MODULE_DESCRIPTION("Wildcard Dual/Quad/Octal-port Digital Card Driver");
-+MODULE_ALIAS("allo2xxp");
-+MODULE_LICENSE("GPL v2");
-+
-+module_param(debug, int, 0600);
-+module_param(noburst, int, 0600);
-+module_param(timingcable, int, 0600);
-+module_param(t1e1override, int, 0400);
-+module_param(default_linemode, charp, S_IRUGO);
-+MODULE_PARM_DESC(default_linemode, "\"auto\"(default), \"e1\", \"t1\", "
-+ "or \"j1\". \"auto\" will use the value from any hardware "
-+ "jumpers.");
-+module_param(alarmdebounce, int, 0600);
-+module_param(losalarmdebounce, int, 0600);
-+module_param(aisalarmdebounce, int, 0600);
-+module_param(yelalarmdebounce, int, 0600);
-+module_param(max_latency, int, 0600);
-+module_param(j1mode, int, 0600);
-+module_param(sigmode, int, 0600);
-+module_param(latency, int, 0600);
-+module_param(ms_per_irq, int, 0600);
-+module_param(ignore_rotary, int, 0400);
-+MODULE_PARM_DESC(ignore_rotary, "Set to > 0 to ignore the rotary switch when " \
-+ "registering with DAHDI.");
-+
-+#ifdef VPM_SUPPORT
-+module_param(vpmsupport, int, 0600);
-+module_param(vpmdtmfsupport, int, 0600);
-+#endif
-+
-+MODULE_DEVICE_TABLE(pci, t4_pci_tbl);
-+
-+module_init(t4_init);
-+module_exit(t4_cleanup);
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/vpm450m.c dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/vpm450m.c
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/vpm450m.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/vpm450m.c 2015-02-10 15:01:15.889462151 +0100
-@@ -0,0 +1,624 @@
-+/*
-+ * Copyright (C) 2005-2012 Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ *
-+ * 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/string.h>
-+#include <linux/time.h>
-+#include <linux/version.h>
-+
-+#include <dahdi/kernel.h>
-+#include <stdbool.h>
-+
-+#include "vpm450m.h"
-+#include <oct612x.h>
-+
-+static int wct4xxp_oct612x_write(struct oct612x_context *context,
-+ u32 address, u16 value)
-+{
-+ struct t4 *wc = dev_get_drvdata(context->dev);
-+ oct_set_reg(wc, address, value);
-+ return 0;
-+}
-+
-+static int wct4xxp_oct612x_read(struct oct612x_context *context, u32 address,
-+ u16 *value)
-+{
-+ struct t4 *wc = dev_get_drvdata(context->dev);
-+ *value = (u16)oct_get_reg(wc, address);
-+ return 0;
-+}
-+
-+static int wct4xxp_oct612x_write_smear(struct oct612x_context *context,
-+ u32 address, u16 value, size_t count)
-+{
-+ 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;
-+}
-+
-+static int wct4xxp_oct612x_write_burst(struct oct612x_context *context,
-+ u32 address, const u16 *buffer,
-+ size_t count)
-+{
-+ 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;
-+}
-+
-+static int wct4xxp_oct612x_read_burst(struct oct612x_context *context,
-+ u32 address, u16 *buffer, size_t count)
-+{
-+ 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;
-+}
-+
-+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,
-+};
-+
-+#define SOUT_G168_1100GB_ON 0x40000004
-+#define SOUT_DTMF_1 0x40000011
-+#define SOUT_DTMF_2 0x40000012
-+#define SOUT_DTMF_3 0x40000013
-+#define SOUT_DTMF_A 0x4000001A
-+#define SOUT_DTMF_4 0x40000014
-+#define SOUT_DTMF_5 0x40000015
-+#define SOUT_DTMF_6 0x40000016
-+#define SOUT_DTMF_B 0x4000001B
-+#define SOUT_DTMF_7 0x40000017
-+#define SOUT_DTMF_8 0x40000018
-+#define SOUT_DTMF_9 0x40000019
-+#define SOUT_DTMF_C 0x4000001C
-+#define SOUT_DTMF_STAR 0x4000001E
-+#define SOUT_DTMF_0 0x40000010
-+#define SOUT_DTMF_POUND 0x4000001F
-+#define SOUT_DTMF_D 0x4000001D
-+
-+#define ROUT_G168_2100GB_ON 0x10000000
-+#define ROUT_G168_2100GB_WSPR 0x10000002
-+#define ROUT_SOUT_G168_2100HB_END 0x50000003
-+#define ROUT_G168_1100GB_ON 0x10000004
-+
-+#define ROUT_DTMF_1 0x10000011
-+#define ROUT_DTMF_2 0x10000012
-+#define ROUT_DTMF_3 0x10000013
-+#define ROUT_DTMF_A 0x1000001A
-+#define ROUT_DTMF_4 0x10000014
-+#define ROUT_DTMF_5 0x10000015
-+#define ROUT_DTMF_6 0x10000016
-+#define ROUT_DTMF_B 0x1000001B
-+#define ROUT_DTMF_7 0x10000017
-+#define ROUT_DTMF_8 0x10000018
-+#define ROUT_DTMF_9 0x10000019
-+#define ROUT_DTMF_C 0x1000001C
-+#define ROUT_DTMF_STAR 0x1000001E
-+#define ROUT_DTMF_0 0x10000010
-+#define ROUT_DTMF_POUND 0x1000001F
-+#define ROUT_DTMF_D 0x1000001D
-+
-+#if 0
-+#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE
-+#else
-+#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN
-+#endif
-+
-+struct vpm450m {
-+ tPOCT6100_INSTANCE_API pApiInstance;
-+ struct oct612x_context context;
-+ UINT32 aulEchoChanHndl[256];
-+ int chanflags[256];
-+ int ecmode[256];
-+ int numchans;
-+};
-+
-+#define FLAG_DTMF (1 << 0)
-+#define FLAG_MUTE (1 << 1)
-+#define FLAG_ECHO (1 << 2)
-+#define FLAG_ALAW (1 << 3)
-+
-+static unsigned int tones[] = {
-+ SOUT_DTMF_1,
-+ SOUT_DTMF_2,
-+ SOUT_DTMF_3,
-+ SOUT_DTMF_A,
-+ SOUT_DTMF_4,
-+ SOUT_DTMF_5,
-+ SOUT_DTMF_6,
-+ SOUT_DTMF_B,
-+ SOUT_DTMF_7,
-+ SOUT_DTMF_8,
-+ SOUT_DTMF_9,
-+ SOUT_DTMF_C,
-+ SOUT_DTMF_STAR,
-+ SOUT_DTMF_0,
-+ SOUT_DTMF_POUND,
-+ SOUT_DTMF_D,
-+ SOUT_G168_1100GB_ON,
-+
-+ ROUT_DTMF_1,
-+ ROUT_DTMF_2,
-+ ROUT_DTMF_3,
-+ ROUT_DTMF_A,
-+ ROUT_DTMF_4,
-+ ROUT_DTMF_5,
-+ ROUT_DTMF_6,
-+ ROUT_DTMF_B,
-+ ROUT_DTMF_7,
-+ ROUT_DTMF_8,
-+ ROUT_DTMF_9,
-+ ROUT_DTMF_C,
-+ ROUT_DTMF_STAR,
-+ ROUT_DTMF_0,
-+ ROUT_DTMF_POUND,
-+ ROUT_DTMF_D,
-+ ROUT_G168_1100GB_ON,
-+};
-+
-+void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
-+ bool alaw)
-+{
-+ tOCT6100_CHANNEL_MODIFY *modify;
-+ UINT32 ulResult;
-+ UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW :
-+ cOCT6100_PCM_U_LAW;
-+
-+ if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
-+ pr_err("Channel out of bounds in %s\n", __func__);
-+ return;
-+ }
-+ /* If we're already in this companding mode, no need to do anything. */
-+ if (alaw == ((vpm450m->chanflags[channel] & FLAG_ALAW) > 0))
-+ return;
-+
-+ modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
-+ if (!modify) {
-+ pr_notice("Unable to allocate memory for setec!\n");
-+ return;
-+ }
-+
-+ Oct6100ChannelModifyDef(modify);
-+ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel];
-+ modify->fTdmConfigModified = TRUE;
-+ modify->TdmConfig.ulSinPcmLaw = law_to_use;
-+ modify->TdmConfig.ulRinPcmLaw = law_to_use;
-+ modify->TdmConfig.ulSoutPcmLaw = law_to_use;
-+ modify->TdmConfig.ulRoutPcmLaw = law_to_use;
-+ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify);
-+ if (ulResult != GENERIC_OK) {
-+ pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n",
-+ vpm450m->aulEchoChanHndl[channel], channel, ulResult);
-+ } else {
-+ if (debug) {
-+ pr_info("Changed companding on channel %d to %s.\n",
-+ channel, (alaw) ? "alaw" : "ulaw");
-+ }
-+ if (alaw)
-+ vpm450m->chanflags[channel] |= FLAG_ALAW;
-+ else
-+ vpm450m->chanflags[channel] &= ~(FLAG_ALAW);
-+ }
-+ kfree(modify);
-+}
-+
-+static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode)
-+{
-+ tOCT6100_CHANNEL_MODIFY *modify;
-+ UINT32 ulResult;
-+
-+ if (vpm450m->ecmode[channel] == mode)
-+ return;
-+ modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
-+ if (!modify) {
-+ printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setec!\n");
-+ return;
-+ }
-+ Oct6100ChannelModifyDef(modify);
-+ modify->ulEchoOperationMode = mode;
-+ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel];
-+ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify);
-+ if (ulResult != GENERIC_OK) {
-+ printk(KERN_NOTICE "Failed to apply echo can changes on channel %d %08x!\n", channel, ulResult);
-+ } else {
-+#ifdef OCTASIC_DEBUG
-+ printk(KERN_DEBUG "Echo can on channel %d set to %d\n", channel, mode);
-+#endif
-+ vpm450m->ecmode[channel] = mode;
-+ }
-+ kfree(modify);
-+}
-+
-+void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
-+{
-+ tOCT6100_CHANNEL_MODIFY *modify;
-+ UINT32 ulResult;
-+
-+ if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
-+ pr_err("Channel out of bounds in %s\n", __func__);
-+ return;
-+ }
-+
-+ modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL);
-+ if (!modify) {
-+ printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setdtmf!\n");
-+ return;
-+ }
-+ Oct6100ChannelModifyDef(modify);
-+ modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel];
-+ if (mute) {
-+ vpm450m->chanflags[channel] |= FLAG_MUTE;
-+ modify->VqeConfig.fDtmfToneRemoval = TRUE;
-+ } else {
-+ vpm450m->chanflags[channel] &= ~FLAG_MUTE;
-+ modify->VqeConfig.fDtmfToneRemoval = FALSE;
-+ }
-+ if (detect)
-+ vpm450m->chanflags[channel] |= FLAG_DTMF;
-+ else
-+ vpm450m->chanflags[channel] &= ~FLAG_DTMF;
-+ if (vpm450m->chanflags[channel] & (FLAG_DTMF|FLAG_MUTE)) {
-+ if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) {
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE);
-+ }
-+ } else {
-+ if (!(vpm450m->chanflags[channel] & FLAG_ECHO))
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL);
-+ }
-+
-+ ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify);
-+ if (ulResult != GENERIC_OK) {
-+ printk(KERN_NOTICE "Failed to apply dtmf mute changes on channel %d!\n", channel);
-+ }
-+/* printk(KERN_DEBUG "VPM450m: Setting DTMF on channel %d: %s / %s\n", channel, (detect ? "DETECT" : "NO DETECT"), (mute ? "MUTE" : "NO MUTE")); */
-+ kfree(modify);
-+}
-+
-+void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen)
-+{
-+ if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
-+ pr_err("Channel out of bounds in %s\n", __func__);
-+ return;
-+ }
-+
-+ if (eclen) {
-+ vpm450m->chanflags[channel] |= FLAG_ECHO;
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_NORMAL);
-+ } else {
-+ vpm450m->chanflags[channel] &= ~FLAG_ECHO;
-+ if (vpm450m->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) {
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE);
-+ } else
-+ vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL);
-+ }
-+/* printk(KERN_DEBUG "VPM450m: Setting EC on channel %d to %d\n", channel, eclen); */
-+}
-+
-+int vpm450m_checkirq(struct vpm450m *vpm450m)
-+{
-+ tOCT6100_INTERRUPT_FLAGS InterruptFlags;
-+
-+ Oct6100InterruptServiceRoutineDef(&InterruptFlags);
-+ Oct6100InterruptServiceRoutine(vpm450m->pApiInstance, &InterruptFlags);
-+
-+ return InterruptFlags.fToneEventsPending ? 1 : 0;
-+}
-+
-+int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start)
-+{
-+ tOCT6100_TONE_EVENT tonefound;
-+ tOCT6100_EVENT_GET_TONE tonesearch;
-+
-+ Oct6100EventGetToneDef(&tonesearch);
-+ tonesearch.pToneEvent = &tonefound;
-+ tonesearch.ulMaxToneEvent = 1;
-+ Oct6100EventGetTone(vpm450m->pApiInstance, &tonesearch);
-+ if (tonesearch.ulNumValidToneEvent) {
-+ if (channel)
-+ *channel = tonefound.ulUserChanId;
-+ if (tone) {
-+ switch(tonefound.ulToneDetected) {
-+ case SOUT_DTMF_1:
-+ *tone = '1';
-+ break;
-+ case SOUT_DTMF_2:
-+ *tone = '2';
-+ break;
-+ case SOUT_DTMF_3:
-+ *tone = '3';
-+ break;
-+ case SOUT_DTMF_A:
-+ *tone = 'A';
-+ break;
-+ case SOUT_DTMF_4:
-+ *tone = '4';
-+ break;
-+ case SOUT_DTMF_5:
-+ *tone = '5';
-+ break;
-+ case SOUT_DTMF_6:
-+ *tone = '6';
-+ break;
-+ case SOUT_DTMF_B:
-+ *tone = 'B';
-+ break;
-+ case SOUT_DTMF_7:
-+ *tone = '7';
-+ break;
-+ case SOUT_DTMF_8:
-+ *tone = '8';
-+ break;
-+ case SOUT_DTMF_9:
-+ *tone = '9';
-+ break;
-+ case SOUT_DTMF_C:
-+ *tone = 'C';
-+ break;
-+ case SOUT_DTMF_STAR:
-+ *tone = '*';
-+ break;
-+ case SOUT_DTMF_0:
-+ *tone = '0';
-+ break;
-+ case SOUT_DTMF_POUND:
-+ *tone = '#';
-+ break;
-+ case SOUT_DTMF_D:
-+ *tone = 'D';
-+ break;
-+ case SOUT_G168_1100GB_ON:
-+ *tone = 'f';
-+ break;
-+ default:
-+#ifdef OCTASIC_DEBUG
-+ printk(KERN_DEBUG "Unknown tone value %08x\n", tonefound.ulToneDetected);
-+#endif
-+ *tone = 'u';
-+ break;
-+ }
-+ }
-+ if (start)
-+ *start = (tonefound.ulEventType == cOCT6100_TONE_PRESENT);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+unsigned int get_vpm450m_capacity(struct device *device)
-+{
-+ 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.ulMemoryType = cOCT6100_MEM_TYPE_DDR;
-+ CapacityPins.fEnableMemClkOut = TRUE;
-+ CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
-+
-+ ulResult = Oct6100ApiGetCapacityPins(&CapacityPins);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk(KERN_DEBUG "Failed to get chip capacity, code %08x!\n", ulResult);
-+ return 0;
-+ }
-+
-+ return CapacityPins.ulCapacityValue;
-+}
-+
-+struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
-+ int numspans, const struct firmware *firmware)
-+{
-+ tOCT6100_CHIP_OPEN *ChipOpen;
-+ tOCT6100_GET_INSTANCE_SIZE InstanceSize;
-+ tOCT6100_CHANNEL_OPEN *ChannelOpen;
-+ UINT32 ulResult;
-+ const unsigned int mask = (8 == numspans) ? 0x7 : 0x3;
-+ unsigned int sout_stream, rout_stream;
-+ struct vpm450m *vpm450m;
-+ int x,y,law;
-+
-+ if (!(vpm450m = kmalloc(sizeof(struct vpm450m), GFP_KERNEL)))
-+ 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);
-+ return NULL;
-+ }
-+
-+ memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN));
-+
-+ if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) {
-+ kfree(vpm450m);
-+ kfree(ChipOpen);
-+ return NULL;
-+ }
-+
-+ memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN));
-+
-+ for (x = 0; x < ARRAY_SIZE(vpm450m->ecmode); x++)
-+ vpm450m->ecmode[x] = -1;
-+
-+ vpm450m->numchans = numspans * 32;
-+ printk(KERN_INFO "VPM450: echo cancellation for %d channels\n", vpm450m->numchans);
-+
-+ Oct6100ChipOpenDef(ChipOpen);
-+
-+ /* Setup Chip Open Parameters */
-+ ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;
-+ Oct6100GetInstanceSizeDef(&InstanceSize);
-+
-+ ChipOpen->pProcessContext = &vpm450m->context;
-+
-+ ChipOpen->pbyImageFile = firmware->data;
-+ ChipOpen->ulImageSize = firmware->size;
-+ ChipOpen->fEnableMemClkOut = TRUE;
-+ ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
-+ ChipOpen->ulMaxChannels = vpm450m->numchans;
-+ ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
-+ ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB;
-+ ChipOpen->ulNumMemoryChips = 1;
-+ ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ;
-+ ChipOpen->ulMaxFlexibleConfParticipants = 0;
-+ ChipOpen->ulMaxConfBridges = 0;
-+ ChipOpen->ulMaxRemoteDebugSessions = 0;
-+ ChipOpen->fEnableChannelRecording = FALSE;
-+ ChipOpen->ulSoftToneEventsBufSize = 64;
-+
-+ if (vpm450m->numchans <= 128) {
-+ ChipOpen->ulMaxTdmStreams = 4;
-+ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
-+ } else {
-+ ChipOpen->ulMaxTdmStreams = 32;
-+ ChipOpen->fEnableFastH100Mode = TRUE;
-+ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_RISING_EDGE;
-+ }
-+
-+#if 0
-+ ChipOpen->fEnableAcousticEcho = TRUE;
-+#endif
-+
-+ ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk(KERN_NOTICE "Failed to get instance size, code %08x!\n", ulResult);
-+ kfree(vpm450m);
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return NULL;
-+ }
-+
-+ vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize);
-+ if (!vpm450m->pApiInstance) {
-+ printk(KERN_NOTICE "Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize);
-+ kfree(vpm450m);
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return NULL;
-+ }
-+
-+ ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk(KERN_NOTICE "Failed to open chip, code %08x!\n", ulResult);
-+ vfree(vpm450m->pApiInstance);
-+ kfree(vpm450m);
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return NULL;
-+ }
-+
-+ sout_stream = (8 == numspans) ? 29 : 2;
-+ rout_stream = (8 == numspans) ? 24 : 3;
-+
-+ for (x = 0; x < ((8 == numspans) ? 256 : 128); x++) {
-+ /* execute this loop always on 4 span cards but
-+ * on 2 span cards only execute for the channels related to our spans */
-+ if (( numspans > 2) || ((x & 0x03) <numspans)) { /*allo: 1port support*/
-+ /* span timeslots are interleaved 12341234...
-+ * therefore, the lower 2 bits tell us which span this
-+ * timeslot/channel
-+ */
-+ if (isalaw[x & mask]) {
-+ law = cOCT6100_PCM_A_LAW;
-+ vpm450m->chanflags[x] |= FLAG_ALAW;
-+ } else {
-+ law = cOCT6100_PCM_U_LAW;
-+ vpm450m->chanflags[x] &= ~(FLAG_ALAW);
-+ }
-+ Oct6100ChannelOpenDef(ChannelOpen);
-+ ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x];
-+ ChannelOpen->ulUserChanId = x;
-+ ChannelOpen->TdmConfig.ulRinPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulRinStream = 0;
-+ ChannelOpen->TdmConfig.ulRinTimeslot = x;
-+ ChannelOpen->TdmConfig.ulSinPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulSinStream = 1;
-+ ChannelOpen->TdmConfig.ulSinTimeslot = x;
-+ ChannelOpen->TdmConfig.ulSoutPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulSoutStream = sout_stream;
-+ ChannelOpen->TdmConfig.ulSoutTimeslot = x;
-+#if 1
-+ ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulRoutStream = rout_stream;
-+ ChannelOpen->TdmConfig.ulRoutTimeslot = x;
-+#endif
-+ ChannelOpen->VqeConfig.fEnableNlp = TRUE;
-+ ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
-+ ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
-+
-+ ChannelOpen->fEnableToneDisabler = TRUE;
-+ ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL;
-+
-+ ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen);
-+ if (ulResult != GENERIC_OK) {
-+ printk(KERN_NOTICE "Failed to open channel %d %x!\n", x, ulResult);
-+ continue;
-+ }
-+ for (y = 0; y < ARRAY_SIZE(tones); y++) {
-+ tOCT6100_TONE_DETECTION_ENABLE enable;
-+ Oct6100ToneDetectionEnableDef(&enable);
-+ enable.ulChannelHndl = vpm450m->aulEchoChanHndl[x];
-+ enable.ulToneNumber = tones[y];
-+ if (Oct6100ToneDetectionEnable(vpm450m->pApiInstance, &enable) != GENERIC_OK)
-+ printk(KERN_NOTICE "Failed to enable tone detection on channel %d for tone %d!\n", x, y);
-+ }
-+ }
-+ }
-+
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return vpm450m;
-+}
-+
-+void release_vpm450m(struct vpm450m *vpm450m)
-+{
-+ UINT32 ulResult;
-+ tOCT6100_CHIP_CLOSE ChipClose;
-+
-+ Oct6100ChipCloseDef(&ChipClose);
-+ ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk(KERN_NOTICE "Failed to close chip, code %08x!\n", ulResult);
-+ }
-+ vfree(vpm450m->pApiInstance);
-+ kfree(vpm450m);
-+}
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/vpm450m.h dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/vpm450m.h
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/vpm450m.h 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/vpm450m.h 2015-02-10 15:01:15.889462151 +0100
-@@ -0,0 +1,49 @@
-+/*
-+ * Copyright (C) 2005-2006 Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ *
-+ * 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 _VPM450M_H
-+#define _VPM450M_H
-+
-+#include <linux/firmware.h>
-+
-+struct t4;
-+struct vpm450m;
-+
-+/* From driver */
-+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);
-+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);
-+int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start);
-+void release_vpm450m(struct vpm450m *instance);
-+void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
-+ int channel, bool alaw);
-+
-+extern int debug;
-+
-+#endif
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/wct4xxp-diag.c dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/wct4xxp-diag.c
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/wct4xxp-diag.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/wct4xxp-diag.c 2015-02-10 15:01:15.892795252 +0100
-@@ -0,0 +1,427 @@
-+/*
-+ * 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 <fcntl.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <sys/ioctl.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <dahdi/user.h>
-+#include "wct4xxp.h"
-+
-+struct t4_reg_def {
-+ int reg;
-+ char *name;
-+ int global;
-+};
-+static struct t4_reg_def xreginfo[] = {
-+ { 0x00, "RDADDR" },
-+ { 0x01, "WRADDR" },
-+ { 0x02, "COUNT" },
-+ { 0x03, "DMACTRL" },
-+ { 0x04, "WCINTR" },
-+ { 0x06, "VERSION" },
-+ { 0x07, "LEDS" },
-+ { 0x08, "GPIOCTL" },
-+ { 0x09, "GPIO" },
-+ { 0x0A, "LADDR" },
-+ { 0x0b, "LDATA" },
-+};
-+
-+static struct t4_reg_def reginfo[] = {
-+ { 0x00, "XFIFO" },
-+ { 0x01, "XFIFO" },
-+ { 0x02, "CMDR" },
-+ { 0x03, "MODE" },
-+ { 0x04, "RAH1" },
-+ { 0x05, "RAH2" },
-+ { 0x06, "RAL1" },
-+ { 0x07, "RAL2" },
-+ { 0x08, "IPC", 1 },
-+ { 0x09, "CCR1" },
-+ { 0x0a, "CCR2" },
-+ { 0x0c, "RTR1" },
-+ { 0x0d, "RTR2" },
-+ { 0x0e, "RTR3" },
-+ { 0x0f, "RTR4" },
-+ { 0x10, "TTR1" },
-+ { 0x11, "TTR2" },
-+ { 0x12, "TTR3" },
-+ { 0x13, "TTR4" },
-+ { 0x14, "IMR0" },
-+ { 0x15, "IMR1" },
-+ { 0x16, "IMR2" },
-+ { 0x17, "IMR3" },
-+ { 0x18, "IMR4" },
-+ { 0x1b, "IERR" },
-+ { 0x1c, "FMR0" },
-+ { 0x1d, "FMR1" },
-+ { 0x1e, "FMR2" },
-+ { 0x1f, "LOOP" },
-+ { 0x20, "XSW" },
-+ { 0x21, "XSP" },
-+ { 0x22, "XC0" },
-+ { 0x23, "XC1" },
-+ { 0x24, "RC0" },
-+ { 0x25, "RC1" },
-+ { 0x26, "XPM0" },
-+ { 0x27, "XPM1" },
-+ { 0x28, "XPM2" },
-+ { 0x29, "TSWM" },
-+ { 0x2b, "IDLE" },
-+ { 0x2c, "XSA4" },
-+ { 0x2d, "XSA5" },
-+ { 0x2e, "XSA6" },
-+ { 0x2f, "XSA7" },
-+ { 0x30, "XSA8" },
-+ { 0x31, "FMR3" },
-+ { 0x32, "ICB1" },
-+ { 0x33, "ICB2" },
-+ { 0x34, "ICB3" },
-+ { 0x35, "ICB4" },
-+ { 0x36, "LIM0" },
-+ { 0x37, "LIM1" },
-+ { 0x38, "PCD" },
-+ { 0x39, "PCR" },
-+ { 0x3a, "LIM2" },
-+ { 0x3b, "LCR1" },
-+ { 0x3c, "LCR2" },
-+ { 0x3d, "LCR3" },
-+ { 0x3e, "SIC1" },
-+ { 0x3f, "SIC2" },
-+ { 0x40, "SIC3" },
-+ { 0x44, "CMR1" },
-+ { 0x45, "CMR2" },
-+ { 0x46, "GCR" },
-+ { 0x47, "ESM" },
-+ { 0x60, "DEC" },
-+ { 0x70, "XS1" },
-+ { 0x71, "XS2" },
-+ { 0x72, "XS3" },
-+ { 0x73, "XS4" },
-+ { 0x74, "XS5" },
-+ { 0x75, "XS6" },
-+ { 0x76, "XS7" },
-+ { 0x77, "XS8" },
-+ { 0x78, "XS9" },
-+ { 0x79, "XS10" },
-+ { 0x7a, "XS11" },
-+ { 0x7b, "XS12" },
-+ { 0x7c, "XS13" },
-+ { 0x7d, "XS14" },
-+ { 0x7e, "XS15" },
-+ { 0x7f, "XS16" },
-+ { 0x80, "PC1" },
-+ { 0x81, "PC2" },
-+ { 0x82, "PC3" },
-+ { 0x83, "PC4" },
-+ { 0x84, "PC5" },
-+ { 0x85, "GPC1", 1 },
-+ { 0x87, "CMDR2" },
-+ { 0x8d, "CCR5" },
-+ { 0x92, "GCM1", 1 },
-+ { 0x93, "GCM2", 1 },
-+ { 0x94, "GCM3", 1 },
-+ { 0x95, "GCM4", 1 },
-+ { 0x96, "GCM5", 1 },
-+ { 0x97, "GCM6", 1 },
-+ { 0x98, "GCM7", 1 },
-+ { 0x99, "GCM8", 1 },
-+ { 0xa0, "TSEO" },
-+ { 0xa1, "TSBS1" },
-+ { 0xa8, "TPC0" },
-+};
-+
-+static struct t4_reg_def t1_reginfo[] = {
-+ { 0x00, "XFIFO" },
-+ { 0x01, "XFIFO" },
-+ { 0x02, "CMDR" },
-+ { 0x03, "MODE" },
-+ { 0x04, "RAH1" },
-+ { 0x05, "RAH2" },
-+ { 0x06, "RAL1" },
-+ { 0x07, "RAL2" },
-+ { 0x08, "IPC", 1 },
-+ { 0x09, "CCR1" },
-+ { 0x0a, "CCR2" },
-+ { 0x0c, "RTR1" },
-+ { 0x0d, "RTR2" },
-+ { 0x0e, "RTR3" },
-+ { 0x0f, "RTR4" },
-+ { 0x10, "TTR1" },
-+ { 0x11, "TTR2" },
-+ { 0x12, "TTR3" },
-+ { 0x13, "TTR4" },
-+ { 0x14, "IMR0" },
-+ { 0x15, "IMR1" },
-+ { 0x16, "IMR2" },
-+ { 0x17, "IMR3" },
-+ { 0x18, "IMR4" },
-+ { 0x1b, "IERR" },
-+ { 0x1c, "FMR0" },
-+ { 0x1d, "FMR1" },
-+ { 0x1e, "FMR2" },
-+ { 0x1f, "LOOP" },
-+ { 0x20, "FMR4" },
-+ { 0x21, "FMR5" },
-+ { 0x22, "XC0" },
-+ { 0x23, "XC1" },
-+ { 0x24, "RC0" },
-+ { 0x25, "RC1" },
-+ { 0x26, "XPM0" },
-+ { 0x27, "XPM1" },
-+ { 0x28, "XPM2" },
-+ { 0x2b, "IDLE" },
-+ { 0x2c, "XDL1" },
-+ { 0x2d, "XDL2" },
-+ { 0x2e, "XDL3" },
-+ { 0x2f, "CCB1" },
-+ { 0x30, "CCB2" },
-+ { 0x31, "CCB3" },
-+ { 0x32, "ICB1" },
-+ { 0x33, "ICB2" },
-+ { 0x34, "ICB3" },
-+ { 0x36, "LIM0" },
-+ { 0x37, "LIM1" },
-+ { 0x38, "PCD" },
-+ { 0x39, "PCR" },
-+ { 0x3a, "LIM2" },
-+ { 0x3b, "LCR1" },
-+ { 0x3c, "LCR2" },
-+ { 0x3d, "LCR3" },
-+ { 0x3e, "SIC1" },
-+ { 0x3f, "SIC2" },
-+ { 0x40, "SIC3" },
-+ { 0x44, "CMR1" },
-+ { 0x45, "CMR2" },
-+ { 0x46, "GCR" },
-+ { 0x47, "ESM" },
-+ { 0x60, "DEC" },
-+ { 0x70, "XS1" },
-+ { 0x71, "XS2" },
-+ { 0x72, "XS3" },
-+ { 0x73, "XS4" },
-+ { 0x74, "XS5" },
-+ { 0x75, "XS6" },
-+ { 0x76, "XS7" },
-+ { 0x77, "XS8" },
-+ { 0x78, "XS9" },
-+ { 0x79, "XS10" },
-+ { 0x7a, "XS11" },
-+ { 0x7b, "XS12" },
-+ { 0x80, "PC1" },
-+ { 0x81, "PC2" },
-+ { 0x82, "PC3" },
-+ { 0x83, "PC4" },
-+ { 0x84, "PC5" },
-+ { 0x85, "GPC1", 1 },
-+ { 0x87, "CMDR2" },
-+ { 0x8d, "CCR5" },
-+ { 0x92, "GCM1", 1 },
-+ { 0x93, "GCM2", 1 },
-+ { 0x94, "GCM3", 1 },
-+ { 0x95, "GCM4", 1 },
-+ { 0x96, "GCM5", 1 },
-+ { 0x97, "GCM6", 1 },
-+ { 0x98, "GCM7", 1 },
-+ { 0x99, "GCM8", 1 },
-+ { 0xa0, "TSEO" },
-+ { 0xa1, "TSBS1" },
-+ { 0xa8, "TPC0" },
-+};
-+
-+static struct t4_reg_def t1_sreginfo[] = {
-+ { 0x00, "RFIFO" },
-+ { 0x01, "RFIFO" },
-+ { 0x49, "RBD" },
-+ { 0x4a, "VSTR", 1 },
-+ { 0x4b, "RES" },
-+ { 0x4c, "FRS0" },
-+ { 0x4d, "FRS1" },
-+ { 0x4e, "FRS2" },
-+ { 0x4f, "Old FRS1" },
-+ { 0x50, "FECL" },
-+ { 0x51, "FECH" },
-+ { 0x52, "CVCL" },
-+ { 0x53, "CVCH" },
-+ { 0x54, "CECL" },
-+ { 0x55, "CECH" },
-+ { 0x56, "EBCL" },
-+ { 0x57, "EBCH" },
-+ { 0x58, "BECL" },
-+ { 0x59, "BECH" },
-+ { 0x5a, "COEC" },
-+ { 0x5c, "RDL1" },
-+ { 0x5d, "RDL2" },
-+ { 0x5e, "RDL3" },
-+ { 0x62, "RSP1" },
-+ { 0x63, "RSP2" },
-+ { 0x64, "SIS" },
-+ { 0x65, "RSIS" },
-+ { 0x66, "RBCL" },
-+ { 0x67, "RBCH" },
-+ { 0x68, "ISR0" },
-+ { 0x69, "ISR1" },
-+ { 0x6a, "ISR2" },
-+ { 0x6b, "ISR3" },
-+ { 0x6c, "ISR4" },
-+ { 0x6e, "GIS" },
-+ { 0x6f, "CIS", 1 },
-+ { 0x70, "RS1" },
-+ { 0x71, "RS2" },
-+ { 0x72, "RS3" },
-+ { 0x73, "RS4" },
-+ { 0x74, "RS5" },
-+ { 0x75, "RS6" },
-+ { 0x76, "RS7" },
-+ { 0x77, "RS8" },
-+ { 0x78, "RS9" },
-+ { 0x79, "RS10" },
-+ { 0x7a, "RS11" },
-+ { 0x7b, "RS12" },
-+};
-+
-+static struct t4_reg_def sreginfo[] = {
-+ { 0x00, "RFIFO" },
-+ { 0x01, "RFIFO" },
-+ { 0x49, "RBD" },
-+ { 0x4a, "VSTR", 1 },
-+ { 0x4b, "RES" },
-+ { 0x4c, "FRS0" },
-+ { 0x4d, "FRS1" },
-+ { 0x4e, "RSW" },
-+ { 0x4f, "RSP" },
-+ { 0x50, "FECL" },
-+ { 0x51, "FECH" },
-+ { 0x52, "CVCL" },
-+ { 0x53, "CVCH" },
-+ { 0x54, "CEC1L" },
-+ { 0x55, "CEC1H" },
-+ { 0x56, "EBCL" },
-+ { 0x57, "EBCH" },
-+ { 0x58, "CEC2L" },
-+ { 0x59, "CEC2H" },
-+ { 0x5a, "CEC3L" },
-+ { 0x5b, "CEC3H" },
-+ { 0x5c, "RSA4" },
-+ { 0x5d, "RSA5" },
-+ { 0x5e, "RSA6" },
-+ { 0x5f, "RSA7" },
-+ { 0x60, "RSA8" },
-+ { 0x61, "RSA6S" },
-+ { 0x62, "RSP1" },
-+ { 0x63, "RSP2" },
-+ { 0x64, "SIS" },
-+ { 0x65, "RSIS" },
-+ { 0x66, "RBCL" },
-+ { 0x67, "RBCH" },
-+ { 0x68, "ISR0" },
-+ { 0x69, "ISR1" },
-+ { 0x6a, "ISR2" },
-+ { 0x6b, "ISR3" },
-+ { 0x6c, "ISR4" },
-+ { 0x6e, "GIS" },
-+ { 0x6f, "CIS", 1 },
-+ { 0x70, "RS1" },
-+ { 0x71, "RS2" },
-+ { 0x72, "RS3" },
-+ { 0x73, "RS4" },
-+ { 0x74, "RS5" },
-+ { 0x75, "RS6" },
-+ { 0x76, "RS7" },
-+ { 0x77, "RS8" },
-+ { 0x78, "RS9" },
-+ { 0x79, "RS10" },
-+ { 0x7a, "RS11" },
-+ { 0x7b, "RS12" },
-+ { 0x7c, "RS13" },
-+ { 0x7d, "RS14" },
-+ { 0x7e, "RS15" },
-+ { 0x7f, "RS16" },
-+};
-+
-+static char *tobin(int x)
-+{
-+ static char s[9] = "";
-+ int y,z=0;
-+ for (y=7;y>=0;y--) {
-+ if (x & (1 << y))
-+ s[z++] = '1';
-+ else
-+ s[z++] = '0';
-+ }
-+ s[z] = '\0';
-+ return s;
-+}
-+
-+static char *tobin32(unsigned int x)
-+{
-+ static char s[33] = "";
-+ int y,z=0;
-+ for (y=31;y>=0;y--) {
-+ if (x & (1 << y))
-+ s[z++] = '1';
-+ else
-+ s[z++] = '0';
-+ }
-+ s[z] = '\0';
-+ return s;
-+}
-+
-+int main(int argc, char *argv[])
-+{
-+ int fd;
-+ int x;
-+ char fn[256];
-+ struct t4_regs regs;
-+ if ((argc < 2) || ((*(argv[1]) != '/') && !atoi(argv[1]))) {
-+ fprintf(stderr, "Usage: wct4xxp-diag <channel>\n");
-+ exit(1);
-+ }
-+ if (*(argv[1]) == '/')
-+ dahdi_copy_string(fn, argv[1], sizeof(fn));
-+ else
-+ snprintf(fn, sizeof(fn), "/dev/dahdi/%d", atoi(argv[1]));
-+ fd = open(fn, O_RDWR);
-+ if (fd <0) {
-+ fprintf(stderr, "Unable to open '%s': %s\n", fn, strerror(errno));
-+ exit(1);
-+ }
-+ if (ioctl(fd, WCT4_GET_REGS, &regs)) {
-+ fprintf(stderr, "Unable to get registers: %s\n", strerror(errno));
-+ exit(1);
-+ }
-+ printf("PCI Registers:\n");
-+ for (x=0;x<sizeof(xreginfo) / sizeof(xreginfo[0]);x++) {
-+ fprintf(stdout, "%s (%02x): %08x (%s)\n", xreginfo[x].name, xreginfo[x].reg, regs.pci[xreginfo[x].reg], tobin32(regs.pci[xreginfo[x].reg]));
-+ }
-+ printf("\nE1 Control Registers:\n");
-+ for (x=0;x<sizeof(reginfo) / sizeof(reginfo[0]);x++) {
-+ fprintf(stdout, "%s (%02x): %02x (%s)\n", reginfo[x].name, reginfo[x].reg, regs.regs[reginfo[x].reg], tobin(regs.regs[reginfo[x].reg]));
-+ }
-+ printf("\nE1 Status Registers:\n");
-+ for (x=0;x<sizeof(sreginfo) / sizeof(sreginfo[0]);x++) {
-+ fprintf(stdout, "%s (%02x): %02x (%s)\n", sreginfo[x].name, sreginfo[x].reg, regs.regs[sreginfo[x].reg], tobin(regs.regs[sreginfo[x].reg]));
-+ }
-+ printf("\nT1 Control Registers:\n");
-+ for (x=0;x<sizeof(t1_reginfo) / sizeof(t1_reginfo[0]);x++) {
-+ fprintf(stdout, "%s (%02x): %02x (%s)\n", t1_reginfo[x].name, t1_reginfo[x].reg, regs.regs[t1_reginfo[x].reg], tobin(regs.regs[t1_reginfo[x].reg]));
-+ }
-+ printf("\nT1 Status Registers:\n");
-+ for (x=0;x<sizeof(t1_sreginfo) / sizeof(t1_sreginfo[0]);x++) {
-+ fprintf(stdout, "%s (%02x): %02x (%s)\n", t1_sreginfo[x].name, t1_sreginfo[x].reg, regs.regs[t1_sreginfo[x].reg], tobin(regs.regs[t1_sreginfo[x].reg]));
-+ }
-+ exit(0);
-+}
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/wct4xxp.h dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/wct4xxp.h
---- dahdi-linux-2.10.0.1/drivers/dahdi/allo4xxp/wct4xxp.h 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/allo4xxp/wct4xxp.h 2015-02-10 15:01:15.892795252 +0100
-@@ -0,0 +1,144 @@
-+/*
-+ * Wildcard T400P FXS Interface Driver for DAHDI Telephony interface
-+ *
-+ * Written by Mark Spencer <markster@linux-support.net>
-+ *
-+ * Copyright (C) 2001-2010, 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/ioctl.h>
-+
-+#define FRMR_TTR_BASE 0x10
-+#define FRMR_RTR_BASE 0x0c
-+#define FRMR_TSEO 0xa0
-+#define FRMR_TSBS1 0xa1
-+#define FRMR_CCR1 0x09
-+#define FRMR_CCR1_ITF 0x08
-+#define FRMR_CCR1_EITS 0x10
-+#define FRMR_CCR2 0x0a
-+#define FRMR_CCR2_RCRC 0x04
-+#define FRMR_CCR2_RADD 0x10
-+#define FRMR_MODE 0x03
-+#define FRMR_MODE_NO_ADDR_CMP 0x80
-+#define FRMR_MODE_SS7 0x20
-+#define FRMR_MODE_HRAC 0x08
-+#define FRMR_IMR0 0x14
-+#define FRMR_IMR0_RME 0x80
-+#define FRMR_IMR0_RPF 0x01
-+#define FRMR_IMR1 0x15
-+#define FRMR_IMR1_ALLS 0x20
-+#define FRMR_IMR1_XDU 0x10
-+#define FRMR_IMR1_XPR 0x01
-+#define FRMR_XC0 0x22
-+#define FRMR_XC1 0x23
-+#define FRMR_RC0 0x24
-+#define FRMR_RC1 0x25
-+#define FRMR_SIC1 0x3e
-+#define FRMR_SIC2 0x3f
-+#define FRMR_SIC3 0x40
-+#define FRMR_CMR1 0x44
-+#define FRMR_CMR2 0x45
-+/* OctalFALC Only */
-+#define FRMR_CMR4 0x41
-+#define FRMR_CMR5 0x42
-+#define FRMR_CMR6 0x43
-+#define FRMR_GPC2 0x8a
-+/* End Octal */
-+#define FRMR_GCR 0x46
-+#define FRMR_ISR0 0x68
-+#define FRMR_ISR0_RME 0x80
-+#define FRMR_ISR0_RPF 0x01
-+#define FRMR_ISR1 0x69
-+#define FRMR_ISR1_ALLS 0x20
-+#define FRMR_ISR1_XDU 0x10
-+#define FRMR_ISR1_XPR 0x01
-+#define FRMR_ISR2 0x6a
-+#define FRMR_ISR3 0x6b
-+#define FRMR_ISR4 0x6c
-+#define FRMR_GIS 0x6e
-+#define FRMR_GIS_ISR0 0x01
-+#define FRMR_GIS_ISR1 0x02
-+#define FRMR_GIS_ISR2 0x04
-+#define FRMR_GIS_ISR3 0x08
-+#define FRMR_GIS_ISR4 0x10
-+#define FRMR_CIS 0x6f
-+#define FRMR_CIS_GIS1 0x01
-+#define FRMR_CIS_GIS2 0x02
-+#define FRMR_CIS_GIS3 0x04
-+#define FRMR_CIS_GIS4 0x08
-+
-+/* CIS - Octal falc bits */
-+#define FRMR_CIS_GIS5 0x10
-+#define FRMR_CIS_GIS6 0x20
-+#define FRMR_CIS_GIS7 0x40
-+#define FRMR_CIS_GIS8 0x80
-+
-+#define FRMR_CMDR 0x02
-+#define FRMR_CMDR_SRES 0x01
-+#define FRMR_CMDR_XRES 0x10
-+#define FRMR_CMDR_RMC 0x80
-+#define FRMR_CMDR_XTF 0x04
-+#define FRMR_CMDR_XHF 0x08
-+#define FRMR_CMDR_XME 0x02
-+#define FRMR_RSIS 0x65
-+#define FRMR_RSIS_VFR 0x80
-+#define FRMR_RSIS_RDO 0x40
-+#define FRMR_RSIS_CRC16 0x20
-+#define FRMR_RSIS_RAB 0x10
-+#define FRMR_RBCL 0x66
-+#define FRMR_RBCL_MAX_SIZE 0x1f
-+#define FRMR_RBCH 0x67
-+#define FRMR_RXFIFO 0x00
-+#define FRMR_SIS 0x64
-+#define FRMR_SIS_XFW 0x40
-+#define FRMR_TXFIFO 0x00
-+
-+#define FRS0 0x4c
-+#define FRS0_LOS (1<<7)
-+#define FRS0_LFA (1<<5)
-+#define FRS0_LMFA (1<<1)
-+
-+#define FRS1 0x4d
-+#define FRS1_XLS (1<<1)
-+#define FRS1_XLO (1<<0)
-+
-+#define NUM_REGS 0xa9
-+#define NUM_PCI 12
-+
-+struct t4_regs {
-+ unsigned int pci[NUM_PCI];
-+ unsigned char regs[NUM_REGS];
-+};
-+
-+struct t4_reg {
-+ unsigned int reg;
-+ unsigned int val;
-+};
-+
-+#define T4_CHECK_VPM 0
-+#define T4_LOADING_FW 1
-+#define T4_STOP_DMA 2
-+#define T4_CHECK_TIMING 3
-+#define T4_CHANGE_LATENCY 4
-+#define T4_IGNORE_LATENCY 5
-+
-+#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
-+#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
-+#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
-+
-diff -Nur dahdi-linux-2.10.0.1/drivers/dahdi/firmware/Makefile dahdi-linux-2.10.0.1-allo/drivers/dahdi/firmware/Makefile
---- dahdi-linux-2.10.0.1/drivers/dahdi/firmware/Makefile 2014-09-22 20:40:19.000000000 +0200
-+++ dahdi-linux-2.10.0.1-allo/drivers/dahdi/firmware/Makefile 2015-02-10 15:01:15.892795252 +0100
-@@ -41,10 +41,11 @@
- A4B_VERSION:=b0019
-
- FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
-+FIRMWARE_URL_ALLO:=http://www.allo.com/firmware/pri-card-second-gen
-
- 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 FIRMWARE-TE436
-+ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435 FIRMWARE-TE436 FIRMWARE-allo-1PPCIe FIRMWARE-allo-2PPCIe FIRMWARE-allo-4PPCI FIRMWARE-allo-4PPCIe FIRMWARE-allo-8PPCIe
-
- # 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
-@@ -69,6 +70,12 @@
- 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)
-+FIRMWARE:=$(FIRMWARE:FIRMWARE-allo-1PPCIe=allo-dahdi-fw-2aCP1e.tar.gz)
-+FIRMWARE:=$(FIRMWARE:FIRMWARE-allo-2PPCIe=allo-dahdi-fw-2aCP2e.tar.gz)
-+FIRMWARE:=$(FIRMWARE:FIRMWARE-allo-4PPCI=allo-dahdi-fw-2aCP4.tar.gz)
-+FIRMWARE:=$(FIRMWARE:FIRMWARE-allo-4PPCIe=allo-dahdi-fw-2aCP4e.tar.gz)
-+FIRMWARE:=$(FIRMWARE:FIRMWARE-allo-8PPCIe=allo-dahdi-fw-2aCP8e.tar.gz)
-+
-
- FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
-
-@@ -100,6 +107,9 @@
- rm -f dahdi-fw-*.tar.gz
- rm -f dahdi-fwload-*.tar.gz
- rm -f make_firmware_object
-+ rm -f allo-dahdi-fw-*.bin
-+ rm -f allo-dahdi-fw-*.tar.gz
-+
-
- # Clean up anything we built
- clean:
-@@ -113,6 +123,15 @@
- if test ! -f $@; then exit 1; fi; \
- fi
-
-+allo-dahdi-fw%.tar.gz:
-+ @if ( [ "$(HOTPLUG_FIRMWARE)" = "no" ] ) || ( [ -d $(DESTDIR)/usr/lib/hotplug/firmware ] && ! [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.$(subst .tar.gz,,$*) ] ) || ( [ -d $(DESTDIR)/lib/firmware ] && ! [ -f $(DESTDIR)/lib/firmware/.$(subst .tar.gz,,$*) ] ); then \
-+ echo "Attempting to download $@"; \
-+ if test ! -f $@; then $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL_ALLO)/$@; fi; \
-+ if test ! -f $@; then exit 1; fi; \
-+ (cat $@ | gzip -d | tar --no-same-owner -xf -) \
-+ fi
-+
-+
- firmware-loaders: $(FWLOADERS)
-
- .PHONY: dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
-@@ -145,16 +164,90 @@
- @$(call RUN_INST,dahdi-fw-a8b,$(A8B_VERSION))
- @$(call RUN_INST,dahdi-fw-a4a,$(A4A_VERSION))
- @$(call RUN_INST,dahdi-fw-a4b,$(A4B_VERSION))
-+######################ALLO#################################
-+ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP1e ] ) && ( [ -f $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP1e ] ); then echo "no"; else echo "yes"; fi),yes)
-+
-+ @echo "Installing ALLO firmwares to hotplug firmware directories"
-+ @install -m 644 allo-dahdi-fw-2aCP1e.bin $(DESTDIR)/usr/lib/hotplug/firmware
-+ @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP1e
-+ @touch $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP1e
-+ @install -m 644 allo-dahdi-fw-2aCP1e.bin $(DESTDIR)/lib/firmware
-+ @rm -rf $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP1e
-+ @touch $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP1e
-+else
-+ @echo "Firmware of ALLO card allo-dahdi-fw-2aCP1e.bin is already installed with required version"
-+endif
-+
-+
-+ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP2e ] ) && ( [ -f $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP2e ] ); then echo "no"; else echo "yes"; fi),yes)
-+
-+ @echo "Installing ALLO firmwares to hotplug firmware directories"
-+ @install -m 644 allo-dahdi-fw-2aCP2e.bin $(DESTDIR)/usr/lib/hotplug/firmware
-+ @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP2e
-+ @touch $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP2e
-+ @install -m 644 allo-dahdi-fw-2aCP2e.bin $(DESTDIR)/lib/firmware
-+ @rm -rf $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP2e
-+ @touch $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP2e
-+else
-+ @echo "Firmware of ALLO cards allo-dahdi-fw-2aCP2e.bin is already installed with required version"
-+endif
-+
-+
-+ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP4 ] ) && ( [ -f $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP4 ] ); then echo "no"; else echo "yes"; fi),yes)
-+
-+ @echo "Installing ALLO firmwares to hotplug firmware directories"
-+ @install -m 644 allo-dahdi-fw-2aCP4.bin $(DESTDIR)/usr/lib/hotplug/firmware
-+ @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP4
-+ @touch $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP4
-+ @install -m 644 allo-dahdi-fw-2aCP4.bin $(DESTDIR)/lib/firmware
-+ @rm -rf $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP4
-+ @touch $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP4
-+else
-+ @echo "Firmware of ALLO cards allo-dahdi-fw-2aCP4.bin is already installed with required version"
-+endif
-+
-+ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP4e ] ) && ( [ -f $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP4e ] ); then echo "no"; else echo "yes"; fi),yes)
-+
-+ @echo "Installing ALLO firmwares to hotplug firmware directories"
-+ @install -m 644 allo-dahdi-fw-2aCP4e.bin $(DESTDIR)/usr/lib/hotplug/firmware
-+ @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP4e
-+ @touch $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP4e
-+ @install -m 644 allo-dahdi-fw-2aCP4e.bin $(DESTDIR)/lib/firmware
-+ @rm -rf $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP4e
-+ @touch $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP4e
-+else
-+ @echo "Firmware of ALLO cards allo-dahdi-fw-2aCP4e.bin is already installed with required version"
-+endif
-+
-+
-+ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP8e ] ) && ( [ -f $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP8e ] ); then echo "no"; else echo "yes"; fi),yes)
-+
-+ @echo "Installing ALLO firmwares to hotplug firmware directories"
-+ @install -m 644 allo-dahdi-fw-2aCP8e.bin $(DESTDIR)/usr/lib/hotplug/firmware
-+ @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP8e*
-+ @touch $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw-2aCP8e
-+ @install -m 644 allo-dahdi-fw-2aCP8e.bin $(DESTDIR)/lib/firmware
-+ @rm -rf $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP8e*
-+ @touch $(DESTDIR)/lib/firmware/.allo-dahdi-fw-2aCP8e
-+else
-+ @echo "Firmware of ALLO cards allo-dahdi-fw-2aCP8e.bin is already installed with required version"
-+endif
-+
-+#########################END######################################
-
- # Uninstall any installed dahdi firmware images from hotplug firmware directories
- hotplug-uninstall:
- if [ -d $(DESTDIR)/usr/lib/hotplug/firmware ]; then \
- rm -f $(DESTDIR)/usr/lib/hotplug/firmware/dahdi-fw-*.bin; \
- rm -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw*; \
-+ rm -f $(DESTDIR)/usr/lib/hotplug/firmware/allo-dahdi-fw-*.bin; \
-+ rm -f $(DESTDIR)/usr/lib/hotplug/firmware/.allo-dahdi-fw*; \
- fi
- if [ -d $(DESTDIR)/lib/firmware ]; then \
- rm -f $(DESTDIR)/lib/firmware/dahdi-fw-*.bin; \
- rm -f $(DESTDIR)/lib/firmware/.dahdi-fw*; \
-+ rm -f $(DESTDIR)/lib/firmware/allo-dahdi-fw-*.bin; \
-+ rm -f $(DESTDIR)/lib/firmware/.allo-dahdi-fw*; \
- fi
-
- make_firmware_object: make_firmware_object.in ../dahdi-base.o
diff --git a/dahdi-linux-2.10.1-openvox-1.patch b/dahdi-linux-2.10.1-openvox-1.patch
deleted file mode 100644
index 4a8fcf98f89..00000000000
--- a/dahdi-linux-2.10.1-openvox-1.patch
+++ /dev/null
@@ -1,6228 +0,0 @@
---- dahdi-linux-2.10.0.1/drivers/dahdi/Kbuild 2014-09-22 20:40:19.000000000 +0200
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/Kbuild 2015-02-10 15:12:07.233961480 +0100
-@@ -14,6 +14,10 @@
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
-
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXD115) += opvxd115/
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXA1200) += opvxa1200/
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXA24XX) += opvxa24xx/
-+
- 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
- ifeq ($(HOTPLUG_FIRMWARE),yes)
---- dahdi-linux-2.10.0.1/drivers/dahdi/Kconfig 2014-09-22 20:40:19.000000000 +0200
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/Kconfig 2015-02-10 15:03:42.355884929 +0100
-@@ -291,4 +291,34 @@
-
- If unsure, say Y.
-
-+config DAHDI_OPVXD115
-+ tristate "OpenVox TE410P Quad-T1/E1 PCI"
-+ depends on DAHDI && PCI
-+ default DAHDI
-+ ---help---
-+ To compile this driver as a module, choose M here: the
-+ module will be called opvxd115.
-+
-+ If unsure, say Y.
-+
-+config DAHDI_OPVXA1200
-+ tristate "OpenVox A1200P FXS/FXO Interface Driver"
-+ depends on DAHDI && PCI
-+ default DAHDI
-+ ---help---
-+ To compile this driver as a module, choose M here: the
-+ module will be called opvxa1200.
-+
-+ If unsure, say Y.
-+
-+config DAHDI_OPVXA24XX
-+ tristate "OpenVox A24xx FXS/FXO Interface Driver"
-+ depends on DAHDI && PCI
-+ default DAHDI
-+ ---help---
-+ To compile this driver as a module, choose M here: the
-+ module will be called opvxa24xx.
-+
-+ If unsure, say Y.
-+
- source "drivers/dahdi/xpp/Kconfig"
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa1200/Kbuild 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa1200/Kbuild 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,19 @@
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXA1200) += opvxa1200.o
-+
-+EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
-+
-+opvxa1200-objs := base.o
-+
-+DAHDI_KERNEL_H_NAME:=kernel.h
-+DAHDI_KERNEL_H_PATH:=$(DAHDI_INCLUDE)/dahdi/$(DAHDI_KERNEL_H_NAME)
-+ifneq ($(DAHDI_KERNEL_H_PATH),)
-+ DAHDI_SPAN_MODULE:=$(shell if grep -C 5 "struct dahdi_span {" $(DAHDI_KERNEL_H_PATH) | grep -q "struct module \*owner"; then echo "yes"; else echo "no"; fi)
-+ DAHDI_SPAN_OPS:=$(shell if grep -q "struct dahdi_span_ops {" $(DAHDI_KERNEL_H_PATH); then echo "yes"; else echo "no"; fi)
-+ ifeq ($(DAHDI_SPAN_MODULE),yes)
-+ EXTRA_CFLAGS+=-DDAHDI_SPAN_MODULE
-+ else
-+ ifeq ($(DAHDI_SPAN_OPS),yes)
-+ EXTRA_CFLAGS+=-DDAHDI_SPAN_OPS
-+ endif
-+ endif
-+endif
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa1200/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa1200/Makefile 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,8 @@
-+ifdef KBUILD_EXTMOD
-+# We only get here on kernels 2.6.0-2.6.9 .
-+# For newer kernels, Kbuild will be included directly by the kernel
-+# build system.
-+include $(src)/Kbuild
-+
-+else
-+endif
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa1200/base.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa1200/base.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,3117 @@
-+/*
-+ * OpenVox A1200P FXS/FXO Interface Driver for DAHDI Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ *
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+/* Rev histroy
-+ *
-+ * Rev 0.10 initial version
-+ * Rev 0.11
-+ * fixed the led light on/off bug.
-+ * modify some wctdm print to opvxa1200
-+ * support firmware version 1.2, faster i/o operation, and better LED control.
-+ *
-+ * Rev 0.12 patched to support new pci id 0x8519
-+ * Rev 0.13 patched to remove the warning during compile under kernel 2.6.22
-+ * Rev 0.14 patched to remove the bug for ZAP_IRQ_SHARED , 3/9/2007
-+ * Rev 0.15 patched to support new pci ID 0X9532 by james.zhu, 23/10/2007
-+ * Rev 0.16 support new pci id 0x9559 by Miao Lin 21/3/2008
-+ * Rev 0.17
-+ * patched a few bugs,
-+ * add hwgain support.
-+ * fixed A800P version check
-+ * Rev 1.4.9.2
-+ * Only generate 8 channels for A800P
-+ * Version number synced to zaptel distribution.
-+ * Rev 1.4.9.2.a
-+ * Fixed freeregion.
-+ *
-+ * Rev 1.4.9.2.b
-+ * Add cid before first ring support.
-+ * New Paremeters:
-+ * cidbeforering : set to 1 will cause the card enable cidbeforering function. default 0
-+ * cidbuflen : length of cid buffer, in msec, default 3000 msec.
-+ * cidtimeout : time out of a ring, default 6000msec
-+ * User must set cidstart=polarity in zapata.conf to use with this feature
-+ * cidsignalling = signalling format send before 1st ring. most likely dtmf.
-+ *
-+ * Rev 1.4.9.2.c
-+ * add driver parameter cidtimeout.
-+ *
-+ * Rev 1.4.9.2.d
-+ * add debug stuff to test fxs power alarm
-+ *
-+ * Rev 1.4.11
-+ * Support enhanced full scale tx/rx for FXO required by europe standard (Register 30, acim) (module parm fxofullscale)
-+ *
-+ * Rev 1.4.12 2008/10/17
-+ * Fixed bug cause FXS module report fake power alarm.
-+ * Power alarm debug stuff removed.
-+ *
-+ * Rev 2.0 DAHDI 2008/10/17
-+ *
-+ * Rev 2.0.1 add new pci id 0x9599
-+ * Re 2.0.2 12/01/2009
-+ add fixedtimepolarity: set time(ms) when send polarity after 1st ring happen.
-+ * Sometimes the dtmf cid is sent just after first ring off, and the system do not have
-+ * enough time to start detect 1st dtmf.
-+ * 0 means send polarity at the end of 1st ring.
-+ * x means send ploarity after x ms of 1st ring begin.
-+ *
-+ * Rev 2.0.3 12/01/2009
-+ * Add touch_softlockup_watchdog() in wctdm_hardware_init, to avoid cpu softlockup system message for FXS.
-+ *
-+ *
-+ * Rev 1.4.12.4 17/04/2009 James.zhu
-+ * Changed wctdm_voicedaa_check_hook() to detect FXO battery and solved the problem with dial(dahdi/go/XXXXXXXXXX)
-+ * add alarm detection for FXO
-+ *
-+ * Rev 1.4.12.5 01/10/2009 james.zhu
-+ * Add jiffies for 5 second in wctdm_hardware_init
-+ *
-+ * Rev 1.4.12.6 5/15/2011 Miaolin
-+ * use write dma to generate irq.
-+ * add parameter watchdma allow reset dma when it is not correctly started.
-+ * add delay after reset
-+ * change reset time to 1 sec.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/pci.h>
-+#include <linux/interrupt.h>
-+#include <linux/moduleparam.h>
-+#include <asm/io.h>
-+#include <linux/sched.h>
-+#include "proslic.h"
-+
-+/* MiaoLin debug start */
-+#include <linux/string.h>
-+#include <asm/uaccess.h> /* get_fs(), set_fs(), KERNEL_DS */
-+#include <linux/file.h> /* fput() */
-+/* MiaoLin debug end */
-+
-+
-+/*
-+ * Define for audio vs. register based ring detection
-+ *
-+ */
-+/* #define AUDIO_RINGCHECK */
-+
-+/*
-+ Experimental max loop current limit for the proslic
-+ Loop current limit is from 20 mA to 41 mA in steps of 3
-+ (according to datasheet)
-+ So set the value below to:
-+ 0x00 : 20mA (default)
-+ 0x01 : 23mA
-+ 0x02 : 26mA
-+ 0x03 : 29mA
-+ 0x04 : 32mA
-+ 0x05 : 35mA
-+ 0x06 : 37mA
-+ 0x07 : 41mA
-+*/
-+static int loopcurrent = 20;
-+
-+static int reversepolarity = 0;
-+
-+static alpha indirect_regs[] =
-+{
-+{0,255,"DTMF_ROW_0_PEAK",0x55C2},
-+{1,255,"DTMF_ROW_1_PEAK",0x51E6},
-+{2,255,"DTMF_ROW2_PEAK",0x4B85},
-+{3,255,"DTMF_ROW3_PEAK",0x4937},
-+{4,255,"DTMF_COL1_PEAK",0x3333},
-+{5,255,"DTMF_FWD_TWIST",0x0202},
-+{6,255,"DTMF_RVS_TWIST",0x0202},
-+{7,255,"DTMF_ROW_RATIO_TRES",0x0198},
-+{8,255,"DTMF_COL_RATIO_TRES",0x0198},
-+{9,255,"DTMF_ROW_2ND_ARM",0x0611},
-+{10,255,"DTMF_COL_2ND_ARM",0x0202},
-+{11,255,"DTMF_PWR_MIN_TRES",0x00E5},
-+{12,255,"DTMF_OT_LIM_TRES",0x0A1C},
-+{13,0,"OSC1_COEF",0x7B30},
-+{14,1,"OSC1X",0x0063},
-+{15,2,"OSC1Y",0x0000},
-+{16,3,"OSC2_COEF",0x7870},
-+{17,4,"OSC2X",0x007D},
-+{18,5,"OSC2Y",0x0000},
-+{19,6,"RING_V_OFF",0x0000},
-+{20,7,"RING_OSC",0x7EF0},
-+{21,8,"RING_X",0x0160},
-+{22,9,"RING_Y",0x0000},
-+{23,255,"PULSE_ENVEL",0x2000},
-+{24,255,"PULSE_X",0x2000},
-+{25,255,"PULSE_Y",0x0000},
-+//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower
-+{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower
-+{27,14,"XMIT_DIGITAL_GAIN",0x4000},
-+//{27,14,"XMIT_DIGITAL_GAIN",0x2000},
-+{28,15,"LOOP_CLOSE_TRES",0x1000},
-+{29,16,"RING_TRIP_TRES",0x3600},
-+{30,17,"COMMON_MIN_TRES",0x1000},
-+{31,18,"COMMON_MAX_TRES",0x0200},
-+{32,19,"PWR_ALARM_Q1Q2",0x07C0},
-+{33,20,"PWR_ALARM_Q3Q4",0x2600},
-+{34,21,"PWR_ALARM_Q5Q6",0x1B80},
-+{35,22,"LOOP_CLOSURE_FILTER",0x8000},
-+{36,23,"RING_TRIP_FILTER",0x0320},
-+{37,24,"TERM_LP_POLE_Q1Q2",0x008C},
-+{38,25,"TERM_LP_POLE_Q3Q4",0x0100},
-+{39,26,"TERM_LP_POLE_Q5Q6",0x0010},
-+{40,27,"CM_BIAS_RINGING",0x0C00},
-+{41,64,"DCDC_MIN_V",0x0C00},
-+{42,255,"DCDC_XTRA",0x1000},
-+{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
-+};
-+
-+
-+#include <dahdi/kernel.h>
-+#include <dahdi/wctdm_user.h>
-+
-+#include "fxo_modes.h"
-+
-+#define NUM_FXO_REGS 60
-+
-+#define WC_MAX_IFACES 128
-+
-+#define WC_OFFSET 4 /* Offset between transmit and receive, in bytes. */
-+#define WC_SYNCFLAG 0xca1ef1ac
-+
-+#define WC_CNTL 0x00
-+#define WC_OPER 0x01
-+#define WC_AUXC 0x02
-+#define WC_AUXD 0x03
-+#define WC_MASK0 0x04
-+#define WC_MASK1 0x05
-+#define WC_INTSTAT 0x06
-+#define WC_AUXR 0x07
-+
-+#define WC_DMAWS 0x08
-+#define WC_DMAWI 0x0c
-+#define WC_DMAWE 0x10
-+#define WC_DMARS 0x18
-+#define WC_DMARI 0x1c
-+#define WC_DMARE 0x20
-+
-+#define WC_AUXFUNC 0x2b
-+#define WC_SERCTL 0x2d
-+#define WC_FSCDELAY 0x2f
-+
-+#define WC_REGBASE 0xc0
-+
-+#define WC_VER 0x0
-+#define WC_CS 0x1
-+#define WC_SPICTRL 0x2
-+#define WC_SPIDATA 0x3
-+
-+#define BIT_SPI_BYHW (1 << 0)
-+#define BIT_SPI_BUSY (1 << 1) // 0=can read/write spi, 1=spi working.
-+#define BIT_SPI_START (1 << 2)
-+
-+
-+#define BIT_LED_CLK (1 << 0) // MiaoLin add to control the led.
-+#define BIT_LED_DATA (1 << 1) // MiaoLin add to control the led.
-+
-+#define BIT_CS (1 << 2)
-+#define BIT_SCLK (1 << 3)
-+#define BIT_SDI (1 << 4)
-+#define BIT_SDO (1 << 5)
-+
-+#define FLAG_EMPTY 0
-+#define FLAG_WRITE 1
-+#define FLAG_READ 2
-+#define DEFAULT_RING_DEBOUNCE 64 /* Ringer Debounce (64 ms) */
-+#define POLARITY_DEBOUNCE 64 /* Polarity debounce (64 ms) */
-+#define OHT_TIMER 6000 /* How long after RING to retain OHT */
-+
-+#define FLAG_3215 (1 << 0)
-+#define FLAG_A800 (1 << 7)
-+
-+#define MAX_NUM_CARDS 12
-+#define NUM_CARDS 12
-+#define NUM_FLAG 4 /* number of flag channels. */
-+
-+
-+enum cid_hook_state {
-+ CID_STATE_IDLE = 0,
-+ CID_STATE_RING_ON,
-+ CID_STATE_RING_OFF,
-+ CID_STATE_WAIT_RING_FINISH
-+};
-+
-+/* if you want to record the last 8 sec voice before the driver unload, uncomment it and rebuild. */
-+/* #define TEST_LOG_INCOME_VOICE */
-+#define voc_buffer_size (8000*8)
-+
-+
-+#define MAX_ALARMS 10
-+
-+#define MOD_TYPE_FXS 0
-+#define MOD_TYPE_FXO 1
-+
-+#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */
-+#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */
-+#define PEGCOUNT 5 /* 5 cycles of pegging means RING */
-+
-+#define NUM_CAL_REGS 12
-+
-+struct calregs {
-+ unsigned char vals[NUM_CAL_REGS];
-+};
-+
-+enum proslic_power_warn {
-+ PROSLIC_POWER_UNKNOWN = 0,
-+ PROSLIC_POWER_ON,
-+ PROSLIC_POWER_WARNED,
-+};
-+
-+enum battery_state {
-+ BATTERY_UNKNOWN = 0,
-+ BATTERY_PRESENT,
-+ BATTERY_LOST,
-+};
-+struct wctdm {
-+ struct pci_dev *dev;
-+ char *variety;
-+ struct dahdi_span span;
-+ struct dahdi_device *ddev;
-+ unsigned char ios;
-+ int usecount;
-+ unsigned int intcount;
-+ int dead;
-+ int pos;
-+ int flags[MAX_NUM_CARDS];
-+ int freeregion;
-+ int alt;
-+ int curcard;
-+ int cardflag; /* Bit-map of present cards */
-+ enum proslic_power_warn proslic_power;
-+ spinlock_t lock;
-+
-+ union {
-+ struct fxo {
-+#ifdef AUDIO_RINGCHECK
-+ unsigned int pegtimer;
-+ int pegcount;
-+ int peg;
-+ int ring;
-+#else
-+ int wasringing;
-+ int lastrdtx;
-+#endif
-+ int ringdebounce;
-+ int offhook;
-+ unsigned int battdebounce;
-+ unsigned int battalarm;
-+ enum battery_state battery;
-+ int lastpol;
-+ int polarity;
-+ int polaritydebounce;
-+ } fxo;
-+ struct fxs {
-+ int oldrxhook;
-+ int debouncehook;
-+ int lastrxhook;
-+ int debounce;
-+ int ohttimer;
-+ int idletxhookstate; /* IDLE changing hook state */
-+ int lasttxhook;
-+ int palarms;
-+ struct calregs calregs;
-+ } fxs;
-+ } mod[MAX_NUM_CARDS];
-+
-+ /* Receive hook state and debouncing */
-+ int modtype[MAX_NUM_CARDS];
-+ unsigned char reg0shadow[MAX_NUM_CARDS];
-+ unsigned char reg1shadow[MAX_NUM_CARDS];
-+
-+ unsigned long ioaddr;
-+ unsigned long mem_region; /* 32 bit Region allocated to tiger320 */
-+ unsigned long mem_len; /* Length of 32 bit region */
-+ volatile unsigned long mem32; /* Virtual representation of 32 bit memory area */
-+
-+ dma_addr_t readdma;
-+ dma_addr_t writedma;
-+ volatile unsigned char *writechunk; /* Double-word aligned write memory */
-+ volatile unsigned char *readchunk; /* Double-word aligned read memory */
-+ /*struct dahdi_chan chans[MAX_NUM_CARDS];*/
-+ struct dahdi_chan _chans[NUM_CARDS];
-+ struct dahdi_chan *chans[NUM_CARDS];
-+
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+ char * voc_buf[MAX_NUM_CARDS + NUM_FLAG];
-+ int voc_ptr[MAX_NUM_CARDS + NUM_FLAG];
-+#endif
-+ int lastchan;
-+ unsigned short ledstate;
-+ unsigned char fwversion;
-+ int max_cards;
-+ char *card_name;
-+
-+ char *cid_history_buf[MAX_NUM_CARDS];
-+ int cid_history_ptr[MAX_NUM_CARDS];
-+ int cid_history_clone_cnt[MAX_NUM_CARDS];
-+ enum cid_hook_state cid_state[MAX_NUM_CARDS];
-+ int cid_ring_on_time[MAX_NUM_CARDS];
-+};
-+
-+static char* A1200P_Name = "A1200P";
-+static char* A800P_Name = "A800P";
-+
-+struct wctdm_desc {
-+ char *name;
-+ int flags;
-+};
-+
-+static struct wctdm_desc wctdme = { "OpenVox A1200P/A800P", 0 };
-+static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 };
-+
-+static struct wctdm *ifaces[WC_MAX_IFACES];
-+
-+static void wctdm_release(struct wctdm *wc);
-+
-+static int watchdma=0;
-+static unsigned int battdebounce;
-+static unsigned int battalarm;
-+static unsigned int battthresh;
-+static int ringdebounce = DEFAULT_RING_DEBOUNCE;
-+/* times 4, because must be a multiple of 4ms: */
-+static int dialdebounce = 8 * 8;
-+static int fwringdetect = 0;
-+static int debug = 0;
-+static int robust = 0;
-+static int timingonly = 0;
-+static int lowpower = 0;
-+static int boostringer = 0;
-+static int fastringer = 0;
-+static int _opermode = 0;
-+static char *opermode = "FCC";
-+static int fxshonormode = 0;
-+static int alawoverride = 0;
-+static int fastpickup = 0;
-+static int fxotxgain = 0;
-+static int fxorxgain = 0;
-+static int fxstxgain = 0;
-+static int fxsrxgain = 0;
-+/* special h/w control command */
-+static int spibyhw = 1;
-+static int usememio = 1;
-+static int cidbeforering = 0;
-+static int cidbuflen = 3000; /* in msec, default 3000 */
-+static int cidtimeout = 6*1000; /* in msec, default 6000 */
-+static int fxofullscale = 0; /* fxo full scale tx/rx, register 30, acim */
-+static int fixedtimepolarity=0; /* time delay in ms when send polarity after rise edge of 1st ring.*/
-+
-+static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
-+
-+static void wctdm_set_led(struct wctdm* wc, int card, int onoff)
-+{
-+ int i;
-+ unsigned char c;
-+
-+ wc->ledstate &= ~(0x01<<card);
-+ wc->ledstate |= (onoff<<card);
-+ c = (inb(wc->ioaddr + WC_AUXD)&~BIT_LED_CLK)|BIT_LED_DATA;
-+ outb( c, wc->ioaddr + WC_AUXD);
-+ for(i=MAX_NUM_CARDS-1; i>=0; i--)
-+ {
-+ if(wc->ledstate & (0x0001<<i))
-+ if(wc->fwversion == 0x11)
-+ c &= ~BIT_LED_DATA;
-+ else
-+ c |= BIT_LED_DATA;
-+ else
-+ if(wc->fwversion == 0x11)
-+ c |= BIT_LED_DATA;
-+ else
-+ c &= ~BIT_LED_DATA;
-+
-+ outb( c, wc->ioaddr + WC_AUXD);
-+ outb( c|BIT_LED_CLK, wc->ioaddr + WC_AUXD);
-+ outb( (c&~BIT_LED_CLK)|BIT_LED_DATA, wc->ioaddr + WC_AUXD);
-+ }
-+}
-+
-+
-+static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char ints)
-+{
-+ int x, y, chan_offset, pos;
-+ volatile unsigned char *txbuf;
-+
-+ //if (ints & /*0x01*/ 0x04)
-+ if (ints & 0x01)
-+ /* Write is at interrupt address. Start writing from normal offset */
-+ txbuf = wc->writechunk;
-+ else
-+ txbuf = wc->writechunk + DAHDI_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG);
-+
-+ /* Calculate Transmission */
-+ dahdi_transmit(&wc->span);
-+
-+ if(wc->lastchan == -1) // not in sync.
-+ return;
-+
-+ chan_offset = (wc->lastchan*4 + 4 ) % (MAX_NUM_CARDS+NUM_FLAG);
-+
-+ for (y=0;y<DAHDI_CHUNKSIZE;y++) {
-+#ifdef __BIG_ENDIAN
-+ // operation pending...
-+#else
-+ for (x=0;x<(MAX_NUM_CARDS+NUM_FLAG);x++) {
-+ pos = y * (MAX_NUM_CARDS+NUM_FLAG) + ((x + chan_offset + MAX_NUM_CARDS+NUM_FLAG - WC_OFFSET)&0x0f);
-+ if(x<wc->max_cards/*MAX_NUM_CARDS*/)
-+ txbuf[pos] = wc->chans[x]->writechunk[y];
-+ else
-+ txbuf[pos] = 0;
-+ }
-+#endif
-+ }
-+}
-+
-+
-+#ifdef AUDIO_RINGCHECK
-+static inline void ring_check(struct wctdm *wc, int card)
-+{
-+ int x;
-+ short sample;
-+ if (wc->modtype[card] != MOD_TYPE_FXO)
-+ return;
-+ wc->mod[card].fxo.pegtimer += DAHDI_CHUNKSIZE;
-+ for (x=0;x<DAHDI_CHUNKSIZE;x++) {
-+ /* Look for pegging to indicate ringing */
-+ sample = DAHDI_XLAW(wc->chans[card].readchunk[x], (&(wc->chans[card])));
-+ if ((sample > 10000) && (wc->mod[card].fxo.peg != 1)) {
-+ if (debug > 1) printk(KERN_DEBUG "High peg!\n");
-+ if ((wc->mod[card].fxo.pegtimer < PEGTIME) && (wc->mod[card].fxo.pegtimer > MINPEGTIME))
-+ wc->mod[card].fxo.pegcount++;
-+ wc->mod[card].fxo.pegtimer = 0;
-+ wc->mod[card].fxo.peg = 1;
-+ } else if ((sample < -10000) && (wc->mod[card].fxo.peg != -1)) {
-+ if (debug > 1) printk(KERN_DEBUG "Low peg!\n");
-+ if ((wc->mod[card].fxo.pegtimer < (PEGTIME >> 2)) && (wc->mod[card].fxo.pegtimer > (MINPEGTIME >> 2)))
-+ wc->mod[card].fxo.pegcount++;
-+ wc->mod[card].fxo.pegtimer = 0;
-+ wc->mod[card].fxo.peg = -1;
-+ }
-+ }
-+ if (wc->mod[card].fxo.pegtimer > PEGTIME) {
-+ /* Reset pegcount if our timer expires */
-+ wc->mod[card].fxo.pegcount = 0;
-+ }
-+ /* Decrement debouncer if appropriate */
-+ if (wc->mod[card].fxo.ringdebounce)
-+ wc->mod[card].fxo.ringdebounce--;
-+ if (!wc->mod[card].fxo.offhook && !wc->mod[card].fxo.ringdebounce) {
-+ if (!wc->mod[card].fxo.ring && (wc->mod[card].fxo.pegcount > PEGCOUNT)) {
-+ /* It's ringing */
-+ if (debug)
-+ printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ if (!wc->mod[card].fxo.offhook)
-+ dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_RING);
-+ wc->mod[card].fxo.ring = 1;
-+ }
-+ if (wc->mod[card].fxo.ring && !wc->mod[card].fxo.pegcount) {
-+ /* No more ring */
-+ if (debug)
-+ printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ wc->mod[card].fxo.ring = 0;
-+ }
-+ }
-+}
-+#endif
-+
-+
-+static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char ints)
-+{
-+ volatile unsigned char *rxbuf;
-+ int x, y, chan_offset;
-+
-+
-+ //if(ints & 0x08/*0x04*/)
-+ if(ints & 0x01)
-+ /* Read is at interrupt address. Valid data is available at normal offset */
-+ rxbuf = wc->readchunk;
-+ else
-+ rxbuf = wc->readchunk + DAHDI_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG);
-+
-+ for (x = 0; x < 4; x++) {
-+ if (*(int*)(rxbuf+x*4) == WC_SYNCFLAG) {
-+ break;
-+ }
-+ }
-+
-+ if(x==4)
-+ {
-+ printk("buffer sync misseed!\n");
-+ wc->lastchan = -1;
-+ return;
-+ } else if(wc->lastchan != x) {
-+ printk("buffer re-sync occur from %d to %d\n", wc->lastchan, x);
-+ wc->lastchan = x;
-+ }
-+
-+ if(watchdma) {
-+ if( (x!=0) && (x!=3) ) {
-+ printk("Bad re-sync %d, resetting...\n", x);
-+ outb(0x0f, wc->ioaddr + WC_CNTL);
-+ for(x=0; x<1000*1000*1000; x++);
-+ outb(0x01, wc->ioaddr + WC_CNTL);
-+ outb(0x01, wc->ioaddr + WC_OPER);
-+ wc->lastchan=-1;
-+ return;
-+ }
-+ }
-+
-+ chan_offset = (wc->lastchan*4 + 4 ) % (MAX_NUM_CARDS+NUM_FLAG);
-+
-+ for (x=0;x<DAHDI_CHUNKSIZE;x++) {
-+#ifdef __BIG_ENDIAN
-+ // operation pending...
-+#else
-+ for (y=0;y<wc->max_cards/*MAX_NUM_CARDS*/;y++) {
-+ if (wc->cardflag & (1 << y))
-+ wc->chans[y]->readchunk[x] = rxbuf[(MAX_NUM_CARDS+NUM_FLAG) * x + ((y + chan_offset ) & 0x0f)];
-+#ifdef TEST_LOG_INCOME_VOICE
-+ wc->voc_buf[y][wc->voc_ptr[y]] = rxbuf[(MAX_NUM_CARDS+NUM_FLAG) * x + ((y + chan_offset) & 0x0f)];
-+ wc->voc_ptr[y]++;
-+ if(wc->voc_ptr[y] >= voc_buffer_size)
-+ wc->voc_ptr[y] = 0;
-+#endif
-+ }
-+#endif
-+ }
-+
-+ if(cidbeforering)
-+ {
-+ for(x=0; x<wc->max_cards; x++)
-+ {
-+ if (wc->modtype[wc->chans[x]->chanpos - 1] == MOD_TYPE_FXO)
-+ if(wc->mod[wc->chans[x]->chanpos - 1].fxo.offhook == 0)
-+ {
-+ /*unsigned int *p_readchunk, *p_cid_history;
-+
-+ p_readchunk = (unsigned int*)wc->chans[x].readchunk;
-+ p_cid_history = (unsigned int*)(wc->cid_history_buf[x] + wc->cid_history_ptr[x]);*/
-+
-+ if(wc->cid_state[x] == CID_STATE_IDLE) /* we need copy data to the cid voice buffer */
-+ {
-+ memcpy(wc->cid_history_buf[x] + wc->cid_history_ptr[x], wc->chans[x]->readchunk, DAHDI_CHUNKSIZE);
-+ wc->cid_history_ptr[x] = (wc->cid_history_ptr[x] + DAHDI_CHUNKSIZE)%(cidbuflen * DAHDI_MAX_CHUNKSIZE);
-+ }
-+ else if (wc->cid_state[x] == CID_STATE_RING_ON)
-+ wc->cid_history_clone_cnt[x] = cidbuflen;
-+ else if (wc->cid_state[x] == CID_STATE_RING_OFF)
-+ {
-+ if(wc->cid_history_clone_cnt[x])
-+ {
-+ memcpy(wc->chans[x]->readchunk, wc->cid_history_buf[x] + wc->cid_history_ptr[x], DAHDI_MAX_CHUNKSIZE);
-+ wc->cid_history_clone_cnt[x]--;
-+ wc->cid_history_ptr[x] = (wc->cid_history_ptr[x] + DAHDI_MAX_CHUNKSIZE)%(cidbuflen * DAHDI_MAX_CHUNKSIZE);
-+ }
-+ else
-+ {
-+ wc->cid_state[x] = CID_STATE_WAIT_RING_FINISH;
-+ wc->cid_history_clone_cnt[x] = cidtimeout; /* wait 6 sec, if no ring, return to idle */
-+ }
-+ }
-+ else if(wc->cid_state[x] == CID_STATE_WAIT_RING_FINISH)
-+ {
-+ if(wc->cid_history_clone_cnt[x] > 0)
-+ wc->cid_history_clone_cnt[x]--;
-+ else
-+ {
-+ wc->cid_state[x] = CID_STATE_IDLE;
-+ wc->cid_history_ptr[x] = 0;
-+ wc->cid_history_clone_cnt[x] = 0;
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+#ifdef AUDIO_RINGCHECK
-+ for (x=0;x<wc->max_cards;x++)
-+ ring_check(wc, x);
-+#endif
-+ /* XXX We're wasting 8 taps. We should get closer :( */
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if (wc->cardflag & (1 << x))
-+ dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->chans[x]->writechunk);
-+ }
-+
-+ dahdi_receive(&wc->span);
-+}
-+
-+static void wctdm_stop_dma(struct wctdm *wc);
-+static void wctdm_reset_tdm(struct wctdm *wc);
-+static void wctdm_restart_dma(struct wctdm *wc);
-+
-+
-+static unsigned char __wctdm_getcreg(struct wctdm *wc, unsigned char reg);
-+static void __wctdm_setcreg(struct wctdm *wc, unsigned char reg, unsigned char val);
-+
-+
-+static inline void __write_8bits(struct wctdm *wc, unsigned char bits)
-+{
-+ if(spibyhw == 0)
-+ {
-+ int x;
-+ /* Drop chip select */
-+ wc->ios |= BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ wc->ios &= ~BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ for (x=0;x<8;x++) {
-+ /* Send out each bit, MSB first, drop SCLK as we do so */
-+ if (bits & 0x80)
-+ wc->ios |= BIT_SDI;
-+ else
-+ wc->ios &= ~BIT_SDI;
-+ wc->ios &= ~BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Now raise SCLK high again and repeat */
-+ wc->ios |= BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ bits <<= 1;
-+ }
-+ /* Finally raise CS back high again */
-+ wc->ios |= BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ }
-+ else
-+ {
-+ __wctdm_setcreg(wc, WC_SPIDATA, bits);
-+ __wctdm_setcreg(wc, WC_SPICTRL, BIT_SPI_BYHW | BIT_SPI_START);
-+ while ((__wctdm_getcreg(wc, WC_SPICTRL) & BIT_SPI_BUSY) != 0);
-+ __wctdm_setcreg(wc, WC_SPICTRL, BIT_SPI_BYHW);
-+ }
-+}
-+
-+
-+static inline void __reset_spi(struct wctdm *wc)
-+{
-+ __wctdm_setcreg(wc, WC_SPICTRL, 0);
-+
-+ /* Drop chip select and clock once and raise and clock once */
-+ wc->ios |= BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ wc->ios &= ~BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ wc->ios |= BIT_SDI;
-+ wc->ios &= ~BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Now raise SCLK high again and repeat */
-+ wc->ios |= BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Finally raise CS back high again */
-+ wc->ios |= BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Clock again */
-+ wc->ios &= ~BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Now raise SCLK high again and repeat */
-+ wc->ios |= BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+
-+ __wctdm_setcreg(wc, WC_SPICTRL, spibyhw);
-+
-+}
-+
-+static inline unsigned char __read_8bits(struct wctdm *wc)
-+{
-+ unsigned char res=0, c;
-+ int x;
-+ if(spibyhw == 0)
-+ {
-+ wc->ios &= ~BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Drop chip select */
-+ wc->ios &= ~BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ for (x=0;x<8;x++) {
-+ res <<= 1;
-+ /* Get SCLK */
-+ wc->ios &= ~BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ /* Read back the value */
-+ c = inb(wc->ioaddr + WC_AUXR);
-+ if (c & BIT_SDO)
-+ res |= 1;
-+ /* Now raise SCLK high again */
-+ wc->ios |= BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ }
-+ /* Finally raise CS back high again */
-+ wc->ios |= BIT_CS;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ wc->ios &= ~BIT_SCLK;
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+ }
-+ else
-+ {
-+ __wctdm_setcreg(wc, WC_SPICTRL, BIT_SPI_BYHW | BIT_SPI_START);
-+ while ((__wctdm_getcreg(wc, WC_SPICTRL) & BIT_SPI_BUSY) != 0);
-+ res = __wctdm_getcreg(wc, WC_SPIDATA);
-+ __wctdm_setcreg(wc, WC_SPICTRL, BIT_SPI_BYHW);
-+ }
-+
-+ /* And return our result */
-+ return res;
-+}
-+
-+static void __wctdm_setcreg_mem(struct wctdm *wc, unsigned char reg, unsigned char val)
-+{
-+ unsigned int *p = (unsigned int*)(wc->mem32 + WC_REGBASE + ((reg & 0xf) << 2));
-+ *p = val;
-+}
-+
-+static unsigned char __wctdm_getcreg_mem(struct wctdm *wc, unsigned char reg)
-+{
-+ unsigned int *p = (unsigned int*)(wc->mem32 + WC_REGBASE + ((reg & 0xf) << 2));
-+ return (*p)&0x00ff;
-+}
-+
-+
-+static void __wctdm_setcreg(struct wctdm *wc, unsigned char reg, unsigned char val)
-+{
-+ if(usememio)
-+ __wctdm_setcreg_mem(wc, reg, val);
-+ else
-+ outb(val, wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));
-+}
-+
-+static unsigned char __wctdm_getcreg(struct wctdm *wc, unsigned char reg)
-+{
-+ if(usememio)
-+ return __wctdm_getcreg_mem(wc, reg);
-+ else
-+ return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));
-+}
-+
-+static inline void __wctdm_setcard(struct wctdm *wc, int card)
-+{
-+ if (wc->curcard != card) {
-+ __wctdm_setcreg(wc, WC_CS, card);
-+ wc->curcard = card;
-+ //printk("Select card %d\n", card);
-+ }
-+}
-+
-+static void __wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value)
-+{
-+ __wctdm_setcard(wc, card);
-+ if (wc->modtype[card] == MOD_TYPE_FXO) {
-+ __write_8bits(wc, 0x20);
-+ __write_8bits(wc, reg & 0x7f);
-+ } else {
-+ __write_8bits(wc, reg & 0x7f);
-+ }
-+ __write_8bits(wc, value);
-+}
-+
-+static void wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc->lock, flags);
-+ __wctdm_setreg(wc, card, reg, value);
-+ spin_unlock_irqrestore(&wc->lock, flags);
-+}
-+
-+static unsigned char __wctdm_getreg(struct wctdm *wc, int card, unsigned char reg)
-+{
-+ __wctdm_setcard(wc, card);
-+ if (wc->modtype[card] == MOD_TYPE_FXO) {
-+ __write_8bits(wc, 0x60);
-+ __write_8bits(wc, reg & 0x7f);
-+ } else {
-+ __write_8bits(wc, reg | 0x80);
-+ }
-+ return __read_8bits(wc);
-+}
-+
-+static inline void reset_spi(struct wctdm *wc, int card)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc->lock, flags);
-+ __wctdm_setcard(wc, card);
-+ __reset_spi(wc);
-+ __reset_spi(wc);
-+ spin_unlock_irqrestore(&wc->lock, flags);
-+}
-+
-+static unsigned char wctdm_getreg(struct wctdm *wc, int card, unsigned char reg)
-+{
-+ unsigned long flags;
-+ unsigned char res;
-+ spin_lock_irqsave(&wc->lock, flags);
-+ res = __wctdm_getreg(wc, card, reg);
-+ spin_unlock_irqrestore(&wc->lock, flags);
-+ return res;
-+}
-+
-+static int __wait_access(struct wctdm *wc, int card)
-+{
-+ unsigned char data = 0;
-+ long origjiffies;
-+ int count = 0;
-+
-+ #define MAX 6000 /* attempts */
-+
-+
-+ origjiffies = jiffies;
-+ /* Wait for indirect access */
-+ while (count++ < MAX)
-+ {
-+ data = __wctdm_getreg(wc, card, I_STATUS);
-+
-+ if (!data)
-+ return 0;
-+
-+ }
-+
-+ if(count > (MAX-1)) printk(KERN_NOTICE " ##### Loop error (%02x) #####\n", data);
-+
-+ return 0;
-+}
-+
-+static unsigned char translate_3215(unsigned char address)
-+{
-+ int x;
-+ for (x=0;x<sizeof(indirect_regs)/sizeof(indirect_regs[0]);x++) {
-+ if (indirect_regs[x].address == address) {
-+ address = indirect_regs[x].altaddr;
-+ break;
-+ }
-+ }
-+ return address;
-+}
-+
-+static int wctdm_proslic_setreg_indirect(struct wctdm *wc, int card, unsigned char address, unsigned short data)
-+{
-+ unsigned long flags;
-+ int res = -1;
-+ /* Translate 3215 addresses */
-+ if (wc->flags[card] & FLAG_3215) {
-+ address = translate_3215(address);
-+ if (address == 255)
-+ return 0;
-+ }
-+ spin_lock_irqsave(&wc->lock, flags);
-+ if(!__wait_access(wc, card)) {
-+ __wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF));
-+ __wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8));
-+ __wctdm_setreg(wc, card, IAA,address);
-+ res = 0;
-+ };
-+ spin_unlock_irqrestore(&wc->lock, flags);
-+ return res;
-+}
-+
-+static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address)
-+{
-+ unsigned long flags;
-+ int res = -1;
-+ char *p=NULL;
-+ /* Translate 3215 addresses */
-+ if (wc->flags[card] & FLAG_3215) {
-+ address = translate_3215(address);
-+ if (address == 255)
-+ return 0;
-+ }
-+ spin_lock_irqsave(&wc->lock, flags);
-+ if (!__wait_access(wc, card)) {
-+ __wctdm_setreg(wc, card, IAA, address);
-+ if (!__wait_access(wc, card)) {
-+ unsigned char data1, data2;
-+ data1 = __wctdm_getreg(wc, card, IDA_LO);
-+ data2 = __wctdm_getreg(wc, card, IDA_HI);
-+ res = data1 | (data2 << 8);
-+ } else
-+ p = "Failed to wait inside\n";
-+ } else
-+ p = "failed to wait\n";
-+ spin_unlock_irqrestore(&wc->lock, flags);
-+ if (p)
-+ printk(KERN_NOTICE "%s", p);
-+ return res;
-+}
-+
-+static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card)
-+{
-+ unsigned char i;
-+
-+ for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++)
-+ {
-+ if(wctdm_proslic_setreg_indirect(wc, card, indirect_regs[i].address,indirect_regs[i].initial))
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int wctdm_proslic_verify_indirect_regs(struct wctdm *wc, int card)
-+{
-+ int passed = 1;
-+ unsigned short i, initial;
-+ int j;
-+
-+ for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++)
-+ {
-+ if((j = wctdm_proslic_getreg_indirect(wc, card, (unsigned char) indirect_regs[i].address)) < 0) {
-+ printk(KERN_NOTICE "Failed to read indirect register %d\n", i);
-+ return -1;
-+ }
-+ initial= indirect_regs[i].initial;
-+
-+ if ( j != initial && (!(wc->flags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255)))
-+ {
-+ printk(KERN_NOTICE "!!!!!!! %s iREG %X = %X should be %X\n",
-+ indirect_regs[i].name,indirect_regs[i].address,j,initial );
-+ passed = 0;
-+ }
-+ }
-+
-+ if (passed) {
-+ if (debug)
-+ printk(KERN_DEBUG "Init Indirect Registers completed successfully.\n");
-+ } else {
-+ printk(KERN_NOTICE " !!!!! Init Indirect Registers UNSUCCESSFULLY.\n");
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card)
-+{
-+ int res;
-+ /* Check loopback */
-+ res = wc->reg1shadow[card];
-+
-+ if (!res && (res != wc->mod[card].fxs.lasttxhook)) // read real state from register By wx
-+ res=wctdm_getreg(wc, card, 64);
-+
-+ if (!res && (res != wc->mod[card].fxs.lasttxhook)) {
-+ res = wctdm_getreg(wc, card, 8);
-+ if (res) {
-+ printk(KERN_NOTICE "Ouch, part reset, quickly restoring reality (%d)\n", card);
-+ wctdm_init_proslic(wc, card, 1, 0, 1);
-+ } else {
-+ if (wc->mod[card].fxs.palarms++ < MAX_ALARMS) {
-+ printk(KERN_NOTICE "Power alarm on module %d, resetting!\n", card + 1);
-+ if (wc->mod[card].fxs.lasttxhook == 4)
-+ wc->mod[card].fxs.lasttxhook = 1;
-+ wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook);
-+ } else {
-+ if (wc->mod[card].fxs.palarms == MAX_ALARMS)
-+ printk(KERN_NOTICE "Too many power alarms on card %d, NOT resetting!\n", card + 1);
-+ }
-+ }
-+ }
-+}
-+static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
-+{
-+#define MS_PER_CHECK_HOOK 16
-+
-+#ifndef AUDIO_RINGCHECK
-+ unsigned char res;
-+#endif
-+ signed char b;
-+ int errors = 0;
-+ struct fxo *fxo = &wc->mod[card].fxo;
-+
-+ /* Try to track issues that plague slot one FXO's */
-+ b = wc->reg0shadow[card];
-+ if ((b & 0x2) || !(b & 0x8)) {
-+ /* Not good -- don't look at anything else */
-+ if (debug)
-+ printk(KERN_DEBUG "Error (%02x) on card %d!\n", b, card + 1);
-+ errors++;
-+ }
-+ b &= 0x9b;
-+ if (fxo->offhook) {
-+ if (b != 0x9)
-+ wctdm_setreg(wc, card, 5, 0x9);
-+ } else {
-+ if (b != 0x8)
-+ wctdm_setreg(wc, card, 5, 0x8);
-+ }
-+ if (errors)
-+ return;
-+ if (!fxo->offhook) {
-+ if(fixedtimepolarity) {
-+ if ( wc->cid_state[card] == CID_STATE_RING_ON && wc->cid_ring_on_time[card]>0) {
-+ if(wc->cid_ring_on_time[card]>=fixedtimepolarity) {
-+ dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
-+ wc->cid_ring_on_time[card] = -1; /* the polarity already sent */
-+ } else {
-+ wc->cid_ring_on_time[card] += 16;
-+ }
-+ }
-+ }
-+ if (fwringdetect) {
-+ res = wc->reg0shadow[card] & 0x60;
-+ if (fxo->ringdebounce) {
-+ --fxo->ringdebounce;
-+ if (res && (res != fxo->lastrdtx) &&
-+ (fxo->battery == BATTERY_PRESENT)) {
-+ if (!fxo->wasringing) {
-+ fxo->wasringing = 1;
-+ if (debug) {
-+ printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ if(cidbeforering) {
-+ if(wc->cid_state[card] == CID_STATE_IDLE) {
-+ wc->cid_state[card] = CID_STATE_RING_ON;
-+ wc->cid_ring_on_time[card] = 16; /* check every 16ms */
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ }
-+ fxo->lastrdtx = res;
-+ fxo->ringdebounce = 10;
-+ } else if (!res) {
-+ if ((fxo->ringdebounce == 0) && fxo->wasringing) {
-+ fxo->wasringing = 0;
-+ if (debug) {
-+ printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ if(cidbeforering) {
-+ if(wc->cid_state[card] == CID_STATE_RING_ON) {
-+ if(fixedtimepolarity==0) {
-+ dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
-+ }
-+ wc->cid_state[card] = CID_STATE_RING_OFF;
-+ } else {
-+ if(wc->cid_state[card] == CID_STATE_WAIT_RING_FINISH) {
-+ wc->cid_history_clone_cnt[card] = cidtimeout;
-+ }
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+ }
-+ }
-+ } else if (res && (fxo->battery == BATTERY_PRESENT)) {
-+ fxo->lastrdtx = res;
-+ fxo->ringdebounce = 10;
-+ }
-+ } else {
-+ res = wc->reg0shadow[card];
-+ if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) {
-+ fxo->ringdebounce += (DAHDI_CHUNKSIZE * 16);
-+ if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) {
-+ if (!fxo->wasringing) {
-+ fxo->wasringing = 1;
-+ if(cidbeforering) {
-+ if(wc->cid_state[card] == CID_STATE_IDLE) {
-+ wc->cid_state[card] = CID_STATE_RING_ON;
-+ wc->cid_ring_on_time[card] = 16; /* check every 16ms */
-+ }
-+ else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ if (debug) {
-+ printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ }
-+ fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce;
-+ }
-+ } else {
-+ fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4;
-+ if (fxo->ringdebounce <= 0) {
-+ if (fxo->wasringing) {
-+ fxo->wasringing = 0;
-+ if(cidbeforering) {
-+ if(wc->cid_state[card] == CID_STATE_RING_ON) {
-+ if(fixedtimepolarity==0) {
-+ dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
-+ }
-+ wc->cid_state[card] = CID_STATE_RING_OFF;
-+ } else {
-+ if(wc->cid_state[card] == CID_STATE_WAIT_RING_FINISH) {
-+ wc->cid_history_clone_cnt[card] = cidtimeout;
-+ }
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+ if (debug) {
-+ printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ }
-+ fxo->ringdebounce = 0;
-+ }
-+ }
-+ }
-+ }
-+
-+ b = wc->reg1shadow[card];
-+ if (abs(b) < battthresh) {
-+ /* possible existing states:
-+ battery lost, no debounce timer
-+ battery lost, debounce timer (going to battery present)
-+ battery present or unknown, no debounce timer
-+ battery present or unknown, debounce timer (going to battery lost)
-+ */
-+
-+ if (fxo->battery == BATTERY_LOST) {
-+ if (fxo->battdebounce) {
-+ /* we were going to BATTERY_PRESENT, but battery was lost again,
-+ so clear the debounce timer */
-+ fxo->battdebounce = 0;
-+ }
-+ } else {
-+ if (fxo->battdebounce) {
-+ /* going to BATTERY_LOST, see if we are there yet */
-+ if (--fxo->battdebounce == 0) {
-+ fxo->battery = BATTERY_LOST;
-+ if (debug)
-+ printk(KERN_DEBUG "NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1);
-+#ifdef JAPAN
-+ if (!wc->ohdebounce && wc->offhook) {
-+ dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_ONHOOK);
-+ if (debug)
-+ printk(KERN_DEBUG "Signalled On Hook\n");
-+#ifdef ZERO_BATT_RING
-+ wc->onhook++;
-+#endif
-+ }
-+#else
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
-+ /* set the alarm timer, taking into account that part of its time
-+ period has already passed while debouncing occurred */
-+ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
-+#endif
-+ }
-+ } else {
-+ /* start the debounce timer to verify that battery has been lost */
-+ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ } else {
-+ /* possible existing states:
-+ battery lost or unknown, no debounce timer
-+ battery lost or unknown, debounce timer (going to battery present)
-+ battery present, no debounce timer
-+ battery present, debounce timer (going to battery lost)
-+ */
-+
-+ if (fxo->battery == BATTERY_PRESENT) {
-+ if (fxo->battdebounce) {
-+ /* we were going to BATTERY_LOST, but battery appeared again,
-+ so clear the debounce timer */
-+ fxo->battdebounce = 0;
-+ }
-+ } else {
-+ if (fxo->battdebounce) {
-+ /* going to BATTERY_PRESENT, see if we are there yet */
-+ if (--fxo->battdebounce == 0) {
-+ fxo->battery = BATTERY_PRESENT;
-+ if (debug)
-+ printk(KERN_DEBUG "BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1,
-+ (b < 0) ? "-" : "+");
-+#ifdef ZERO_BATT_RING
-+ if (wc->onhook) {
-+ wc->onhook = 0;
-+ dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ if (debug)
-+ printk(KERN_DEBUG "Signalled Off Hook\n");
-+ }
-+#else
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+#endif
-+ /* set the alarm timer, taking into account that part of its time
-+ period has already passed while debouncing occurred */
-+ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
-+ }
-+ } else {
-+ /* start the debounce timer to verify that battery has appeared */
-+ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ }
-+
-+ if (fxo->lastpol >= 0) {
-+ if (b < 0) {
-+ fxo->lastpol = -1;
-+ fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ if (fxo->lastpol <= 0) {
-+ if (b > 0) {
-+ fxo->lastpol = 1;
-+ fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+
-+ if (fxo->battalarm) {
-+ if (--fxo->battalarm == 0) {
-+ /* the alarm timer has expired, so update the battery alarm state
-+ for this channel */
-+ dahdi_alarm_channel(wc->chans[card], fxo->battery == BATTERY_LOST ? DAHDI_ALARM_RED : DAHDI_ALARM_NONE);
-+ }
-+ }
-+
-+ if (fxo->polaritydebounce) {
-+ if (--fxo->polaritydebounce == 0) {
-+ if (fxo->lastpol != fxo->polarity) {
-+ if (debug)
-+ printk(KERN_DEBUG "%lu Polarity reversed (%d -> %d)\n", jiffies,
-+ fxo->polarity,
-+ fxo->lastpol);
-+ if (fxo->polarity)
-+ dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
-+ fxo->polarity = fxo->lastpol;
-+ }
-+ }
-+ }
-+#undef MS_PER_CHECK_HOOK
-+}
-+
-+static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card)
-+{
-+ char res;
-+ int hook;
-+
-+ /* For some reason we have to debounce the
-+ hook detector. */
-+
-+ res = wc->reg0shadow[card];
-+ hook = (res & 1);
-+ if (hook != wc->mod[card].fxs.lastrxhook) {
-+ /* Reset the debounce (must be multiple of 4ms) */
-+ wc->mod[card].fxs.debounce = dialdebounce * 4;
-+
-+#if 0
-+ printk(KERN_DEBUG "Resetting debounce card %d hook %d, %d\n", card, hook, wc->mod[card].fxs.debounce);
-+#endif
-+ } else {
-+ if (wc->mod[card].fxs.debounce > 0) {
-+ wc->mod[card].fxs.debounce-= 16 * DAHDI_CHUNKSIZE;
-+#if 0
-+ printk(KERN_DEBUG "Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce);
-+#endif
-+ if (!wc->mod[card].fxs.debounce) {
-+#if 0
-+ printk(KERN_DEBUG "Counted down debounce, newhook: %d...\n", hook);
-+#endif
-+ wc->mod[card].fxs.debouncehook = hook;
-+ }
-+ if (!wc->mod[card].fxs.oldrxhook && wc->mod[card].fxs.debouncehook) {
-+ /* Off hook */
-+#if 1
-+ if (debug)
-+#endif
-+ printk(KERN_DEBUG "opvxa1200: Card %d Going off hook\n", card);
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ if (robust)
-+ wctdm_init_proslic(wc, card, 1, 0, 1);
-+ wc->mod[card].fxs.oldrxhook = 1;
-+
-+ } else if (wc->mod[card].fxs.oldrxhook && !wc->mod[card].fxs.debouncehook) {
-+ /* On hook */
-+#if 1
-+ if (debug)
-+#endif
-+ printk(KERN_DEBUG "opvxa1200: Card %d Going on hook\n", card);
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
-+ wc->mod[card].fxs.oldrxhook = 0;
-+ }
-+ }
-+ }
-+ wc->mod[card].fxs.lastrxhook = hook;
-+}
-+
-+DAHDI_IRQ_HANDLER(wctdm_interrupt)
-+{
-+ struct wctdm *wc = dev_id;
-+ unsigned char ints;
-+ int x, y, z;
-+ int mode;
-+
-+ ints = inb(wc->ioaddr + WC_INTSTAT);
-+
-+ if (!ints)
-+ return IRQ_NONE;
-+
-+ outb(ints, wc->ioaddr + WC_INTSTAT);
-+
-+ if (ints & 0x10) {
-+ /* Stop DMA, wait for watchdog */
-+ printk(KERN_INFO "TDM PCI Master abort\n");
-+ wctdm_stop_dma(wc);
-+ return IRQ_RETVAL(1);
-+ }
-+
-+ if (ints & 0x20) {
-+ printk(KERN_INFO "PCI Target abort\n");
-+ return IRQ_RETVAL(1);
-+ }
-+
-+ for (x=0;x<wc->max_cards/*4*3*/;x++) {
-+ if (wc->cardflag & (1 << x) &&
-+ (wc->modtype[x] == MOD_TYPE_FXS)) {
-+ if (wc->mod[x].fxs.lasttxhook == 0x4) {
-+ /* RINGing, prepare for OHT */
-+ wc->mod[x].fxs.ohttimer = OHT_TIMER << 3;
-+ if (reversepolarity)
-+ wc->mod[x].fxs.idletxhookstate = 0x6; /* OHT mode when idle */
-+ else
-+ wc->mod[x].fxs.idletxhookstate = 0x2;
-+ } else {
-+ if (wc->mod[x].fxs.ohttimer) {
-+ wc->mod[x].fxs.ohttimer-= DAHDI_CHUNKSIZE;
-+ if (!wc->mod[x].fxs.ohttimer) {
-+ if (reversepolarity)
-+ wc->mod[x].fxs.idletxhookstate = 0x5; /* Switch to active */
-+ else
-+ wc->mod[x].fxs.idletxhookstate = 0x1;
-+ if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) {
-+ /* Apply the change if appropriate */
-+ if (reversepolarity)
-+ wc->mod[x].fxs.lasttxhook = 0x5;
-+ else
-+ wc->mod[x].fxs.lasttxhook = 0x1;
-+ wctdm_setreg(wc, x, 64, wc->mod[x].fxs.lasttxhook);
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ if (ints & 0x0f) {
-+ wc->intcount++;
-+ z = wc->intcount & 0x3;
-+ mode = wc->intcount & 0xc;
-+ for(y=0; y<wc->max_cards/4/*3*/; y++)
-+ {
-+ x = z + y*4;
-+ if (wc->cardflag & (1 << x ) )
-+ {
-+ switch(mode)
-+ {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 4:
-+ /* Read first shadow reg */
-+ if (wc->modtype[x] == MOD_TYPE_FXS)
-+ wc->reg0shadow[x] = wctdm_getreg(wc, x, 68);
-+ else if (wc->modtype[x] == MOD_TYPE_FXO)
-+ wc->reg0shadow[x] = wctdm_getreg(wc, x, 5);
-+ break;
-+ case 8:
-+ /* Read second shadow reg */
-+ if (wc->modtype[x] == MOD_TYPE_FXS)
-+ wc->reg1shadow[x] = wctdm_getreg(wc, x, 64);
-+ else if (wc->modtype[x] == MOD_TYPE_FXO)
-+ wc->reg1shadow[x] = wctdm_getreg(wc, x, 29);
-+ break;
-+ case 12:
-+ /* Perform processing */
-+ if (wc->modtype[x] == MOD_TYPE_FXS) {
-+ wctdm_proslic_check_hook(wc, x);
-+ if (!(wc->intcount & 0xf0))
-+ wctdm_proslic_recheck_sanity(wc, x);
-+ } else if (wc->modtype[x] == MOD_TYPE_FXO) {
-+ wctdm_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ if (!(wc->intcount % 10000)) {
-+ /* Accept an alarm once per 10 seconds */
-+ for (x=0;x<wc->max_cards/*4*3*/;x++)
-+ if (wc->modtype[x] == MOD_TYPE_FXS) {
-+ if (wc->mod[x].fxs.palarms)
-+ wc->mod[x].fxs.palarms--;
-+ }
-+ }
-+ wctdm_receiveprep(wc, ints);
-+ wctdm_transmitprep(wc, ints);
-+ }
-+
-+ return IRQ_RETVAL(1);
-+
-+}
-+
-+static int wctdm_voicedaa_insane(struct wctdm *wc, int card)
-+{
-+ int blah;
-+ blah = wctdm_getreg(wc, card, 2);
-+ if (blah != 0x3)
-+ return -2;
-+ blah = wctdm_getreg(wc, card, 11);
-+ if (debug)
-+ printk(KERN_DEBUG "VoiceDAA System: %02x\n", blah & 0xf);
-+ return 0;
-+}
-+
-+static int wctdm_proslic_insane(struct wctdm *wc, int card)
-+{
-+ int blah,insane_report;
-+ insane_report=0;
-+
-+ blah = wctdm_getreg(wc, card, 0);
-+ if (debug)
-+ printk(KERN_DEBUG "ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf));
-+
-+#if 0
-+ if ((blah & 0x30) >> 4) {
-+ printk(KERN_DEBUG "ProSLIC on module %d is not a 3210.\n", card);
-+ return -1;
-+ }
-+#endif
-+ if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) {
-+ /* SLIC not loaded */
-+ return -1;
-+ }
-+ if ((blah & 0xf) < 2) {
-+ printk(KERN_NOTICE "ProSLIC 3210 version %d is too old\n", blah & 0xf);
-+ return -1;
-+ }
-+ if (wctdm_getreg(wc, card, 1) & 0x80)
-+ /* ProSLIC 3215, not a 3210 */
-+ wc->flags[card] |= FLAG_3215;
-+
-+ blah = wctdm_getreg(wc, card, 8);
-+ if (blah != 0x2) {
-+ printk(KERN_NOTICE "ProSLIC on module %d insane (1) %d should be 2\n", card, blah);
-+ return -1;
-+ } else if ( insane_report)
-+ printk(KERN_NOTICE "ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah);
-+
-+ blah = wctdm_getreg(wc, card, 64);
-+ if (blah != 0x0) {
-+ printk(KERN_NOTICE "ProSLIC on module %d insane (2)\n", card);
-+ return -1;
-+ } else if ( insane_report)
-+ printk(KERN_NOTICE "ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah);
-+
-+ blah = wctdm_getreg(wc, card, 11);
-+ if (blah != 0x33) {
-+ printk(KERN_NOTICE "ProSLIC on module %d insane (3)\n", card);
-+ return -1;
-+ } else if ( insane_report)
-+ printk(KERN_NOTICE "ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah);
-+
-+ /* Just be sure it's setup right. */
-+ wctdm_setreg(wc, card, 30, 0);
-+
-+ if (debug)
-+ printk(KERN_DEBUG "ProSLIC on module %d seems sane.\n", card);
-+ return 0;
-+}
-+
-+static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card)
-+{
-+ unsigned long origjiffies;
-+ unsigned char vbat;
-+
-+ /* Turn off linefeed */
-+ wctdm_setreg(wc, card, 64, 0);
-+
-+ /* Power down */
-+ wctdm_setreg(wc, card, 14, 0x10);
-+
-+ /* Wait for one second */
-+ origjiffies = jiffies;
-+
-+ while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) {
-+ if ((jiffies - origjiffies) >= (HZ/2))
-+ break;
-+ }
-+
-+ if (vbat < 0x06) {
-+ printk(KERN_NOTICE "Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card,
-+ 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ));
-+ return -1;
-+ } else if (debug) {
-+ printk(KERN_NOTICE "Post-leakage voltage: %d volts\n", 376 * vbat / 1000);
-+ }
-+ return 0;
-+}
-+
-+static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast)
-+{
-+ unsigned char vbat;
-+ unsigned long origjiffies;
-+ int lim;
-+
-+ /* Set period of DC-DC converter to 1/64 khz */
-+ wctdm_setreg(wc, card, 92, 0xff /* was 0xff */);
-+
-+ /* Wait for VBat to powerup */
-+ origjiffies = jiffies;
-+
-+ /* Disable powerdown */
-+ wctdm_setreg(wc, card, 14, 0);
-+
-+ /* If fast, don't bother checking anymore */
-+ if (fast)
-+ return 0;
-+
-+ while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) {
-+ /* Wait no more than 500ms */
-+ if ((jiffies - origjiffies) > HZ/2) {
-+ break;
-+ }
-+ }
-+
-+ if (vbat < 0xc0) {
-+ if (wc->proslic_power == PROSLIC_POWER_UNKNOWN)
-+ printk(KERN_NOTICE "ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE A1200P??\n",
-+ card, (int)(((jiffies - origjiffies) * 1000 / HZ)),
-+ vbat * 375);
-+ wc->proslic_power = PROSLIC_POWER_WARNED;
-+ return -1;
-+ } else if (debug) {
-+ printk(KERN_DEBUG "ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
-+ card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));
-+ }
-+ wc->proslic_power = PROSLIC_POWER_ON;
-+
-+ /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */
-+ /* If out of range, just set it to the default value */
-+ lim = (loopcurrent - 20) / 3;
-+ if ( loopcurrent > 41 ) {
-+ lim = 0;
-+ if (debug)
-+ printk(KERN_DEBUG "Loop current out of range! Setting to default 20mA!\n");
-+ }
-+ else if (debug)
-+ printk(KERN_DEBUG "Loop current set to %dmA!\n",(lim*3)+20);
-+ wctdm_setreg(wc,card,LOOP_I_LIMIT,lim);
-+
-+ /* Engage DC-DC converter */
-+ wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */);
-+#if 0
-+ origjiffies = jiffies;
-+ while(0x80 & wctdm_getreg(wc, card, 93)) {
-+ if ((jiffies - origjiffies) > 2 * HZ) {
-+ printk(KERN_DEBUG "Timeout waiting for DC-DC calibration on module %d\n", card);
-+ return -1;
-+ }
-+ }
-+
-+#if 0
-+ /* Wait a full two seconds */
-+ while((jiffies - origjiffies) < 2 * HZ);
-+
-+ /* Just check to be sure */
-+ vbat = wctdm_getreg(wc, card, 82);
-+ printk(KERN_DEBUG "ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
-+ card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));
-+#endif
-+#endif
-+ return 0;
-+
-+}
-+
-+static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card){
-+ unsigned long origjiffies;
-+ unsigned char i;
-+
-+ wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21
-+ wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21
-+ wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21
-+ wctdm_setreg(wc, card, 64, 0);//(0)
-+
-+ wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration.
-+ wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM
-+
-+ origjiffies=jiffies;
-+ while( wctdm_getreg(wc,card,96)!=0 ){
-+ if((jiffies-origjiffies)>80)
-+ return -1;
-+ }
-+//Initialized DR 98 and 99 to get consistant results.
-+// 98 and 99 are the results registers and the search should have same intial conditions.
-+
-+/*******************************The following is the manual gain mismatch calibration****************************/
-+/*******************************This is also available as a function *******************************************/
-+ // Delay 10ms
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<1);
-+ wctdm_proslic_setreg_indirect(wc, card, 88,0);
-+ wctdm_proslic_setreg_indirect(wc,card,89,0);
-+ wctdm_proslic_setreg_indirect(wc,card,90,0);
-+ wctdm_proslic_setreg_indirect(wc,card,91,0);
-+ wctdm_proslic_setreg_indirect(wc,card,92,0);
-+ wctdm_proslic_setreg_indirect(wc,card,93,0);
-+
-+ wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time
-+ wctdm_setreg(wc, card, 99,0x10);
-+
-+ for ( i=0x1f; i>0; i--)
-+ {
-+ wctdm_setreg(wc, card, 98,i);
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<4);
-+ if((wctdm_getreg(wc,card,88)) == 0)
-+ break;
-+ } // for
-+
-+ for ( i=0x1f; i>0; i--)
-+ {
-+ wctdm_setreg(wc, card, 99,i);
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<4);
-+ if((wctdm_getreg(wc,card,89)) == 0)
-+ break;
-+ }//for
-+
-+/*******************************The preceding is the manual gain mismatch calibration****************************/
-+/**********************************The following is the longitudinal Balance Cal***********************************/
-+ wctdm_setreg(wc,card,64,1);
-+ while((jiffies-origjiffies)<10); // Sleep 100?
-+
-+ wctdm_setreg(wc, card, 64, 0);
-+ wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal
-+ wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration
-+ wctdm_setreg(wc, card, 96,0x40);
-+
-+ wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */
-+
-+ wctdm_setreg(wc, card, 21, 0xFF);
-+ wctdm_setreg(wc, card, 22, 0xFF);
-+ wctdm_setreg(wc, card, 23, 0xFF);
-+
-+ /**The preceding is the longitudinal Balance Cal***/
-+ return(0);
-+
-+}
-+#if 1
-+static int wctdm_proslic_calibrate(struct wctdm *wc, int card)
-+{
-+ unsigned long origjiffies;
-+ int x;
-+ /* Perform all calibrations */
-+ wctdm_setreg(wc, card, 97, 0x1f);
-+
-+ /* Begin, no speedup */
-+ wctdm_setreg(wc, card, 96, 0x5f);
-+
-+ /* Wait for it to finish */
-+ origjiffies = jiffies;
-+ while(wctdm_getreg(wc, card, 96)) {
-+ if ((jiffies - origjiffies) > 2 * HZ) {
-+ printk(KERN_NOTICE "Timeout waiting for calibration of module %d\n", card);
-+ return -1;
-+ }
-+ }
-+
-+ if (debug) {
-+ /* Print calibration parameters */
-+ printk(KERN_DEBUG "Calibration Vector Regs 98 - 107: \n");
-+ for (x=98;x<108;x++) {
-+ printk(KERN_DEBUG "%d: %02x\n", x, wctdm_getreg(wc, card, x));
-+ }
-+ }
-+ return 0;
-+}
-+#endif
-+
-+static void wait_just_a_bit(int foo)
-+{
-+ long newjiffies;
-+ newjiffies = jiffies + foo;
-+ while(jiffies < newjiffies);
-+}
-+
-+/*********************************************************************
-+ * Set the hwgain on the analog modules
-+ *
-+ * card = the card position for this module (0-23)
-+ * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35)
-+ * tx = (0 for rx; 1 for tx)
-+ *
-+ *******************************************************************/
-+static int wctdm_set_hwgain(struct wctdm *wc, int card, __s32 gain, __u32 tx)
-+{
-+ if (!(wc->modtype[card] == MOD_TYPE_FXO)) {
-+ printk(KERN_NOTICE "Cannot adjust gain. Unsupported module type!\n");
-+ return -1;
-+ }
-+ if (tx) {
-+ if (debug)
-+ printk(KERN_DEBUG "setting FXO tx gain for card=%d to %d\n", card, gain);
-+ if (gain >= -150 && gain <= 0) {
-+ wctdm_setreg(wc, card, 38, 16 + (gain/-10));
-+ wctdm_setreg(wc, card, 40, 16 + (-gain%10));
-+ } else if (gain <= 120 && gain > 0) {
-+ wctdm_setreg(wc, card, 38, gain/10);
-+ wctdm_setreg(wc, card, 40, (gain%10));
-+ } else {
-+ printk(KERN_INFO "FXO tx gain is out of range (%d)\n", gain);
-+ return -1;
-+ }
-+ } else { /* rx */
-+ if (debug)
-+ printk(KERN_DEBUG "setting FXO rx gain for card=%d to %d\n", card, gain);
-+ if (gain >= -150 && gain <= 0) {
-+ wctdm_setreg(wc, card, 39, 16+ (gain/-10));
-+ wctdm_setreg(wc, card, 41, 16 + (-gain%10));
-+ } else if (gain <= 120 && gain > 0) {
-+ wctdm_setreg(wc, card, 39, gain/10);
-+ wctdm_setreg(wc, card, 41, (gain%10));
-+ } else {
-+ printk(KERN_INFO "FXO rx gain is out of range (%d)\n", gain);
-+ return -1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane)
-+{
-+ unsigned char reg16=0, reg26=0, reg30=0, reg31=0;
-+ unsigned int tsi;
-+ long newjiffies;
-+ wc->modtype[card] = MOD_TYPE_FXO;
-+ /* Sanity check the ProSLIC */
-+ reset_spi(wc, card);
-+ if (!sane && wctdm_voicedaa_insane(wc, card))
-+ return -2;
-+
-+ /* Software reset */
-+ wctdm_setreg(wc, card, 1, 0x80);
-+
-+ /* Wait just a bit */
-+ wait_just_a_bit(HZ/10);
-+
-+ /* Enable PCM, ulaw */
-+ if (alawoverride)
-+ wctdm_setreg(wc, card, 33, 0x20);
-+ else
-+ wctdm_setreg(wc, card, 33, 0x28);
-+
-+ /* Set On-hook speed, Ringer impedence, and ringer threshold */
-+ reg16 |= (fxo_modes[_opermode].ohs << 6);
-+ reg16 |= (fxo_modes[_opermode].rz << 1);
-+ reg16 |= (fxo_modes[_opermode].rt);
-+ wctdm_setreg(wc, card, 16, reg16);
-+
-+ if(fwringdetect) {
-+ /* Enable ring detector full-wave rectifier mode */
-+ wctdm_setreg(wc, card, 18, 2);
-+ wctdm_setreg(wc, card, 24, 0);
-+ } else {
-+ /* Set to the device defaults */
-+ wctdm_setreg(wc, card, 18, 0);
-+ wctdm_setreg(wc, card, 24, 0x19);
-+ }
-+
-+ /* Set DC Termination:
-+ Tip/Ring voltage adjust, minimum operational current, current limitation */
-+ reg26 |= (fxo_modes[_opermode].dcv << 6);
-+ reg26 |= (fxo_modes[_opermode].mini << 4);
-+ reg26 |= (fxo_modes[_opermode].ilim << 1);
-+ wctdm_setreg(wc, card, 26, reg26);
-+
-+ /* Set AC Impedence */
-+ reg30 = (fxofullscale==1) ? (fxo_modes[_opermode].acim|0x10) : (fxo_modes[_opermode].acim);
-+ wctdm_setreg(wc, card, 30, reg30);
-+
-+ /* Misc. DAA parameters */
-+ if (fastpickup)
-+ reg31 = 0xb3;
-+ else
-+ reg31 = 0xa3;
-+
-+ reg31 |= (fxo_modes[_opermode].ohs2 << 3);
-+ wctdm_setreg(wc, card, 31, reg31);
-+
-+ if((wc->fwversion&0x0f)==6)
-+ {
-+ tsi = (3-(card%4))*8 + (card/4) *128;
-+ wctdm_setreg(wc, card, 34, tsi&0xff);
-+ wctdm_setreg(wc, card, 35, (tsi>>8)&0x3);
-+ wctdm_setreg(wc, card, 36, (tsi+1)&0xff);
-+ wctdm_setreg(wc, card, 37, ((tsi+1)>>8)&0x3);
-+ }
-+ else
-+ {
-+ /* Set Transmit/Receive timeslot */
-+ //printk("set card %d to %d\n", card, (3-(card%4)) * 8 + (card/4) * 64);
-+ wctdm_setreg(wc, card, 34, (3-(card%4)) * 8 + (card/4) * 64);
-+ wctdm_setreg(wc, card, 35, 0x00);
-+ wctdm_setreg(wc, card, 36, (3-(card%4)) * 8 + (card/4) * 64);
-+ wctdm_setreg(wc, card, 37, 0x00);
-+ }
-+
-+ /* Enable ISO-Cap */
-+ wctdm_setreg(wc, card, 6, 0x00);
-+
-+ if (fastpickup)
-+ wctdm_setreg(wc, card, 17, wctdm_getreg(wc, card, 17) | 0x20);
-+
-+ /* Wait 1000ms for ISO-cap to come up */
-+ newjiffies = jiffies;
-+ newjiffies += 2 * HZ;
-+ while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0))
-+ wait_just_a_bit(HZ/10);
-+
-+ if (!(wctdm_getreg(wc, card, 11) & 0xf0)) {
-+ printk(KERN_NOTICE "VoiceDAA did not bring up ISO link properly!\n");
-+ return -1;
-+ }
-+ if (debug)
-+ printk(KERN_DEBUG "ISO-Cap is now up, line side: %02x rev %02x\n",
-+ wctdm_getreg(wc, card, 11) >> 4,
-+ (wctdm_getreg(wc, card, 13) >> 2) & 0xf);
-+ /* Enable on-hook line monitor */
-+ wctdm_setreg(wc, card, 5, 0x08);
-+
-+ /* Take values for fxotxgain and fxorxgain and apply them to module */
-+ wctdm_set_hwgain(wc, card, fxotxgain, 1);
-+ wctdm_set_hwgain(wc, card, fxorxgain, 0);
-+
-+ /* NZ -- crank the tx gain up by 7 dB */
-+ if (!strcmp(fxo_modes[_opermode].name, "NEWZEALAND")) {
-+ printk(KERN_INFO "Adjusting gain\n");
-+ wctdm_set_hwgain(wc, card, 7, 1);
-+ }
-+
-+ if(debug)
-+ printk(KERN_DEBUG "DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16)?-(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16)? -(wctdm_getreg(wc, card, 40) - 16):wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16)? -(wctdm_getreg(wc, card, 39) - 16) : wctdm_getreg(wc, card, 39),(wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16):wctdm_getreg(wc, card, 41));
-+
-+ return 0;
-+
-+}
-+
-+static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane)
-+{
-+
-+ unsigned short tmp[5];
-+ unsigned char r19, r9;
-+ int x, tsi;
-+ int fxsmode=0;
-+// int tmpcard;
-+
-+ /* Sanity check the ProSLIC */
-+ if (!sane && wctdm_proslic_insane(wc, card))
-+ return -2;
-+
-+ /* By default, don't send on hook */
-+ if (reversepolarity)
-+ wc->mod[card].fxs.idletxhookstate = 5;
-+ else
-+ wc->mod[card].fxs.idletxhookstate = 1;
-+
-+ if (sane) {
-+ /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */
-+ wctdm_setreg(wc, card, 14, 0x10);
-+ }
-+
-+ if (wctdm_proslic_init_indirect_regs(wc, card)) {
-+ printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card);
-+ return -1;
-+ }
-+
-+ /* Clear scratch pad area */
-+ wctdm_proslic_setreg_indirect(wc, card, 97,0);
-+
-+ /* Clear digital loopback */
-+ wctdm_setreg(wc, card, 8, 0);
-+
-+ /* Revision C optimization */
-+ wctdm_setreg(wc, card, 108, 0xeb);
-+
-+ /* Disable automatic VBat switching for safety to prevent
-+ Q7 from accidently turning on and burning out. */
-+ wctdm_setreg(wc, card, 67, 0x07); /* Note, if pulse dialing has problems at high REN loads
-+ change this to 0x17 */
-+
-+ /* Turn off Q7 */
-+ wctdm_setreg(wc, card, 66, 1);
-+
-+ /* Flush ProSLIC digital filters by setting to clear, while
-+ saving old values */
-+ for (x=0;x<5;x++) {
-+ tmp[x] = wctdm_proslic_getreg_indirect(wc, card, x + 35);
-+ wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000);
-+ }
-+
-+ /* Power up the DC-DC converter */
-+ if (wctdm_powerup_proslic(wc, card, fast)) {
-+ printk(KERN_NOTICE "Unable to do INITIAL ProSLIC powerup on module %d\n", card);
-+ return -1;
-+ }
-+
-+ if (!fast) {
-+
-+ /* Check for power leaks */
-+ if (wctdm_proslic_powerleak_test(wc, card)) {
-+ printk(KERN_NOTICE "ProSLIC module %d failed leakage test. Check for short circuit\n", card);
-+ }
-+ /* Power up again */
-+ if (wctdm_powerup_proslic(wc, card, fast)) {
-+ printk(KERN_NOTICE "Unable to do FINAL ProSLIC powerup on module %d\n", card);
-+ return -1;
-+ }
-+#ifndef NO_CALIBRATION
-+ /* Perform calibration */
-+ if(manual) {
-+ if (wctdm_proslic_manual_calibrate(wc, card)) {
-+ //printk(KERN_NOTICE "Proslic failed on Manual Calibration\n");
-+ if (wctdm_proslic_manual_calibrate(wc, card)) {
-+ printk(KERN_NOTICE "Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n");
-+ return -1;
-+ }
-+ printk(KERN_NOTICE "Proslic Passed Manual Calibration on Second Attempt\n");
-+ }
-+ }
-+ else {
-+ if(wctdm_proslic_calibrate(wc, card)) {
-+ //printk(KERN_NOTICE "ProSlic died on Auto Calibration.\n");
-+ if (wctdm_proslic_calibrate(wc, card)) {
-+ printk(KERN_NOTICE "Proslic Failed on Second Attempt to Auto Calibrate\n");
-+ return -1;
-+ }
-+ printk(KERN_NOTICE "Proslic Passed Auto Calibration on Second Attempt\n");
-+ }
-+ }
-+ /* Perform DC-DC calibration */
-+ wctdm_setreg(wc, card, 93, 0x99);
-+ r19 = wctdm_getreg(wc, card, 107);
-+ if ((r19 < 0x2) || (r19 > 0xd)) {
-+ printk(KERN_NOTICE "DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19);
-+ wctdm_setreg(wc, card, 107, 0x8);
-+ }
-+
-+ /* Save calibration vectors */
-+ for (x=0;x<NUM_CAL_REGS;x++)
-+ wc->mod[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x);
-+#endif
-+
-+ } else {
-+ /* Restore calibration registers */
-+ for (x=0;x<NUM_CAL_REGS;x++)
-+ wctdm_setreg(wc, card, 96 + x, wc->mod[card].fxs.calregs.vals[x]);
-+ }
-+ /* Calibration complete, restore original values */
-+ for (x=0;x<5;x++) {
-+ wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]);
-+ }
-+
-+ if (wctdm_proslic_verify_indirect_regs(wc, card)) {
-+ printk(KERN_INFO "Indirect Registers failed verification.\n");
-+ return -1;
-+ }
-+
-+
-+#if 0
-+ /* Disable Auto Power Alarm Detect and other "features" */
-+ wctdm_setreg(wc, card, 67, 0x0e);
-+ blah = wctdm_getreg(wc, card, 67);
-+#endif
-+
-+#if 0
-+ if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix
-+ printk(KERN_INFO "ProSlic IndirectReg Died.\n");
-+ return -1;
-+ }
-+#endif
-+
-+ if (alawoverride)
-+ wctdm_setreg(wc, card, 1, 0x20);
-+ else
-+ wctdm_setreg(wc, card, 1, 0x28);
-+ if((wc->fwversion&0x0f)==6)
-+ {
-+ tsi = (3-(card%4))* 8 + (card/4) *128;
-+ wctdm_setreg(wc, card, 2, (tsi)&0xff); // Tx Start count low byte 0
-+ wctdm_setreg(wc, card, 3, ((tsi)>>8)&0x3); // Tx Start count high byte 0
-+ wctdm_setreg(wc, card, 4, (tsi+1)&0xff); // Rx Start count low byte 0
-+ wctdm_setreg(wc, card, 5, ((tsi+1)>>8)&0x3); // Rx Start count high byte 0
-+ }
-+ else
-+ {
-+ // U-Law 8-bit interface
-+ wctdm_setreg(wc, card, 2, (3-(card%4)) * 8 + (card/4) * 64); // Tx Start count low byte 0
-+ wctdm_setreg(wc, card, 3, 0); // Tx Start count high byte 0
-+ wctdm_setreg(wc, card, 4, (3-(card%4)) * 8 + (card/4) * 64); // Rx Start count low byte 0
-+ wctdm_setreg(wc, card, 5, 0); // Rx Start count high byte 0
-+ }
-+ wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt
-+ wctdm_setreg(wc, card, 19, 0xff);
-+ wctdm_setreg(wc, card, 20, 0xff);
-+ wctdm_setreg(wc, card, 73, 0x04);
-+ if (fxshonormode) {
-+ fxsmode = acim2tiss[fxo_modes[_opermode].acim];
-+ wctdm_setreg(wc, card, 10, 0x08 | fxsmode);
-+ if (fxo_modes[_opermode].ring_osc)
-+ wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc);
-+ if (fxo_modes[_opermode].ring_x)
-+ wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x);
-+ }
-+ if (lowpower)
-+ wctdm_setreg(wc, card, 72, 0x10);
-+
-+#if 0
-+ wctdm_setreg(wc, card, 21, 0x00); // enable interrupt
-+ wctdm_setreg(wc, card, 22, 0x02); // Loop detection interrupt
-+ wctdm_setreg(wc, card, 23, 0x01); // DTMF detection interrupt
-+#endif
-+
-+#if 0
-+ /* Enable loopback */
-+ wctdm_setreg(wc, card, 8, 0x2);
-+ wctdm_setreg(wc, card, 14, 0x0);
-+ wctdm_setreg(wc, card, 64, 0x0);
-+ wctdm_setreg(wc, card, 1, 0x08);
-+#endif
-+
-+ if (fastringer) {
-+ /* Speed up Ringer */
-+ wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d);
-+ wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9);
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ wctdm_setreg(wc, card, 74, 0x3f);
-+ if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247))
-+ return -1;
-+ printk(KERN_INFO "Boosting fast ringer on slot %d (89V peak)\n", card + 1);
-+ } else if (lowpower) {
-+ if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b))
-+ return -1;
-+ printk(KERN_INFO "Reducing fast ring power on slot %d (50V peak)\n", card + 1);
-+ } else
-+ printk(KERN_INFO "Speeding up ringer on slot %d (25Hz)\n", card + 1);
-+ } else {
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ wctdm_setreg(wc, card, 74, 0x3f);
-+ if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1))
-+ return -1;
-+ printk(KERN_INFO "Boosting ringer on slot %d (89V peak)\n", card + 1);
-+ } else if (lowpower) {
-+ if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108))
-+ return -1;
-+ printk(KERN_INFO "Reducing ring power on slot %d (50V peak)\n", card + 1);
-+ }
-+ }
-+
-+ if(fxstxgain || fxsrxgain) {
-+ r9 = wctdm_getreg(wc, card, 9);
-+ switch (fxstxgain) {
-+
-+ case 35:
-+ r9+=8;
-+ break;
-+ case -35:
-+ r9+=4;
-+ break;
-+ case 0:
-+ break;
-+ }
-+
-+ switch (fxsrxgain) {
-+
-+ case 35:
-+ r9+=2;
-+ break;
-+ case -35:
-+ r9+=1;
-+ break;
-+ case 0:
-+ break;
-+ }
-+ wctdm_setreg(wc,card,9,r9);
-+ }
-+
-+ if(debug)
-+ printk(KERN_DEBUG "DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
-+
-+ wctdm_setreg(wc, card, 64, 0x01);
-+ return 0;
-+}
-+
-+
-+static int wctdm_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data)
-+{
-+ struct wctdm_stats stats;
-+ struct wctdm_regs regs;
-+ struct wctdm_regop regop;
-+ struct wctdm_echo_coefs echoregs;
-+ struct dahdi_hwgain hwgain;
-+ struct wctdm *wc = chan->pvt;
-+ int x;
-+ switch (cmd) {
-+ case DAHDI_ONHOOKTRANSFER:
-+ if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
-+ return -EINVAL;
-+ if (get_user(x, (__user int *)data))
-+ return -EFAULT;
-+ wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3;
-+ if (reversepolarity)
-+ wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6; /* OHT mode when idle */
-+ else
-+ wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2;
-+ if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) {
-+ /* Apply the change if appropriate */
-+ if (reversepolarity)
-+ wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6;
-+ else
-+ wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x2;
-+ wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
-+ }
-+ break;
-+ case DAHDI_SETPOLARITY:
-+ if (get_user(x, (__user int *)data))
-+ return -EFAULT;
-+ if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
-+ return -EINVAL;
-+ /* Can't change polarity while ringing or when open */
-+ if ((wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x04) ||
-+ (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00))
-+ return -EINVAL;
-+
-+ if ((x && !reversepolarity) || (!x && reversepolarity))
-+ wc->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04;
-+ else
-+ wc->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04;
-+ wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
-+ break;
-+ case WCTDM_GET_STATS:
-+ if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-+ stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376;
-+ stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376;
-+ stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376;
-+ } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
-+ stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000;
-+ stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000;
-+ stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000;
-+ } else
-+ return -EINVAL;
-+ if (copy_to_user((__user void *)data, &stats, sizeof(stats)))
-+ return -EFAULT;
-+ break;
-+ case WCTDM_GET_REGS:
-+ if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-+ for (x=0;x<NUM_INDIRECT_REGS;x++)
-+ regs.indirect[x] = wctdm_proslic_getreg_indirect(wc, chan->chanpos -1, x);
-+ for (x=0;x<NUM_REGS;x++)
-+ regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x);
-+ } else {
-+ memset(&regs, 0, sizeof(regs));
-+ for (x=0;x<NUM_FXO_REGS;x++)
-+ regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x);
-+ }
-+ if (copy_to_user((__user void *)data, &regs, sizeof(regs)))
-+ return -EFAULT;
-+ break;
-+ case WCTDM_SET_REG:
-+ if (copy_from_user(&regop, (__user void *)data, sizeof(regop)))
-+ return -EFAULT;
-+ if (regop.indirect) {
-+ if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
-+ return -EINVAL;
-+ printk(KERN_INFO "Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos);
-+ wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val);
-+ } else {
-+ regop.val &= 0xff;
-+ printk(KERN_INFO "Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos);
-+ wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val);
-+ }
-+ break;
-+ case WCTDM_SET_ECHOTUNE:
-+ printk(KERN_INFO "-- Setting echo registers: \n");
-+ if (copy_from_user(&echoregs, (__user void *)data, sizeof(echoregs)))
-+ return -EFAULT;
-+
-+ if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
-+ /* Set the ACIM register */
-+ wctdm_setreg(wc, chan->chanpos - 1, 30, (fxofullscale==1) ? (echoregs.acim|0x10) : echoregs.acim);
-+
-+ /* Set the digital echo canceller registers */
-+ wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1);
-+ wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2);
-+ wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3);
-+ wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4);
-+ wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5);
-+ wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6);
-+ wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7);
-+ wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8);
-+
-+ printk(KERN_INFO "-- Set echo registers successfully\n");
-+
-+ break;
-+ } else {
-+ return -EINVAL;
-+
-+ }
-+ break;
-+ case DAHDI_SET_HWGAIN:
-+ if (copy_from_user(&hwgain, (__user void *) data, sizeof(hwgain)))
-+ return -EFAULT;
-+
-+ wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx);
-+
-+ if (debug)
-+ printk(KERN_DEBUG "Setting hwgain on channel %d to %d for %s direction\n",
-+ chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx");
-+ break;
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+
-+}
-+
-+static int wctdm_open(struct dahdi_chan *chan)
-+{
-+ struct wctdm *wc = chan->pvt;
-+ if (!(wc->cardflag & (1 << (chan->chanpos - 1))))
-+ return -ENODEV;
-+ if (wc->dead)
-+ return -ENODEV;
-+ wc->usecount++;
-+
-+ /*MOD_INC_USE_COUNT; */
-+ try_module_get(THIS_MODULE);
-+ return 0;
-+}
-+
-+static inline struct wctdm *wctdm_from_span(struct dahdi_span *span)
-+{
-+ return container_of(span, struct wctdm, span);
-+}
-+
-+static int wctdm_watchdog(struct dahdi_span *span, int event)
-+{
-+ printk(KERN_INFO "opvxa1200: Restarting DMA\n");
-+ wctdm_restart_dma(wctdm_from_span(span));
-+ return 0;
-+}
-+
-+static int wctdm_close(struct dahdi_chan *chan)
-+{
-+ struct wctdm *wc = chan->pvt;
-+ wc->usecount--;
-+
-+ /*MOD_DEC_USE_COUNT;*/
-+ module_put(THIS_MODULE);
-+
-+ if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-+ if (reversepolarity)
-+ wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 5;
-+ else
-+ wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 1;
-+ }
-+ /* If we're dead, release us now */
-+ if (!wc->usecount && wc->dead)
-+ wctdm_release(wc);
-+ return 0;
-+}
-+
-+static int wctdm_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
-+{
-+ struct wctdm *wc = chan->pvt;
-+ int reg=0;
-+ if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
-+ /* XXX Enable hooksig for FXO XXX */
-+ switch(txsig) {
-+ case DAHDI_TXSIG_START:
-+ case DAHDI_TXSIG_OFFHOOK:
-+ wc->mod[chan->chanpos - 1].fxo.offhook = 1;
-+ wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9);
-+ if(cidbeforering)
-+ {
-+ wc->cid_state[chan->chanpos - 1] = CID_STATE_IDLE;
-+ wc->cid_history_clone_cnt[chan->chanpos - 1] = 0;
-+ wc->cid_history_ptr[chan->chanpos - 1] = 0;
-+ memset(wc->cid_history_buf[chan->chanpos - 1], DAHDI_LIN2X(0, chan), cidbuflen * DAHDI_MAX_CHUNKSIZE);
-+ }
-+ break;
-+ case DAHDI_TXSIG_ONHOOK:
-+ wc->mod[chan->chanpos - 1].fxo.offhook = 0;
-+ wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8);
-+ break;
-+ default:
-+ printk(KERN_NOTICE "wcfxo: Can't set tx state to %d\n", txsig);
-+ }
-+ } else {
-+ switch(txsig) {
-+ case DAHDI_TXSIG_ONHOOK:
-+ switch(chan->sig) {
-+ case DAHDI_SIG_EM:
-+ case DAHDI_SIG_FXOKS:
-+ case DAHDI_SIG_FXOLS:
-+ wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate;
-+ break;
-+ case DAHDI_SIG_FXOGS:
-+ wc->mod[chan->chanpos-1].fxs.lasttxhook = 3;
-+ break;
-+ }
-+ break;
-+ case DAHDI_TXSIG_OFFHOOK:
-+ switch(chan->sig) {
-+ case DAHDI_SIG_EM:
-+ wc->mod[chan->chanpos-1].fxs.lasttxhook = 5;
-+ break;
-+ default:
-+ wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate;
-+ break;
-+ }
-+ break;
-+ case DAHDI_TXSIG_START:
-+ wc->mod[chan->chanpos-1].fxs.lasttxhook = 4;
-+ break;
-+ case DAHDI_TXSIG_KEWL:
-+ wc->mod[chan->chanpos-1].fxs.lasttxhook = 0;
-+ break;
-+ default:
-+ printk(KERN_NOTICE "opvxa1200: Can't set tx state to %d\n", txsig);
-+ }
-+ if (debug)
-+ printk(KERN_DEBUG "Setting FXS hook state to %d (%02x)\n", txsig, reg);
-+
-+#if 1
-+ wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos-1].fxs.lasttxhook);
-+#endif
-+ }
-+ return 0;
-+}
-+
-+#ifdef DAHDI_SPAN_OPS
-+static const struct dahdi_span_ops wctdm_span_ops = {
-+ .owner = THIS_MODULE,
-+ .hooksig = wctdm_hooksig,
-+ .open = wctdm_open,
-+ .close = wctdm_close,
-+ .ioctl = wctdm_ioctl,
-+ .watchdog = wctdm_watchdog,
-+};
-+#endif
-+
-+static int wctdm_initialize(struct wctdm *wc)
-+{
-+ int x;
-+
-+ wc->ddev = dahdi_create_device(); //Dennis
-+ if (!wc->ddev)
-+ return -ENOMEM;
-+
-+ /* Dahdi stuff */
-+ sprintf(wc->span.name, "OPVXA1200/%d", wc->pos);
-+ snprintf(wc->span.desc, sizeof(wc->span.desc)-1, "%s Board %d", wc->variety, wc->pos + 1);
-+
-+ wc->ddev->location = kasprintf(GFP_KERNEL, //Dennis
-+ "PCI Bus %02d Slot %02d",
-+ wc->dev->bus->number,
-+ PCI_SLOT(wc->dev->devfn) + 1);
-+ if (!wc->ddev->location) {
-+ dahdi_free_device(wc->ddev);
-+ wc->ddev = NULL;
-+ return -ENOMEM;
-+ }
-+
-+ wc->ddev->manufacturer = "OpenVox"; //Dennis
-+ wc->ddev->devicetype = wc->variety;
-+
-+ if (alawoverride) {
-+ printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
-+ wc->span.deflaw = DAHDI_LAW_ALAW;
-+ } else
-+ wc->span.deflaw = DAHDI_LAW_MULAW;
-+
-+ x = __wctdm_getcreg(wc, WC_VER);
-+ wc->fwversion = x;
-+ if( x & FLAG_A800)
-+ {
-+ wc->card_name = A800P_Name;
-+ wc->max_cards = 8;
-+ }
-+ else
-+ {
-+ wc->card_name = A1200P_Name;
-+ wc->max_cards = 12;
-+ }
-+
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ sprintf(wc->chans[x]->name, "OPVXA1200/%d/%d", wc->pos, x);
-+ wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR;
-+ wc->chans[x]->sigcap |= DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR;
-+ wc->chans[x]->chanpos = x+1;
-+ wc->chans[x]->pvt = wc;
-+ }
-+
-+#ifdef DAHDI_SPAN_MODULE
-+ wc->span.owner = THIS_MODULE;
-+#endif
-+
-+#ifdef DAHDI_SPAN_OPS
-+ wc->span.ops = &wctdm_span_ops;
-+#else
-+ wc->span.hooksig = wctdm_hooksig,
-+ wc->span.watchdog = wctdm_watchdog,
-+ wc->span.open = wctdm_open;
-+ wc->span.close = wctdm_close;
-+ wc->span.ioctl = wctdm_ioctl;
-+ wc->span.pvt = wc;
-+#endif
-+ wc->span.chans = wc->chans;
-+ wc->span.channels = wc->max_cards; /*MAX_NUM_CARDS;*/
-+ wc->span.flags = DAHDI_FLAG_RBS;
-+// init_waitqueue_head(&wc->span.maintq);
-+ list_add_tail(&wc->span.device_node, &wc->ddev->spans);
-+ if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
-+ printk(KERN_NOTICE "Unable to register span with Dahdi\n");
-+ kfree(wc->ddev->location);
-+ dahdi_free_device(wc->ddev);
-+ wc->ddev = NULL;
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static void wctdm_post_initialize(struct wctdm *wc)
-+{
-+ int x;
-+
-+ /* Finalize signalling */
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if (wc->cardflag & (1 << x)) {
-+ if (wc->modtype[x] == MOD_TYPE_FXO)
-+ wc->chans[x]->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR;
-+ else
-+ wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR;
-+ } else if (!(wc->chans[x]->sigcap & DAHDI_SIG_BROKEN)) {
-+ wc->chans[x]->sigcap = 0;
-+ }
-+ }
-+}
-+
-+static int wctdm_hardware_init(struct wctdm *wc)
-+{
-+ /* Hardware stuff */
-+ unsigned char ver;
-+ unsigned char x,y;
-+ int failed;
-+ long origjiffies; //ML.
-+
-+ /* Signal Reset */
-+ printk("before raise reset\n");
-+ outb(0x00, wc->ioaddr + WC_CNTL);
-+ /* Wait for 1 second */
-+ origjiffies = jiffies;
-+ while(1)
-+ {
-+ if ((jiffies-origjiffies) >= (HZ))
-+ break;;
-+ }
-+ outb(0x01, wc->ioaddr + WC_CNTL);
-+ origjiffies = jiffies;
-+ while(1)
-+ {
-+ if ((jiffies-origjiffies) >= (HZ/2))
-+ break;;
-+ }
-+
-+ /* printk(KERN_INFO "after raise reset\n");*/
-+
-+ /* Check OpenVox chip */
-+ x=inb(wc->ioaddr + WC_CNTL);
-+ ver = __wctdm_getcreg(wc, WC_VER);
-+ wc->fwversion = ver;
-+ /*if( ver & FLAG_A800)
-+ {
-+ wc->card_name = A800P_Name;
-+ wc->max_cards = 8;
-+ }
-+ else
-+ {
-+ wc->card_name = A1200P_Name;
-+ wc->max_cards = 12;
-+ }*/
-+ printk(KERN_NOTICE "OpenVox %s version: %01x.%01x\n", wc->card_name, (ver&(~FLAG_A800))>>4, ver&0x0f);
-+
-+ failed = 0;
-+ if (ver != 0x00) {
-+ for (x=0;x<16;x++) {
-+ /* Test registers */
-+ __wctdm_setcreg(wc, WC_CS, x);
-+ y = __wctdm_getcreg(wc, WC_CS) & 0x0f;
-+ if (x != y) {
-+ printk(KERN_INFO "%02x != %02x\n", x, y);
-+ failed++;
-+ }
-+ }
-+
-+ if (!failed) {
-+ printk(KERN_INFO "OpenVox %s passed register test\n", wc->card_name);
-+ } else {
-+ printk(KERN_NOTICE "OpenVox %s failed register test\n", wc->card_name);
-+ return -1;
-+ }
-+ } else {
-+ printk(KERN_INFO "No OpenVox chip %02x\n", ver);
-+ }
-+
-+ if (spibyhw)
-+ __wctdm_setcreg(wc, WC_SPICTRL, BIT_SPI_BYHW); // spi controled by hw MiaoLin;
-+ else
-+ __wctdm_setcreg(wc, WC_SPICTRL, 0);
-+
-+ /* Reset PCI Interface chip and registers (and serial) */
-+ outb(0x06, wc->ioaddr + WC_CNTL);
-+ /* Setup our proper outputs for when we switch for our "serial" port */
-+ wc->ios = BIT_CS | BIT_SCLK | BIT_SDI;
-+
-+ outb(wc->ios, wc->ioaddr + WC_AUXD);
-+
-+ /* Set all to outputs except AUX 5, which is an input */
-+ outb(0xdf, wc->ioaddr + WC_AUXC);
-+
-+ /* Select alternate function for AUX0 */ /* Useless in OpenVox by MiaoLin. */
-+ /* outb(0x4, wc->ioaddr + WC_AUXFUNC); */
-+
-+ /* Wait 1/4 of a sec */
-+ wait_just_a_bit(HZ/4);
-+
-+ /* Back to normal, with automatic DMA wrap around */
-+ outb(0x30 | 0x01, wc->ioaddr + WC_CNTL);
-+ wc->ledstate = 0;
-+ wctdm_set_led(wc, 0, 0);
-+
-+ /* Make sure serial port and DMA are out of reset */
-+ outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL);
-+
-+ /* Configure serial port for MSB->LSB operation */
-+ outb(0xc1, wc->ioaddr + WC_SERCTL);
-+
-+ /* Delay FSC by 0 so it's properly aligned */
-+ outb(0x01, wc->ioaddr + WC_FSCDELAY); /* Modify to 1 by MiaoLin */
-+
-+ /* Setup DMA Addresses */
-+ outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */
-+ outl(wc->writedma + DAHDI_CHUNKSIZE * 4 * 4 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */
-+ outl(wc->writedma + DAHDI_CHUNKSIZE * 8 * 4 - 4, wc->ioaddr + WC_DMAWE); /* End */
-+
-+ outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */
-+ outl(wc->readdma + DAHDI_CHUNKSIZE * 4 * 4 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */
-+ outl(wc->readdma + DAHDI_CHUNKSIZE * 8 * 4 - 4, wc->ioaddr + WC_DMARE); /* End */
-+
-+ /* Clear interrupts */
-+ outb(0xff, wc->ioaddr + WC_INTSTAT);
-+
-+ /* Wait 1/4 of a second more */
-+ wait_just_a_bit(HZ/4);
-+
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ int sane=0,ret=0,readi=0;
-+#if 1
-+ touch_softlockup_watchdog(); // avoid showing CPU softlock message
-+ /* Init with Auto Calibration */
-+ if (!(ret=wctdm_init_proslic(wc, x, 0, 0, sane))) {
-+ wc->cardflag |= (1 << x);
-+ if (debug) {
-+ readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
-+ printk("Proslic module %d loop current is %dmA\n",x,
-+ ((readi*3)+20));
-+ }
-+ printk(KERN_INFO "Module %d: Installed -- AUTO FXS/DPO\n",x);
-+ wctdm_set_led(wc, (unsigned int)x, 1);
-+ } else {
-+ if(ret!=-2) {
-+ sane=1;
-+
-+ printk(KERN_INFO "Init ProSlic with Manual Calibration \n");
-+ /* Init with Manual Calibration */
-+ if (!wctdm_init_proslic(wc, x, 0, 1, sane)) {
-+ wc->cardflag |= (1 << x);
-+ if (debug) {
-+ readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
-+ printk("Proslic module %d loop current is %dmA\n",x,
-+ ((readi*3)+20));
-+ }
-+ printk(KERN_INFO "Module %d: Installed -- MANUAL FXS\n",x);
-+ } else {
-+ printk(KERN_NOTICE "Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC");
-+ wc->chans[x]->sigcap = __DAHDI_SIG_FXO | DAHDI_SIG_BROKEN;
-+ }
-+ } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) {
-+ wc->cardflag |= (1 << x);
-+ printk(KERN_INFO "Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name);
-+ wctdm_set_led(wc, (unsigned int)x, 1);
-+ } else
-+ printk(KERN_NOTICE "Module %d: Not installed\n", x);
-+ }
-+#endif
-+ }
-+
-+ /* Return error if nothing initialized okay. */
-+ if (!wc->cardflag && !timingonly)
-+ return -1;
-+ /*__wctdm_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1); */ /* removed by MiaoLin */
-+ return 0;
-+}
-+
-+static void wctdm_enable_interrupts(struct wctdm *wc)
-+{
-+ /* Clear interrupts */
-+ outb(0xff, wc->ioaddr + WC_INTSTAT);
-+
-+ /* Enable interrupts (we care about all of them) */
-+ //outb(0x3c, wc->ioaddr + WC_MASK0);
-+ outb(0x33, wc->ioaddr + WC_MASK0);
-+ /* No external interrupts */
-+ outb(0x00, wc->ioaddr + WC_MASK1);
-+}
-+
-+static void wctdm_restart_dma(struct wctdm *wc)
-+{
-+ /* Reset Master and TDM */
-+ outb(0x01, wc->ioaddr + WC_CNTL);
-+ outb(0x01, wc->ioaddr + WC_OPER);
-+}
-+
-+static void wctdm_start_dma(struct wctdm *wc)
-+{
-+ /* Reset Master and TDM */
-+ outb(0x0f, wc->ioaddr + WC_CNTL);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ outb(0x01, wc->ioaddr + WC_CNTL);
-+ outb(0x01, wc->ioaddr + WC_OPER);
-+}
-+
-+static void wctdm_stop_dma(struct wctdm *wc)
-+{
-+ outb(0x00, wc->ioaddr + WC_OPER);
-+}
-+
-+static void wctdm_reset_tdm(struct wctdm *wc)
-+{
-+ /* Reset TDM */
-+ outb(0x0f, wc->ioaddr + WC_CNTL);
-+}
-+
-+static void wctdm_disable_interrupts(struct wctdm *wc)
-+{
-+ outb(0x00, wc->ioaddr + WC_MASK0);
-+ outb(0x00, wc->ioaddr + WC_MASK1);
-+}
-+
-+static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-+{
-+ int res;
-+ struct wctdm *wc;
-+ struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data;
-+ int x;
-+ int y;
-+
-+ static int initd_ifaces=0;
-+
-+ if(initd_ifaces){
-+ memset((void *)ifaces,0,(sizeof(struct wctdm *))*WC_MAX_IFACES);
-+ initd_ifaces=1;
-+ }
-+ for (x=0;x<WC_MAX_IFACES;x++)
-+ if (!ifaces[x]) break;
-+ if (x >= WC_MAX_IFACES) {
-+ printk(KERN_NOTICE "Too many interfaces\n");
-+ return -EIO;
-+ }
-+
-+ if (pci_enable_device(pdev)) {
-+ res = -EIO;
-+ } else {
-+ wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL);
-+ if (wc) {
-+ int cardcount = 0;
-+
-+ wc->lastchan = -1; /* first channel offset = -1; */
-+ wc->ledstate = 0;
-+
-+ ifaces[x] = wc;
-+ memset(wc, 0, sizeof(struct wctdm));
-+ for (x=0; x < sizeof(wc->chans)/sizeof(wc->chans[0]); ++x) {
-+ wc->chans[x] = &wc->_chans[x];
-+ }
-+
-+ spin_lock_init(&wc->lock);
-+ wc->curcard = -1;
-+ wc->ioaddr = pci_resource_start(pdev, 0);
-+ wc->mem_region = pci_resource_start(pdev, 1);
-+ wc->mem_len = pci_resource_len(pdev, 1);
-+ wc->mem32 = (unsigned long)ioremap(wc->mem_region, wc->mem_len);
-+ wc->dev = pdev;
-+ wc->pos = x;
-+ wc->variety = d->name;
-+ for (y=0;y<MAX_NUM_CARDS;y++)
-+ wc->flags[y] = d->flags;
-+ /* Keep track of whether we need to free the region */
-+ if (request_region(wc->ioaddr, 0xff, "opvxa1200"))
-+ wc->freeregion = 1;
-+ else
-+ wc->freeregion = 0;
-+
-+ if (request_mem_region(wc->mem_region, wc->mem_len, "opvxa1200"))
-+ wc->freeregion |= 0x02;
-+
-+ /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses
-+ 8 bits. */
-+ wc->writechunk = pci_alloc_consistent(pdev, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, &wc->writedma);
-+ if (!wc->writechunk) {
-+ printk(KERN_NOTICE "opvxa1200: Unable to allocate DMA-able memory\n");
-+ if (wc->freeregion & 0x01)
-+ release_region(wc->ioaddr, 0xff);
-+ if (wc->freeregion & 0x02)
-+ {
-+ release_mem_region(wc->mem_region, wc->mem_len);
-+ iounmap((void *)wc->mem32);
-+ }
-+ return -ENOMEM;
-+ }
-+
-+ wc->readchunk = wc->writechunk + DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2; /* in bytes */
-+ wc->readdma = wc->writedma + DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2; /* in bytes */
-+
-+ if (wctdm_initialize(wc)) {
-+ printk(KERN_NOTICE "opvxa1200: Unable to intialize FXS\n");
-+ /* Set Reset Low */
-+ x=inb(wc->ioaddr + WC_CNTL);
-+ outb((~0x1)&x, wc->ioaddr + WC_CNTL);
-+ /* Free Resources */
-+ free_irq(pdev->irq, wc);
-+ if (wc->freeregion & 0x01)
-+ release_region(wc->ioaddr, 0xff);
-+ if (wc->freeregion & 0x02)
-+ {
-+ release_mem_region(wc->mem_region, wc->mem_len);
-+ iounmap((void *)wc->mem32);
-+ }
-+ }
-+
-+ /* Enable bus mastering */
-+ pci_set_master(pdev);
-+
-+ /* Keep track of which device we are */
-+ pci_set_drvdata(pdev, wc);
-+
-+
-+ if (request_irq(pdev->irq, wctdm_interrupt, DAHDI_IRQ_SHARED, "opvxa1200", wc)) {
-+ printk(KERN_NOTICE "opvxa1200: Unable to request IRQ %d\n", pdev->irq);
-+ if (wc->freeregion & 0x01)
-+ release_region(wc->ioaddr, 0xff);
-+ if (wc->freeregion & 0x02)
-+ {
-+ release_mem_region(wc->mem_region, wc->mem_len);
-+ iounmap((void *)wc->mem32);
-+ }
-+ pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
-+ pci_set_drvdata(pdev, NULL);
-+ kfree(wc);
-+ return -EIO;
-+ }
-+
-+ if (wctdm_hardware_init(wc)) {
-+ unsigned char w;
-+
-+ /* Set Reset Low */
-+ w=inb(wc->ioaddr + WC_CNTL);
-+ outb((~0x1)&w, wc->ioaddr + WC_CNTL);
-+ /* Free Resources */
-+ free_irq(pdev->irq, wc);
-+ if (wc->freeregion & 0x01)
-+ release_region(wc->ioaddr, 0xff);
-+ if (wc->freeregion & 0x02)
-+ {
-+ release_mem_region(wc->mem_region, wc->mem_len);
-+ iounmap((void *)wc->mem32);
-+ }
-+ pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
-+ pci_set_drvdata(pdev, NULL);
-+ dahdi_unregister_device(wc->ddev);
-+ kfree(wc->ddev->location);
-+ dahdi_free_device(wc->ddev);
-+ kfree(wc);
-+ return -EIO;
-+
-+ }
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+ for(x=0; x<MAX_NUM_CARDS+NUM_FLAG; x++)
-+ {
-+ wc->voc_buf[x] = kmalloc(voc_buffer_size, GFP_KERNEL);
-+ wc->voc_ptr[x] = 0;
-+ }
-+#endif
-+
-+ if(cidbeforering)
-+ {
-+ int len = cidbuflen * DAHDI_MAX_CHUNKSIZE;
-+ if(debug)
-+ printk("cidbeforering support enabled, length is %d msec\n", cidbuflen);
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++)
-+ {
-+ wc->cid_history_buf[x] = kmalloc(len, GFP_KERNEL);
-+ wc->cid_history_ptr[x] = 0;
-+ wc->cid_history_clone_cnt[x] = 0;
-+ wc->cid_state[x] = CID_STATE_IDLE;
-+ }
-+ }
-+
-+ wctdm_post_initialize(wc);
-+
-+ /* Enable interrupts */
-+ wctdm_enable_interrupts(wc);
-+ /* Initialize Write/Buffers to all blank data */
-+ memset((void *)wc->writechunk,0, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2);
-+
-+ /* Start DMA */
-+ wctdm_start_dma(wc);
-+
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if (wc->cardflag & (1 << x))
-+ cardcount++;
-+ }
-+
-+ printk(KERN_INFO "Found an OpenVox %s: Version %x.%x (%d modules)\n", wc->card_name, (wc->fwversion&(~FLAG_A800))>>4, wc->fwversion&0x0f, cardcount);
-+ if(debug)
-+ printk(KERN_DEBUG "OpenVox %s debug On\n", wc->card_name);
-+
-+ res = 0;
-+ } else
-+ res = -ENOMEM;
-+ }
-+ return res;
-+}
-+
-+static void wctdm_release(struct wctdm *wc)
-+{
-+#ifdef TEST_LOG_INCOME_VOICE
-+ struct file * f = NULL;
-+ mm_segment_t orig_fs;
-+ int i;
-+ char fname[20];
-+#endif
-+
-+ dahdi_unregister_device(wc->ddev); //Dennis
-+ if (wc->freeregion & 0x01)
-+ release_region(wc->ioaddr, 0xff);
-+
-+ if (wc->freeregion & 0x02)
-+ {
-+ release_mem_region(wc->mem_region, wc->mem_len);
-+ iounmap((void *)wc->mem32);
-+ }
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+ for(i=0; i<MAX_NUM_CARDS + NUM_FLAG; i++)
-+ {
-+ sprintf(fname, "//usr//%d.pcm", i);
-+ f = filp_open(fname, O_RDWR|O_CREAT, 00);
-+
-+ if (!f || !f->f_op || !f->f_op->read)
-+ {
-+ printk("WARNING: File (read) object is a null pointer!!!\n");
-+ continue;
-+ }
-+
-+ f->f_pos = 0;
-+
-+ orig_fs = get_fs();
-+ set_fs(KERNEL_DS);
-+
-+ if(wc->voc_buf[i])
-+ {
-+ f->f_op->write(f, wc->voc_buf[i], voc_buffer_size, &f->f_pos);
-+ kfree(wc->voc_buf[i]);
-+ }
-+
-+ set_fs(orig_fs);
-+ fput(f);
-+ }
-+#endif
-+
-+ if(cidbeforering)
-+ {
-+ int x;
-+ for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++)
-+ kfree(wc->cid_history_buf[x]);
-+ }
-+ kfree(wc->ddev->location); //Dennis
-+ dahdi_free_device(wc->ddev);
-+ kfree(wc);
-+ printk(KERN_INFO "Free an OpenVox A1200 card\n");
-+}
-+
-+static void __devexit wctdm_remove_one(struct pci_dev *pdev)
-+{
-+ struct wctdm *wc = pci_get_drvdata(pdev);
-+ if (wc) {
-+
-+ /* Stop any DMA */
-+ wctdm_stop_dma(wc);
-+ wctdm_reset_tdm(wc);
-+
-+ /* In case hardware is still there */
-+ wctdm_disable_interrupts(wc);
-+
-+ /* Immediately free resources */
-+ pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
-+ free_irq(pdev->irq, wc);
-+
-+ /* Reset PCI chip and registers */
-+ if(wc->fwversion > 0x11)
-+ outb(0x0e, wc->ioaddr + WC_CNTL);
-+ else
-+ {
-+ wc->ledstate = 0;
-+ wctdm_set_led(wc,0,0); // power off all leds.
-+ }
-+
-+ /* Release span, possibly delayed */
-+ if (!wc->usecount)
-+ wctdm_release(wc);
-+ else
-+ wc->dead = 1;
-+ }
-+}
-+
-+static struct pci_device_id wctdm_pci_tbl[] = {
-+ { 0xe159, 0x0001, 0x9100, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x9519, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x95D9, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x9500, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x9532, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x8519, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x9559, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0xe159, 0x0001, 0x9599, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
-+ { 0 }
-+};
-+
-+MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl);
-+
-+static struct pci_driver wctdm_driver = {
-+ .name = "opvxa1200",
-+ .probe = wctdm_init_one,
-+ .remove = __devexit_p(wctdm_remove_one),
-+ .suspend = NULL,
-+ .resume = NULL,
-+ .id_table = wctdm_pci_tbl,
-+};
-+
-+static int __init wctdm_init(void)
-+{
-+ int res;
-+ int x;
-+ for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) {
-+ if (!strcmp(fxo_modes[x].name, opermode))
-+ break;
-+ }
-+ if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) {
-+ _opermode = x;
-+ } else {
-+ printk(KERN_NOTICE "Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode);
-+ for (x=0;x<sizeof(fxo_modes) / sizeof(fxo_modes[0]); x++)
-+ printk(KERN_INFO " %s\n", fxo_modes[x].name);
-+ printk(KERN_INFO "Note this option is CASE SENSITIVE!\n");
-+ return -ENODEV;
-+ }
-+ if (!strcmp(fxo_modes[_opermode].name, "AUSTRALIA")) {
-+ boostringer=1;
-+ fxshonormode=1;
-+}
-+ if (battdebounce == 0) {
-+ battdebounce = fxo_modes[_opermode].battdebounce;
-+ }
-+ if (battalarm == 0) {
-+ battalarm = fxo_modes[_opermode].battalarm;
-+ }
-+ if (battthresh == 0) {
-+ battthresh = fxo_modes[_opermode].battthresh;
-+ }
-+
-+ res = dahdi_pci_module(&wctdm_driver);
-+ if (res)
-+ return -ENODEV;
-+ return 0;
-+}
-+
-+static void __exit wctdm_cleanup(void)
-+{
-+ pci_unregister_driver(&wctdm_driver);
-+}
-+
-+module_param(debug, int, 0600);
-+module_param(loopcurrent, int, 0600);
-+module_param(reversepolarity, int, 0600);
-+module_param(robust, int, 0600);
-+module_param(opermode, charp, 0600);
-+module_param(timingonly, int, 0600);
-+module_param(lowpower, int, 0600);
-+module_param(boostringer, int, 0600);
-+module_param(fastringer, int, 0600);
-+module_param(fxshonormode, int, 0600);
-+module_param(battdebounce, uint, 0600);
-+module_param(battthresh, uint, 0600);
-+module_param(battalarm, uint, 0600);
-+module_param(ringdebounce, int, 0600);
-+module_param(dialdebounce, int, 0600);
-+module_param(fwringdetect, int, 0600);
-+module_param(alawoverride, int, 0600);
-+module_param(fastpickup, int, 0600);
-+module_param(fxotxgain, int, 0600);
-+module_param(fxorxgain, int, 0600);
-+module_param(fxstxgain, int, 0600);
-+module_param(fxsrxgain, int, 0600);
-+module_param(spibyhw, int, 0600);
-+module_param(usememio, int, 0600);
-+module_param(cidbeforering, int, 0600);
-+module_param(cidbuflen, int, 0600);
-+module_param(cidtimeout, int, 0600);
-+module_param(fxofullscale, int, 0600);
-+module_param(fixedtimepolarity, int, 0600);
-+module_param(watchdma, int, 0600);
-+
-+MODULE_DESCRIPTION("OpenVox A1200 Driver");
-+MODULE_AUTHOR("MiaoLin <miaolin@openvox.com.cn>");
-+MODULE_LICENSE("GPL v2");
-+
-+module_init(wctdm_init);
-+module_exit(wctdm_cleanup);
-+
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/Kbuild 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/Kbuild 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,40 @@
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXA24XX) += opvxa24xx.o
-+
-+FIRM_DIR := ../firmware
-+
-+EXTRA_CFLAGS += -I$(src)/.. -I$(src)/../oct612x/ $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef
-+
-+DAHDI_KERNEL_H_NAME:=kernel.h
-+DAHDI_KERNEL_H_PATH:=$(DAHDI_INCLUDE)/dahdi/$(DAHDI_KERNEL_H_NAME)
-+ifneq ($(DAHDI_KERNEL_H_PATH),)
-+ DAHDI_SPAN_MODULE:=$(shell if grep -C 5 "struct dahdi_span {" $(DAHDI_KERNEL_H_PATH) | grep -q "struct module \*owner"; then echo "yes"; else echo "no"; fi)
-+ DAHDI_SPAN_OPS:=$(shell if grep -q "struct dahdi_span_ops {" $(DAHDI_KERNEL_H_PATH); then echo "yes"; else echo "no"; fi)
-+ ifeq ($(DAHDI_SPAN_MODULE),yes)
-+ EXTRA_CFLAGS+=-DDAHDI_SPAN_MODULE
-+ else
-+ ifeq ($(DAHDI_SPAN_OPS),yes)
-+ EXTRA_CFLAGS+=-DDAHDI_SPAN_OPS
-+ endif
-+ endif
-+endif
-+
-+ifeq ($(HOTPLUG_FIRMWARE),yes)
-+ EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
-+endif
-+
-+opvxa24xx-objs := private.o a24xx.o si321x.o si3050.o ec3000.o callerid.o busydetect.o base.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x)
-+
-+ifneq ($(HOTPLUG_FIRMWARE),yes)
-+opvxa24xx-objs += $(FIRM_DIR)/dahdi-fw-oct6114-032.o $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o
-+endif
-+
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-032.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-032.o
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-064.o
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o
-+
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/Makefile 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,8 @@
-+ifdef KBUILD_EXTMOD
-+# We only get here on kernels 2.6.0-2.6.9 .
-+# For newer kernels, Kbuild will be included directly by the kernel
-+# build system.
-+include $(src)/Kbuild
-+
-+else
-+endif
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/a24xx.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/a24xx.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,286 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * $Id: a24xx.c 185 2010-12-14 07:58:51Z yangshugang $
-+
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include <linux/spinlock.h>
-+#include <linux/jiffies.h>
-+
-+#include <dahdi/kernel.h>
-+
-+#include "base.h"
-+#include "proslic.h"
-+
-+#define BIT_EC_PRESENT (1<<0)
-+
-+#define VPM_DEFAULT_DTMFTHRESHOLD 1000
-+
-+/* indirect_resg */
-+static alpha indirect_regs[] =
-+{
-+{0,255,"DTMF_ROW_0_PEAK",0x55C2},
-+{1,255,"DTMF_ROW_1_PEAK",0x51E6},
-+{2,255,"DTMF_ROW2_PEAK",0x4B85},
-+{3,255,"DTMF_ROW3_PEAK",0x4937},
-+{4,255,"DTMF_COL1_PEAK",0x3333},
-+{5,255,"DTMF_FWD_TWIST",0x0202},
-+{6,255,"DTMF_RVS_TWIST",0x0202},
-+{7,255,"DTMF_ROW_RATIO_TRES",0x0198},
-+{8,255,"DTMF_COL_RATIO_TRES",0x0198},
-+{9,255,"DTMF_ROW_2ND_ARM",0x0611},
-+{10,255,"DTMF_COL_2ND_ARM",0x0202},
-+{11,255,"DTMF_PWR_MIN_TRES",0x00E5},
-+{12,255,"DTMF_OT_LIM_TRES",0x0A1C},
-+{13,0,"OSC1_COEF",0x7B30},
-+{14,1,"OSC1X",0x0063},
-+{15,2,"OSC1Y",0x0000},
-+{16,3,"OSC2_COEF",0x7870},
-+{17,4,"OSC2X",0x007D},
-+{18,5,"OSC2Y",0x0000},
-+{19,6,"RING_V_OFF",0x0000},
-+{20,7,"RING_OSC",0x7EF0},
-+{21,8,"RING_X",0x0160},
-+{22,9,"RING_Y",0x0000},
-+{23,255,"PULSE_ENVEL",0x2000},
-+{24,255,"PULSE_X",0x2000},
-+{25,255,"PULSE_Y",0x0000},
-+//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower
-+{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower
-+{27,14,"XMIT_DIGITAL_GAIN",0x4000},
-+//{27,14,"XMIT_DIGITAL_GAIN",0x2000},
-+{28,15,"LOOP_CLOSE_TRES",0x1000},
-+{29,16,"RING_TRIP_TRES",0x3600},
-+{30,17,"COMMON_MIN_TRES",0x1000},
-+{31,18,"COMMON_MAX_TRES",0x0200},
-+{32,19,"PWR_ALARM_Q1Q2",0x0ff4},
-+{33,20,"PWR_ALARM_Q3Q4",0x6e7e},
-+{34,21,"PWR_ALARM_Q5Q6",0x0ff4},
-+{35,22,"LOOP_CLOSURE_FILTER",0x8000},
-+{36,23,"RING_TRIP_FILTER",0x0320},
-+{37,24,"TERM_LP_POLE_Q1Q2",0x0012},
-+{38,25,"TERM_LP_POLE_Q3Q4",0x0012},
-+{39,26,"TERM_LP_POLE_Q5Q6",0x0012},
-+{40,27,"CM_BIAS_RINGING",0x0C00},
-+{41,64,"DCDC_MIN_V",0x0C00},
-+{42,255,"DCDC_XTRA",0x1000},
-+{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
-+};
-+
-+void __a24xx_wait_just_a_bit(int foo)
-+{
-+ long newjiffies;
-+ newjiffies = jiffies + foo;
-+ while(jiffies < newjiffies);
-+}
-+
-+void __a24xx_setcard(void *wc_dev, int card)
-+{
-+ struct a24xx_dev *dev = (struct a24xx_dev *)(wc_dev);
-+ if (dev->curcard != card) {
-+ __opvx_a24xx_setcard(dev->mem32, card);
-+ dev->curcard = card;
-+ }
-+}
-+
-+inline void __a24xx_spi_setreg(struct a24xx_dev *wc_dev, int card, unsigned char reg, unsigned char value)
-+{
-+ __opvx_a24xx_spi_setreg((void *)wc_dev, wc_dev->mem32, card, wc_dev->modtype[card], reg, value, __a24xx_setcard);
-+}
-+
-+inline unsigned char __a24xx_spi_getreg(struct a24xx_dev *wc_dev, int card, unsigned char reg)
-+{
-+ return __opvx_a24xx_spi_getreg((void *)wc_dev, wc_dev->mem32, card, wc_dev->modtype[card], reg, __a24xx_setcard);
-+}
-+
-+int __a24xx_malloc_chunk(struct a24xx_dev *wc_dev,unsigned int frq)
-+{
-+ __opvx_a24xx_set_chunk(&(wc_dev->readchunk), &(wc_dev->writechunk),frq);
-+ wc_dev->readdma = wc_dev->writedma + frq * DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS) * 2;
-+
-+ return 0;
-+}
-+
-+static unsigned char __translate_3215(unsigned char address)
-+{
-+ int x;
-+ for (x=0;x<sizeof(indirect_regs)/sizeof(indirect_regs[0]);x++) {
-+ if (indirect_regs[x].address == address) {
-+ address = indirect_regs[x].altaddr;
-+ break;
-+ }
-+ }
-+ return address;
-+}
-+
-+int __a24xx_wait_access(struct a24xx_dev *wc_dev, int card)
-+{
-+ unsigned char data = 0;
-+ long origjiffies;
-+ int count = 0;
-+
-+ #define MAX 6000 /* attempts */
-+
-+ origjiffies = jiffies;
-+ /* Wait for indirect access */
-+ while (count++ < MAX) {
-+ data = __a24xx_spi_getreg(wc_dev, card, I_STATUS);
-+ if (!data) {
-+ return 0;
-+ }
-+ }
-+
-+ if(count > (MAX-1)) {
-+ printk(" ##### Loop error (%02x) #####\n", data);
-+ }
-+
-+ return 0;
-+}
-+
-+int __a24xx_proslic_setreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address, unsigned short data)
-+{
-+ int res = -1;
-+ /* Translate 3215 addresses */
-+ if (wc_dev->flags[card] & FLAG_3215) {
-+ address = __translate_3215(address);
-+ if (address == 255) {
-+ return 0;
-+ }
-+ }
-+ if(!__a24xx_wait_access(wc_dev, card)) {
-+ __a24xx_spi_setreg(wc_dev, card, IDA_LO,(unsigned char)(data & 0xFF));
-+ __a24xx_spi_setreg(wc_dev, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8));
-+ __a24xx_spi_setreg(wc_dev, card, IAA,address);
-+ res = 0;
-+ }
-+
-+ return res;
-+}
-+
-+int __a24xx_proslic_getreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address)
-+{
-+ int res = -1;
-+ char *p=NULL;
-+ /* Translate 3215 addresses */
-+ if (wc_dev->flags[card] & FLAG_3215) {
-+ address = __translate_3215(address);
-+ if (address == 255) {
-+ return 0;
-+ }
-+ }
-+ if (!__a24xx_wait_access(wc_dev, card)) {
-+ __a24xx_spi_setreg(wc_dev, card, IAA, address);
-+ if (!__a24xx_wait_access(wc_dev, card)) {
-+ unsigned char data1, data2;
-+ data1 = __a24xx_spi_getreg(wc_dev, card, IDA_LO);
-+ data2 = __a24xx_spi_getreg(wc_dev, card, IDA_HI);
-+ res = data1 | (data2 << 8);
-+ } else {
-+ p = "Failed to wait inside\n";
-+ }
-+ } else {
-+ p = "failed to wait\n";
-+ }
-+ if (p) {
-+ printk("%s\n", p);
-+ }
-+ return res;
-+}
-+
-+void __a24xx_vpm_setpresent(struct a24xx_dev *wc_dev)
-+{
-+ wc_dev->vpm = BIT_EC_PRESENT;
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ __opvx_a24xx_vpm_setpresent_v2(wc_dev->mem32);
-+ else
-+ __opvx_a24xx_vpm_setpresent(wc_dev->mem32);
-+ printk("OpenVox VPM: Present and operational servicing %d span(s)\n", 1/*wc_dev->numspans*/);
-+}
-+
-+void a24xx_spi_setreg(struct a24xx_dev *wc_dev, int card, unsigned char reg, unsigned char value)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ __a24xx_spi_setreg(wc_dev, card, reg, value);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+}
-+
-+unsigned char a24xx_spi_getreg(struct a24xx_dev *wc_dev, int card, unsigned char reg)
-+{
-+ unsigned long flags;
-+ unsigned char ret;
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ ret = __a24xx_spi_getreg(wc_dev, card, reg);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+ return ret;
-+}
-+
-+static inline unsigned int a24xx_oct_in(struct a24xx_dev *wc_dev, const unsigned int addr)
-+{
-+ unsigned long flags;
-+ unsigned int ret;
-+
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ ret = __opvx_a24xx_oct_in_v2(wc_dev->mem32, addr);
-+ else
-+ ret = __opvx_a24xx_oct_in(wc_dev->mem32, addr);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+
-+ return ret;
-+}
-+
-+static inline void a24xx_oct_out(struct a24xx_dev *wc_dev, const unsigned int addr, const unsigned int value)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ __opvx_a24xx_oct_out_v2(wc_dev->mem32, addr, value);
-+ else
-+ __opvx_a24xx_oct_out(wc_dev->mem32, addr, value);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+}
-+
-+void oct_set_reg(void *data, unsigned int reg, unsigned int val)
-+{
-+ struct a24xx_dev *wc_dev = data;
-+ a24xx_oct_out(wc_dev, reg, val);
-+}
-+
-+unsigned int oct_get_reg(void *data, unsigned int reg)
-+{
-+ struct a24xx_dev *wc_dev = data;
-+ unsigned int ret;
-+ ret = a24xx_oct_in(wc_dev, reg);
-+ return ret;
-+}
-+
-+void a24xx_reset_spi(struct a24xx_dev *wc_dev, int card)
-+{
-+ unsigned long flags;
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ __opvx_a24xx_reset_spi(wc_dev, card, __a24xx_setcard);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+}
-+
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/base.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/base.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,2679 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * $Id: base.c 359 2011-04-06 06:11:39Z yangshugang $
-+
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+/* Rev histroy
-+ *
-+ * Rev 0.10 initial version, modified from opvxa1200.c
-+ * Rev 0.20 add octasic echo canceller support.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/pci.h>
-+#include <linux/interrupt.h>
-+#include <asm/io.h>
-+#include <linux/delay.h>
-+#include <linux/moduleparam.h>
-+#include <linux/sched.h>
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+#include <linux/string.h>
-+#include <asm/uaccess.h> /* get_fs(), set_fs(), KERNEL_DS */
-+#include <linux/file.h> /* fput() */
-+#endif
-+
-+#include <dahdi/kernel.h>
-+#include <dahdi/wctdm_user.h>
-+#include "fxo_modes.h"
-+
-+#include "proslic.h"
-+#include "base.h"
-+#include "ec3000.h"
-+#include "busydetect.h"
-+
-+/* module parameters */
-+int debug;
-+int spi_cmd=0x223;
-+
-+int reversepolarity = 0;
-+int alawoverride = 0;
-+int fxotxgain = 0;
-+int fxorxgain = 0;
-+int fastpickup = 0;
-+int fxofullscale = 0; /* fxo full scale tx/rx, register 30, acim */
-+int fwringdetect = 0;
-+int _opermode = 0;
-+int cidsupport = 1; /* default support caller id analysis */
-+int cidbuflen = 3000; /* in msec, default 3000 */
-+int cidtimeout = 6*1000; /* in msec, default 6000 */
-+int fxstxgain = 0;
-+int fxsrxgain = 0;
-+int fxshonormode = 0;
-+int boostringer = 0;
-+int fastringer = 0;
-+int lowpower = 0;
-+int loopcurrent = 20;
-+int timingonly = 0;
-+int fixedtimepolarity=0; /* time delay in ms when send polarity after rise edge of 1st ring.*/
-+int ringdebounce = DEFAULT_RING_DEBOUNCE;
-+unsigned int battdebounce;
-+unsigned int battalarm;
-+unsigned int battthresh;
-+int robust = 0;
-+#ifdef VPM_SUPPORT
-+/* ec debug */
-+int ec_debug = 0;
-+int vpmsupport = 1;
-+#endif
-+
-+#define MS_PER_HOOKCHECK (1)
-+
-+int ec_spans = 4;
-+
-+static char* A2410P_Name = "A2410P";
-+static struct a24xx_desc a2410a = { "OpenVox A2410", 0 };
-+static char* A1610P_Name = "A1610P";
-+static struct a24xx_desc a1610a = { "OpenVox A1610", 0 };
-+static char* A810P_Name = "A810P";
-+static struct a24xx_desc a810a = { "OpenVox A810", 0 };
-+static struct a24xx *ifaces[WC_MAX_IFACES];
-+static char *opermode = "FCC";
-+
-+/* If set to auto, vpmdtmfsupport is enabled for VPM400M and disabled for VPM450M */
-+static int vpmdtmfsupport = -1; /* -1=auto, 0=disabled, 1=enabled*/
-+static unsigned int ms_per_irq = 1; // 1/2/4/8/16 allowed
-+static unsigned int max_iface_index = 0;
-+static unsigned int irq_stub = 0;
-+
-+#define POLARITY_XOR(card) ( \
-+ (reversepolarity != 0) ^ (wc_dev->mod[(card)].fxs.reversepolarity != 0) ^ \
-+ (wc_dev->mod[(card)].fxs.vmwi_lrev != 0) ^\
-+ ((wc_dev->mod[(card)].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVAC) != 0)\
-+ )
-+
-+static const struct dahdi_echocan_features vpm_ec_features = {
-+ .NLP_automatic = 1,
-+ .CED_tx_detect = 1,
-+ .CED_rx_detect = 1,
-+};
-+
-+static void a24xx_release(struct a24xx *wc);
-+static void a24xx_echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
-+
-+static const struct dahdi_echocan_ops vpm_ec_ops = {
-+// .name = "OPENVOX VPM",
-+ .echocan_free = a24xx_echocan_free,
-+};
-+
-+static int a24xx_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
-+ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec)
-+{
-+ struct a24xx *wc = chan->pvt;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ int channel;
-+ const struct dahdi_echocan_ops *ops;
-+ const struct dahdi_echocan_features *features;
-+
-+
-+ if (!wc_dev->vpm) {
-+ return -ENODEV;
-+ }
-+
-+ if (chan->span->offset >= ec_spans) {
-+ return -ENODEV;
-+ }
-+
-+ if (wc_dev->vpm_ec) {
-+ ops = &vpm_ec_ops;
-+ features = &vpm_ec_features;
-+ }
-+
-+ if (ecp->param_count > 0) {
-+ printk(KERN_WARNING "OpenVox VPM echo canceller does not support parameters; failing request\n");
-+ return -EINVAL;
-+ }
-+
-+ *ec = wc->ec[chan->chanpos - 1];
-+ (*ec)->ops = ops;
-+ (*ec)->features = *features;
-+
-+ channel = chan->chanpos;
-+
-+ if (wc_dev->vpm_ec) {
-+ channel -= 1;
-+ if(ec_debug) {
-+ printk(KERN_DEBUG "echocan: Card is %d, Channel is %d, offset is %d, length %d\n",
-+ wc_dev->pos, chan->chanpos, channel, ecp->tap_length);
-+ }
-+ opvx_vpm_setec(wc_dev->vpm_ec, channel, ecp->tap_length);
-+ msleep(10);
-+ }
-+
-+ return 0;
-+}
-+
-+static void a24xx_echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec)
-+{
-+ struct a24xx *wc = chan->pvt;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ int channel;
-+
-+ memset(ec, 0, sizeof(*ec));
-+
-+ channel = chan->chanpos;
-+
-+ if (wc_dev->vpm_ec) {
-+ channel -= 1;
-+ if (ec_debug)
-+ printk(KERN_DEBUG "echocan: Card is %d, Channel is %d, Span is %d, offset is %d length 0\n",
-+ wc_dev->pos, chan->chanpos, chan->span->offset, channel);
-+ opvx_vpm_setec(wc_dev->vpm_ec, channel, 0);
-+ }
-+}
-+
-+static void free_wc(struct a24xx *wc)
-+{
-+ int i;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ if (wc->ec[i]) {
-+ kfree(wc->ec[i]);
-+ wc->ec[i] = NULL;
-+ }
-+ }
-+ kfree(wc);
-+ wc = NULL;
-+}
-+
-+static void a24xx_vpm_init(struct a24xx *wc)
-+{
-+ int x;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ int laws[4] = { 0, };
-+ int res;
-+
-+ unsigned int vpm_capacity;
-+ struct firmware embedded_firmware;
-+ const struct firmware *firmware = &embedded_firmware;
-+
-+#if !defined(HOTPLUG_FIRMWARE)
-+ extern void _binary_dahdi_fw_oct6114_032_bin_size;
-+ extern void _binary_dahdi_fw_oct6114_064_bin_size;
-+ extern void _binary_dahdi_fw_oct6114_128_bin_size;
-+ extern u8 _binary_dahdi_fw_oct6114_032_bin_start[];
-+ extern u8 _binary_dahdi_fw_oct6114_064_bin_start[];
-+ extern u8 _binary_dahdi_fw_oct6114_128_bin_start[];
-+#else
-+ static const char oct032_firmware[] = "dahdi-fw-oct6114-032.bin";
-+ static const char oct064_firmware[] = "dahdi-fw-oct6114-064.bin";
-+ static const char oct128_firmware[] = "dahdi-fw-oct6114-128.bin";
-+#endif
-+
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ res = __opvx_a24xx_check_vpm_v2(wc_dev->mem32);
-+ else
-+ res = __opvx_a24xx_check_vpm(wc_dev->mem32);
-+
-+ if (res < 0) {
-+ if (-1 == res) {
-+ printk("OpenVox VPM: Support Disabled\n");
-+ } else if (-2 == res) {
-+ printk("OpenVox VPM: Not Present\n");
-+ }
-+ return;
-+ }
-+
-+ /* Setup alaw vs ulaw rules */
-+ for (x = 0;x < 1; x++) {
-+ if(wc->span.deflaw == DAHDI_LAW_ALAW) {
-+ laws[x] = 1;
-+ }
-+ else {
-+ laws[x] = 0;
-+ }
-+ }
-+
-+ vpm_capacity = opvx_vpm_getcapacity(wc_dev);
-+ printk("OpenVox VPM: echo cancellation supports %d channels\n", vpm_capacity);
-+
-+ switch (vpm_capacity) {
-+ case 32:
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct032_firmware, &wc_dev->dev->dev) != 0) ||
-+ !firmware) {
-+ printk("OpenVox VPM: firmware %s not available from userspace\n", oct032_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_032_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_zaptel_fw_oct6114_032_bin_size;
-+#endif
-+ break;
-+ case 64:
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct064_firmware, &wc_dev->dev->dev) != 0) ||
-+ !firmware) {
-+ printk("OpenVox VPM: firmware %s not available from userspace\n", oct064_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_064_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_064_bin_size;
-+#endif
-+ break;
-+ case 128:
-+#if defined(HOTPLUG_FIRMWARE)
-+ if ((request_firmware(&firmware, oct128_firmware, &wc_dev->dev->dev) != 0) ||
-+ !firmware) {
-+ printk("OpenVox VPM: firmware %s not available from userspace\n", oct128_firmware);
-+ return;
-+ }
-+#else
-+ embedded_firmware.data = _binary_dahdi_fw_oct6114_128_bin_start;
-+ /* Yes... this is weird. objcopy gives us a symbol containing
-+ the size of the firmware, not a pointer a variable containing
-+ the size. The only way we can get the value of the symbol
-+ is to take its address, so we define it as a pointer and
-+ then cast that value to the proper type.
-+ */
-+ embedded_firmware.size = (size_t) &_binary_dahdi_fw_oct6114_128_bin_size;
-+#endif
-+ break;
-+ default:
-+ printk("Unsupported channel capacity found on VPM module (%d).\n", vpm_capacity);
-+ return;
-+ }
-+
-+ if (!(wc_dev->vpm_ec = opvx_vpm_init(wc_dev, laws, /*wc_dev->numspans*/1, firmware))) {
-+ printk("OpenVox VPM: Failed to initialize\n");
-+ if (firmware != &embedded_firmware) {
-+ release_firmware(firmware);
-+ }
-+ return;
-+ }
-+
-+ if (firmware != &embedded_firmware) {
-+ release_firmware(firmware);
-+ }
-+
-+ if (vpmdtmfsupport == -1) {
-+ printk("OpenVox VPM: hardware DTMF disabled.\n");
-+ vpmdtmfsupport = 0;
-+ }
-+
-+ __a24xx_vpm_setpresent(wc_dev);
-+
-+}
-+
-+#ifdef AUDIO_RINGCHECK
-+static inline void ring_check(struct a24xx *wc, int card)
-+{
-+ int x;
-+ short sample;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ if (wc_dev->modtype[card] != MOD_TYPE_FXO) {
-+ return;
-+ }
-+ wc_dev->mod[card].fxo.pegtimer += DAHDI_CHUNKSIZE;
-+ for (x=0;x<DAHDI_CHUNKSIZE;x++) {
-+ /* Look for pegging to indicate ringing */
-+ sample = DAHDI_XLAW(wc->chans[card].readchunk[x], (&(wc->chans[card])));
-+ if ((sample > 10000) && (wc_dev->mod[card].fxo.peg != 1)) {
-+ if (debug > 1) {
-+ printk(KERN_DEBUG "High peg!\n");
-+ }
-+ if ((wc_dev->mod[card].fxo.pegtimer < PEGTIME) && (wc_dev->mod[card].fxo.pegtimer > MINPEGTIME)) {
-+ wc_dev->mod[card].fxo.pegcount++;
-+ }
-+ wc_dev->mod[card].fxo.pegtimer = 0;
-+ wc_dev->mod[card].fxo.peg = 1;
-+ } else if ((sample < -10000) && (wc_dev->mod[card].fxo.peg != -1)) {
-+ if (debug > 1) {
-+ printk(KERN_DEBUG "Low peg!\n");
-+ }
-+ if ((wc_dev->mod[card].fxo.pegtimer < (PEGTIME >> 2)) && (wc_dev->mod[card].fxo.pegtimer > (MINPEGTIME >> 2))) {
-+ wc_dev->mod[card].fxo.pegcount++;
-+ }
-+ wc_dev->mod[card].fxo.pegtimer = 0;
-+ wc_dev->mod[card].fxo.peg = -1;
-+ }
-+ }
-+ if (wc_dev->mod[card].fxo.pegtimer > PEGTIME) {
-+ /* Reset pegcount if our timer expires */
-+ wc_dev->mod[card].fxo.pegcount = 0;
-+ }
-+ /* Decrement debouncer if appropriate */
-+ if (wc_dev->mod[card].fxo.ringdebounce) {
-+ wc_dev->mod[card].fxo.ringdebounce--;
-+ }
-+ if (!wc_dev->mod[card].fxo.offhook && !wc_dev->mod[card].fxo.ringdebounce) {
-+ if (!wc_dev->mod[card].fxo.ring && (wc_dev->mod[card].fxo.pegcount > PEGCOUNT)) {
-+ /* It's ringing */
-+ if (debug) {
-+ printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ if (!wc_dev->mod[card].fxo.offhook) {
-+ dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ wc_dev->mod[card].fxo.ring = 1;
-+ }
-+ if (wc_dev->mod[card].fxo.ring && !wc_dev->mod[card].fxo.pegcount) {
-+ /* No more ring */
-+ if (debug) {
-+ printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ wc_dev->mod[card].fxo.ring = 0;
-+ }
-+ }
-+}
-+#endif
-+
-+#if 0
-+static int a24xx_hardware_init(struct a24xx_dev *wc_dev, char *sigcap)
-+{
-+ unsigned int x;
-+ unsigned char ch;
-+
-+ /* Signal Reset */
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ __opvx_a24xx_reset_modules_v2(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+ else
-+ __opvx_a24xx_reset_modules(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+
-+ /* Check OpenVox version */
-+ printk("OpenVox %s version: %01x.%01x\n", wc_dev->card_name, wc_dev->fwversion>>16, wc_dev->fwversion&0xffff);
-+
-+ /* Clear interrupts */
-+ __opvx_a24xx_clear_irqs(wc_dev->mem32);
-+
-+ /* Wait 1/4 of a second more */
-+ //opvx_wait_just_a_bit(HZ/4);
-+
-+ /* test cards exist and type at first */
-+ for(x=0; x<wc_dev->max_cards; x+=CARDS_PER_MODULE) {
-+ __a24xx_setcard(wc_dev, x);
-+ wc_dev->modtype[x] = MOD_TYPE_FXO;
-+ ch = __a24xx_spi_getreg(wc_dev, x, 2); /* read register 2, 3050 return 0x3, 3210 return 0x0 */
-+ if(0x03 == ch) {
-+ wc_dev->modtype[x+1] = MOD_TYPE_FXO;
-+ wc_dev->modtype[x+2] = MOD_TYPE_FXO;
-+ wc_dev->modtype[x+3] = MOD_TYPE_FXO;
-+ if(debug) {
-+ printk("module %d is a FXO\n", x);
-+ }
-+ } else {
-+ wc_dev->modtype[x] = MOD_TYPE_FXS;
-+ wc_dev->modtype[x+1] = MOD_TYPE_FXS;
-+ wc_dev->modtype[x+2] = MOD_TYPE_FXS;
-+ wc_dev->modtype[x+3] = MOD_TYPE_FXS;
-+ if(debug) {
-+ printk("module %d is a FXS or Not Installed\n", x);
-+ }
-+ }
-+ }
-+
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ __opvx_a24xx_reset_modules_v2(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+ else
-+ __opvx_a24xx_reset_modules(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ int sane=0,ret=0,readi=0;
-+
-+ if( (x%4) == 0 && wc_dev->modtype[x]==MOD_TYPE_FXS) { /* set 3215 to daisy chain mode */
-+ __a24xx_setcard(wc_dev, x);
-+ __opvx_a24xx_write_8bits(wc_dev->mem32, 0x00);
-+ __opvx_a24xx_write_8bits(wc_dev->mem32, 0x80);
-+ }
-+
-+#if 1
-+ touch_softlockup_watchdog(); // avoid showing CPU softlock message
-+
-+ /* Init with Auto Calibration */
-+ if (!(ret=si321x_init_proslic(wc_dev, x, 0, 0, sane))) {
-+ wc_dev->cardflag |= (1 << x);
-+ if (debug) {
-+ readi = a24xx_spi_getreg(wc_dev,x,LOOP_I_LIMIT);
-+ printk("Proslic module %d loop current is %dmA\n",x,
-+ ((readi*3)+20));
-+ }
-+ printk("Module %d: Installed -- AUTO FXS/DPO\n",x);
-+ } else {
-+ if(ret!=-2) {
-+ sane=1;
-+
-+ printk("Init ProSlic with Manual Calibration \n");
-+ /* Init with Manual Calibration */
-+ if (!si321x_init_proslic(wc_dev, x, 0, 1, sane)) {
-+ wc_dev->cardflag |= (1 << x);
-+ if (debug) {
-+ readi = a24xx_spi_getreg(wc_dev,x,LOOP_I_LIMIT);
-+ printk("Proslic module %d loop current is %dmA\n",x,
-+ ((readi*3)+20));
-+ }
-+ printk("Module %d: Installed -- MANUAL FXS\n",x);
-+ } else {
-+ printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC");
-+ sigcap[x] = 1;
-+ }
-+ } else if (!(ret = si3050_init_voicedaa(wc_dev, x, 0, 0, sane))) {
-+ wc_dev->cardflag |= (1 << x);
-+ printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name);
-+ } else
-+ printk("Module %d: Not installed\n", x);
-+ }
-+#endif
-+ }
-+
-+ /* Return error if nothing initialized okay. */
-+ if (!wc_dev->cardflag && !timingonly) {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+static int a24xx_hardware_init_all(struct a24xx_dev *wc_dev, char *sigcap)
-+{
-+ unsigned int x;
-+ unsigned char ch;
-+ int sane=0,ret=0;
-+ int flag=0,tmp_flag=0,blank_flag=0;
-+
-+ /* Signal Reset */
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ __opvx_a24xx_reset_modules_v2(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+ else
-+ __opvx_a24xx_reset_modules(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+
-+ /* Check OpenVox version */
-+ printk("OpenVox %s version: %01x.%01x\n", wc_dev->card_name, wc_dev->fwversion>>16, wc_dev->fwversion&0xffff);
-+
-+ /* Clear interrupts */
-+ __opvx_a24xx_clear_irqs(wc_dev->mem32);
-+
-+ /* Wait 1/4 of a second more */
-+ //opvx_wait_just_a_bit(HZ/4);
-+
-+ /* test cards exist and type at first */
-+ for(x=0; x<wc_dev->max_cards; x+=CARDS_PER_MODULE) {
-+ __a24xx_setcard(wc_dev, x);
-+ wc_dev->modtype[x] = MOD_TYPE_FXO;
-+ ch = __a24xx_spi_getreg(wc_dev, x, 2); /* read register 2, 3050 return 0x3, 3210 return 0x0 */
-+ if(0x03 == ch) {
-+ wc_dev->modtype[x+1] = MOD_TYPE_FXO;
-+ wc_dev->modtype[x+2] = MOD_TYPE_FXO;
-+ wc_dev->modtype[x+3] = MOD_TYPE_FXO;
-+ if(debug) {
-+ printk("module %d is a FXO\n", x);
-+ }
-+ } else {
-+ wc_dev->modtype[x] = MOD_TYPE_FXS;
-+ wc_dev->modtype[x+1] = MOD_TYPE_FXS;
-+ wc_dev->modtype[x+2] = MOD_TYPE_FXS;
-+ wc_dev->modtype[x+3] = MOD_TYPE_FXS;
-+ if(debug) {
-+ printk("module %d is a FXS or Not Installed\n", x);
-+ }
-+ }
-+ }
-+
-+ if ( (wc_dev->fwversion&0xffff) > 0x3)
-+ __opvx_a24xx_reset_modules_v2(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+ else
-+ __opvx_a24xx_reset_modules(wc_dev->mem32, __a24xx_wait_just_a_bit, HZ); // reset again;
-+
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ sane=1,ret=0;
-+ touch_softlockup_watchdog(); // avoid showing CPU softlock message
-+
-+ /* Init with Auto Calibration */
-+ if(wc_dev->modtype[x] == MOD_TYPE_FXO){
-+ if (!(ret = si3050_init_voicedaa(wc_dev, x, 0, 0, sane))) {
-+ wc_dev->cardflag |= (1 << x);
-+ }
-+ }
-+ }
-+
-+ /*initial FXS modules*/
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if(wc_dev->modtype[x] == MOD_TYPE_FXS){
-+ flag |=(1 << x);
-+ }
-+ }
-+
-+ touch_softlockup_watchdog();
-+ if((tmp_flag=si321x_init_proslic_all(wc_dev,flag,0,0,0,&blank_flag))>0)
-+ {
-+ tmp_flag=si321x_init_proslic_all(wc_dev,tmp_flag,0,1,1,NULL);
-+ }
-+ flag &=~blank_flag;
-+ flag &=~tmp_flag;
-+ wc_dev->cardflag |=flag;
-+
-+ for (x = 0; x < wc_dev->max_cards; x++){
-+ if(wc_dev->cardflag & (1<<x)){
-+ spin_lock_init(&wc_dev->mod[x].fxs.lasttxhooklock);
-+ if(wc_dev->modtype[x] == MOD_TYPE_FXS){
-+ printk("Module %d: Installed -- AUTO FXS/DPO\n",x);
-+ }else
-+ printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name);
-+ }else{
-+ if(tmp_flag & (1 << x)){
-+ printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC");
-+ sigcap[x] = 1; //************
-+ }
-+ else
-+ printk("Module %d: Not installed\n", x);
-+ }
-+ }
-+
-+ /* Return error if nothing initialized okay. */
-+ if (!wc_dev->cardflag && !timingonly) {
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static void callerid_ring_on_deal(struct a24xx *wc, int card)
-+{
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ if(wc_dev->cid_state[card] == CID_STATE_IDLE) {
-+ reset_parser_variable_from_chan_num(wc->span.spanno, wc->chans[card]->channo);
-+ if (is_ring_delay_operation(wc->span.spanno, wc->chans[card]->channo)) {
-+ wc_dev->cid_state[card] = CID_STATE_RING_DELAY;
-+ } else {
-+ wc_dev->cid_state[card] = CID_STATE_RING_ON;
-+ wc_dev->cid_history_clone_cnt[card] = cidbuflen;
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ } else if(wc_dev->cid_state[card] == CID_STATE_RING_DELAY) {
-+ wc_dev->cid_state[card] = CID_STATE_RING_ON;
-+ wc_dev->cid_history_clone_cnt[card] = cidbuflen;
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ } else {
-+ if (wc_dev->cid_state[card] != CID_STATE_WAIT_RING_FINISH) {
-+ set_signal_unknown_from_chan_num(wc->span.spanno, wc->chans[card]->channo);
-+ wc_dev->cid_state[card] = CID_STATE_WAIT_RING_FINISH;
-+ }
-+ wc_dev->cid_history_clone_cnt[card] = cidtimeout;
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+}
-+
-+static void callerid_ring_off_deal(struct a24xx *wc, int card)
-+{
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ if(wc_dev->cid_state[card] == CID_STATE_RING_ON) {
-+ wc_dev->cid_state[card] = CID_STATE_RING_OFF;
-+ }
-+
-+ if(wc_dev->cid_state[card] != CID_STATE_RING_DELAY) {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+}
-+
-+static void a24xx_voicedaa_check_hook(struct a24xx *wc, int card)
-+{
-+#define MS_PER_CHECK_HOOK 16
-+#ifndef AUDIO_RINGCHECK
-+ unsigned char res;
-+#endif
-+ signed char b;
-+ int errors = 0;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ struct fxo *fxo = &wc_dev->mod[card].fxo;
-+
-+ /* Try to track issues that plague slot one FXO's */
-+ b = wc_dev->reg0shadow[card];
-+ if ((b & 0x2) || !(b & 0x8)) {
-+ /* Not good -- don't look at anything else */
-+ if (debug) {
-+ printk(KERN_DEBUG "Errors (%02x) on card %d!\n", b, card + 1);
-+ }
-+ errors++;
-+ }
-+ b &= 0x9b;
-+ if (fxo->offhook) {
-+ if (b != 0x9) {
-+ a24xx_spi_setreg(wc_dev, card, 5, 0x9);
-+ }
-+ } else {
-+ if (b != 0x8) {
-+ a24xx_spi_setreg(wc_dev, card, 5, 0x8);
-+ }
-+ }
-+ if (errors) {
-+ return;
-+ }
-+
-+ if (!fxo->offhook) {
-+ if (fwringdetect) {
-+ res = wc_dev->reg0shadow[card] & 0x60;
-+ if (fxo->ringdebounce--) {
-+ if (res && (res != fxo->lastrdtx)
-+ && (fxo->battery == BATTERY_PRESENT)) {
-+ if (!fxo->wasringing) {
-+ fxo->wasringing = 1;
-+ if (debug) {
-+ printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ if(cidsupport) {
-+ callerid_ring_on_deal(wc, card);
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ }
-+ fxo->lastrdtx = res;
-+ fxo->ringdebounce = 10;
-+ } else if (!res) {
-+ if ((fxo->ringdebounce == 0)
-+ && fxo->wasringing) {
-+ fxo->wasringing = 0;
-+ if (debug) {
-+ printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ if(cidsupport) {
-+ callerid_ring_off_deal(wc, card);
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+ }
-+ }
-+ } else if (res && (fxo->battery == BATTERY_PRESENT)) {
-+ fxo->lastrdtx = res;
-+ fxo->ringdebounce = 10;
-+ }
-+ } else {
-+ res = wc_dev->reg0shadow[card];
-+ if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) {
-+ fxo->ringdebounce += (DAHDI_CHUNKSIZE * 16);
-+ if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) {
-+ if (!fxo->wasringing) {
-+ fxo->wasringing = 1;
-+ if(cidsupport) {
-+ callerid_ring_on_deal(wc, card);
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
-+ }
-+ if (debug) {
-+ printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ }
-+ fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce;
-+ }
-+ } else {
-+ fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4;
-+ if (fxo->ringdebounce <= 0) {
-+ if (fxo->wasringing) {
-+ fxo->wasringing = 0;
-+ if(cidsupport) {
-+ callerid_ring_off_deal(wc, card);
-+ } else {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ }
-+ if (debug) {
-+ printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+ }
-+ fxo->ringdebounce = 0;
-+ }
-+ }
-+ }
-+ }
-+
-+ b = wc_dev->reg1shadow[card];
-+ if (abs(b) < battthresh) {
-+ /* possible existing states:
-+ battery lost, no debounce timer
-+ battery lost, debounce timer (going to battery present)
-+ battery present or unknown, no debounce timer
-+ battery present or unknown, debounce timer (going to battery lost)
-+ */
-+
-+ if (fxo->battery == BATTERY_LOST) {
-+ if (fxo->battdebounce) {
-+ /* we were going to BATTERY_PRESENT, but battery was lost again,
-+ so clear the debounce timer */
-+ fxo->battdebounce = 0;
-+ }
-+ } else {
-+ if (fxo->battdebounce) {
-+ /* going to BATTERY_LOST, see if we are there yet */
-+ if (--fxo->battdebounce == 0) {
-+ fxo->battery = BATTERY_LOST;
-+ if (debug) {
-+ printk(KERN_DEBUG "NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1);
-+ }
-+#ifdef JAPAN
-+ if (!wc_dev->ohdebounce && wc_dev->offhook) {
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
-+ if (debug) {
-+ printk(KERN_DEBUG "Signalled On Hook\n");
-+ }
-+#ifdef ZERO_BATT_RING
-+ wc_dev->onhook++;
-+#endif
-+ }
-+#else
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
-+ /* set the alarm timer, taking into account that part of its time
-+ period has already passed while debouncing occurred */
-+ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
-+#endif
-+ }
-+ } else {
-+ /* start the debounce timer to verify that battery has been lost */
-+ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ } else {
-+ /* possible existing states:
-+ battery lost or unknown, no debounce timer
-+ battery lost or unknown, debounce timer (going to battery present)
-+ battery present, no debounce timer
-+ battery present, debounce timer (going to battery lost)
-+ */
-+ if (fxo->battery == BATTERY_PRESENT) {
-+ if (fxo->battdebounce) {
-+ /* we were going to BATTERY_LOST, but battery appeared again,
-+ so clear the debounce timer */
-+ fxo->battdebounce = 0;
-+ }
-+ } else {
-+ if (fxo->battdebounce) {
-+ /* going to BATTERY_PRESENT, see if we are there yet */
-+ if (--fxo->battdebounce == 0) {
-+ fxo->battery = BATTERY_PRESENT;
-+ if (debug) {
-+ printk(KERN_DEBUG "BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1,
-+ (b < 0) ? "-" : "+");
-+ }
-+#ifdef ZERO_BATT_RING
-+ if (wc_dev->onhook) {
-+ wc_dev->onhook = 0;
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ if (debug) {
-+ printk(KERN_DEBUG "Signalled Off Hook\n");
-+ }
-+ }
-+#else
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+#endif
-+ /* set the alarm timer, taking into account that part of its time
-+ period has already passed while debouncing occurred */
-+ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
-+ }
-+ } else {
-+ /* start the debounce timer to verify that battery has appeared */
-+ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ }
-+
-+ if (fxo->lastpol >= 0) {
-+ if (b < 0) {
-+ fxo->lastpol = -1;
-+ fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ if (fxo->lastpol <= 0) {
-+ if (b > 0) {
-+ fxo->lastpol = 1;
-+ fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
-+ }
-+ }
-+ if (fxo->battalarm) {
-+ if (--fxo->battalarm == 0) {
-+ /* the alarm timer has expired, so update the battery alarm state
-+ for this channel */
-+ dahdi_alarm_channel(wc->chans[card], fxo->battery== BATTERY_LOST ? DAHDI_ALARM_RED:DAHDI_ALARM_NONE );
-+ }
-+ }
-+ if (fxo->polaritydebounce) {
-+ if (--fxo->polaritydebounce == 0) {
-+ if (fxo->lastpol != fxo->polarity) {
-+ if (debug) {
-+ printk(KERN_DEBUG "%lu Polarity reversed (%d -> %d)\n", jiffies,
-+ fxo->polarity,
-+ fxo->lastpol);
-+ }
-+ if (fxo->polarity) {
-+ if (cidsupport) {
-+ set_cidstart_desc_from_chan_num(wc->span.spanno, wc->chans[card]->channo, wc_dev->cid_state[card]);
-+ if (is_callerid_disable(wc->span.spanno, wc->chans[card]->channo)) {
-+ dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
-+ }
-+ } else {
-+ dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
-+ }
-+ }
-+ fxo->polarity = fxo->lastpol;
-+ }
-+ }
-+ }
-+#undef MS_PER_CHECK_HOOK
-+}
-+
-+
-+static void a24xx_post_initialize(struct a24xx *wc)
-+{
-+ int x;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ /* Finalize signalling */
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if (wc_dev->cardflag & (1 << x)) {
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ wc->chans[x]->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR;
-+ }
-+ else {
-+ wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR;
-+ }
-+ } else if (!(wc->chans[x]->sigcap & DAHDI_SIG_BROKEN)) {
-+ wc->chans[x]->sigcap = 0;
-+ }
-+ }
-+}
-+
-+static void a24xx_proslic_check_hook(struct a24xx *wc, int card)
-+{
-+ char res;
-+ int hook;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ /* For some reason we have to debounce the
-+ hook detector. */
-+
-+ res = wc_dev->reg0shadow[card];
-+ hook = (res & 1);
-+ if (hook != wc_dev->mod[card].fxs.lastrxhook) {
-+ /* Reset the debounce (must be multiple of 4ms) */
-+ wc_dev->mod[card].fxs.debounce = 8 * (4 * 8);
-+#if 0
-+ printk(KERN_DEBUG "Resetting debounce card %d hook %d, %d\n", card, hook, wc_dev->mod[card].fxs.debounce);
-+#endif
-+ } else {
-+ if (wc_dev->mod[card].fxs.debounce > 0) {
-+ wc_dev->mod[card].fxs.debounce-= 16 * DAHDI_CHUNKSIZE;
-+#if 0
-+ printk(KERN_DEBUG "Sustaining hook %d, %d\n", hook, wc_dev->mod[card].fxs.debounce);
-+#endif
-+ if (!wc_dev->mod[card].fxs.debounce) {
-+#if 0
-+ printk(KERN_DEBUG "Counted down debounce, newhook: %d...\n", hook);
-+#endif
-+ wc_dev->mod[card].fxs.debouncehook = hook;
-+ }
-+ if (!wc_dev->mod[card].fxs.oldrxhook && wc_dev->mod[card].fxs.debouncehook) {
-+ /* Off hook */
-+ if (debug) {
-+ printk(KERN_DEBUG "opvxa24xx: Card %d Going off hook\n", card);
-+ }
-+ switch (wc_dev->mod[card].fxs.lasttxhook) {
-+ case SLIC_LF_RINGING: /* Ringing */
-+ case SLIC_LF_OHTRAN_FWD: /* Forward On Hook Transfer */
-+ case SLIC_LF_OHTRAN_REV: /* Reverse On Hook Transfer */
-+ /* just detected OffHook, during Ringing or OnHookTransfer */
-+ wc_dev->mod[card].fxs.idletxhookstate = POLARITY_XOR(card) ?
-+ SLIC_LF_ACTIVE_REV :
-+ SLIC_LF_ACTIVE_FWD;
-+ break;
-+ }
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
-+ if (robust) {
-+ si321x_init_proslic(wc_dev, card, 1, 0, 1);
-+ }
-+ wc_dev->mod[card].fxs.oldrxhook = 1;
-+
-+ } else if (wc_dev->mod[card].fxs.oldrxhook && !wc_dev->mod[card].fxs.debouncehook) {
-+ /* On hook */
-+ if (debug) {
-+ printk(KERN_DEBUG "opvxa24xx: Card %d Going on hook\n", card);
-+ }
-+ dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
-+ wc_dev->mod[card].fxs.oldrxhook = 0;
-+ }
-+ }
-+ }
-+ wc_dev->mod[card].fxs.lastrxhook = hook;
-+}
-+
-+static void a24xx_transmit(struct a24xx *wc,unsigned int order)
-+{
-+ int x, y, pos;
-+ volatile unsigned char *txbuf;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ __opvx_a24xx_transmit(wc_dev->mem32, wc_dev->writechunk, &txbuf,ms_per_irq,order);
-+ //printk("ints is %d\n", ints);
-+ /* Calculate Transmission */
-+
-+ for (y=0;y<DAHDI_CHUNKSIZE;y++) {
-+#ifdef __BIG_ENDIAN
-+ // operation pending...
-+#else
-+ for (x=0;x<wc_dev->max_cards;x++) {
-+ pos = y * MAX_NUM_CARDS + x;
-+ txbuf[pos] = wc->chans[x]->writechunk[y];
-+ }
-+#endif
-+ }
-+}
-+
-+static void a24xx_receive(struct a24xx *wc,unsigned int order)
-+{
-+ int x, y;
-+ volatile unsigned char *rxbuf;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ __opvx_a24xx_receive(wc_dev->mem32, wc_dev->readchunk, &rxbuf ,ms_per_irq,order);
-+ for (x=0;x<DAHDI_CHUNKSIZE;x++) {
-+#ifdef __BIG_ENDIAN
-+ // operation pending...
-+#else
-+ for (y=0;y<wc_dev->max_cards/*MAX_NUM_CARDS*/;y++) {
-+ if (wc_dev->cardflag & (1 << y)) {
-+ wc->chans[y]->readchunk[x] = rxbuf[MAX_NUM_CARDS * x + y];
-+ }
-+#ifdef TEST_LOG_INCOME_VOICE
-+ wc_dev->voc_buf[y][wc_dev->voc_ptr[y]] = rxbuf[MAX_NUM_CARDS * x + y];
-+ wc_dev->voc_ptr[y]++;
-+ if(wc_dev->voc_ptr[y] >= voc_buffer_size) {
-+ wc_dev->voc_ptr[y] = 0;
-+ }
-+#endif
-+ }
-+#endif
-+ }
-+
-+#if 0
-+ if( (ints&0x0f) == 0x0f) { // dump buffer every 16 times;
-+ printk("dump 0x%x\n", ints);
-+ for(x=0; x<48; x++) {
-+ printk("0x%02x, ", (int)rxbuf[x]);
-+ //if( 15== (x%15) )
-+ }
-+ printk("\n");
-+ }
-+#endif
-+
-+ if(cidsupport) {
-+ parser_callerid_process(wc, cidbuflen, cidtimeout);
-+ }
-+
-+#ifdef AUDIO_RINGCHECK
-+ for (x=0;x<wc_dev->max_cards;x++) {
-+ ring_check(wc, x);
-+ }
-+#endif
-+ /* XXX We're wasting 8 taps. We should get closer :( */
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if (wc_dev->cardflag & (1 << x)) {
-+ dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->chans[x]->writechunk);
-+ }
-+ }
-+}
-+
-+#if 0
-+DAHDI_IRQ_HANDLER(a24xx_interrupt)
-+{
-+ unsigned int ints;
-+ int x, y, z,order;
-+ int mode;
-+ struct a24xx *wc = dev_id;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ struct fxs * fxs ;
-+
-+ ints = __opvx_a24xx_get_irqstatus(wc_dev->mem32);
-+
-+ if (!ints)
-+ return IRQ_NONE;
-+
-+ __opvx_a24xx_set_irqstatus(wc_dev->mem32, ints); // clear interrupt register.
-+
-+ for (x=0;x<wc_dev->max_cards; x++) {
-+ if (wc_dev->cardflag & (1 << x) && (wc_dev->modtype[x] == MOD_TYPE_FXS)) {
-+
-+ fxs = &wc_dev->mod[x].fxs;
-+
-+ if (SLIC_LF_RINGING == fxs->lasttxhook && !fxs->neonringing) {
-+ /* RINGing, prepare for OHT */
-+ fxs->ohttimer = OHT_TIMER << 3;
-+ /* OHT mode when idle */
-+ fxs->idletxhookstate = POLARITY_XOR(x) ? SLIC_LF_OHTRAN_REV :
-+ SLIC_LF_OHTRAN_FWD;
-+ } else if (fxs->ohttimer) {
-+ /* check if still OnHook */
-+ if (!fxs->oldrxhook) {
-+ fxs->ohttimer -= DAHDI_CHUNKSIZE;
-+ if (fxs->ohttimer)
-+ continue;
-+
-+ /* Switch to active */
-+ fxs->idletxhookstate = POLARITY_XOR(x) ? SLIC_LF_ACTIVE_REV :
-+ SLIC_LF_ACTIVE_FWD;
-+ /* if currently OHT */
-+ if ((fxs->lasttxhook == SLIC_LF_OHTRAN_FWD) || (fxs->lasttxhook == SLIC_LF_OHTRAN_REV)) {
-+ if (fxs->vmwi_hvac) {
-+ /* force idle polarity Forward if ringing */
-+ fxs->idletxhookstate = SLIC_LF_ACTIVE_FWD;
-+ /* Set ring generator for neon */
-+ si321x_set_ring_generator_mode(wc_dev, x, 1);
-+ fxs->lasttxhook = SLIC_LF_RINGING;
-+ } else {
-+ fxs->lasttxhook = fxs->idletxhookstate;
-+ }
-+ /* Apply the change as appropriate */
-+ a24xx_spi_setreg(wc_dev, x, LINE_STATE, fxs->lasttxhook);
-+ }
-+ } else {
-+ fxs->ohttimer = 0;
-+ /* Switch to active */
-+ fxs->idletxhookstate = POLARITY_XOR(x) ? SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD;
-+ printk("Channel %d OnHookTransfer abort\n",x);
-+ }
-+ }
-+ }
-+ }
-+
-+ if (ints & (1<<16)) { /* it is our interrupts */
-+ wc_dev->intcount++;
-+ switch(ms_per_irq){
-+ case 1:
-+ z = wc_dev->intcount & 0x3;
-+ mode = wc_dev->intcount & 0xc;
-+ for(y = 0; y < wc_dev->max_cards / 4; y++) { /* do some detect operate every 4ms */
-+ x = z + y*4;
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 4:
-+ /* Read first shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ //if(x==0)
-+ //printk("reg 68 of %x is 0x%x\n", x, wc_dev->reg0shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ break;
-+ case 8:
-+ /* Read second shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ //if(x==1)
-+ // printk("reg 64 of %x is 0x%x\n", x, wc_dev->reg1shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ break;
-+ case 12:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & 0xf0)) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ } else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 2:
-+ z = wc_dev->intcount & 0x1;
-+ mode = wc_dev->intcount & 0x6;
-+ for(y = 0; y < wc_dev->max_cards / 2; y++) { /* do some detect operate every 4ms */
-+ x = z + y*2;
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 2:
-+ /* Read first shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ //if(x==0)
-+ //printk("reg 68 of %x is 0x%x\n", x, wc_dev->reg0shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ break;
-+ case 4:
-+ /* Read second shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ //if(x==1)
-+ // printk("reg 64 of %x is 0x%x\n", x, wc_dev->reg1shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ break;
-+ case 6:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>1))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ } else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 4:
-+ mode = wc_dev->intcount & 0x3;
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 1:
-+ /* Read first shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ //if(x==0)
-+ //printk("reg 68 of %x is 0x%x\n", x, wc_dev->reg0shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ break;
-+ case 2:
-+ /* Read second shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ //if(x==1)
-+ // printk("reg 64 of %x is 0x%x\n", x, wc_dev->reg1shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ break;
-+ case 3:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>2))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 8:
-+ mode = wc_dev->intcount & 0x1;
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 1:
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO){
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ }
-+ break;
-+ case 0:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>3))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 16:
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>4))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO){
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ }
-+ }
-+ break;
-+ }
-+
-+ if (!(wc_dev->intcount % ( 10000/ms_per_irq ))) {
-+ /* Accept an alarm once per 10 seconds */
-+ for (x=0;x<wc_dev->max_cards;x++)
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ if (wc_dev->mod[x].fxs.palarms) {
-+ wc_dev->mod[x].fxs.palarms--;
-+ }
-+ }
-+ }
-+ /**/
-+ for(order=0;order < ms_per_irq;order++){
-+ a24xx_receive(wc, order);
-+ dahdi_receive(&wc->span);
-+
-+ dahdi_transmit(&wc->span);
-+ a24xx_transmit(wc, order);
-+ }
-+ }
-+
-+ return IRQ_RETVAL(1);
-+}
-+#endif
-+
-+#if 1
-+static int interrupt_onecard_handler(struct a24xx *wc)
-+{
-+ unsigned int ints=0;
-+ int x, y, z,order;
-+ int mode;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ struct fxs * fxs ;
-+
-+ if((wc_dev->fwversion < ((1 << 16)|3)) || (wc_dev->master)){
-+ ints = __opvx_a24xx_get_irqstatus(wc_dev->mem32);
-+ if (!ints)
-+ return IRQ_NONE;
-+ }
-+
-+ __opvx_a24xx_set_irqstatus(wc_dev->mem32, ints); // clear interrupt register.
-+
-+ for (x=0;x<wc_dev->max_cards; x++) {
-+ if (wc_dev->cardflag & (1 << x) && (wc_dev->modtype[x] == MOD_TYPE_FXS)) {
-+ fxs = &wc_dev->mod[x].fxs;
-+
-+ if (SLIC_LF_RINGING == fxs->lasttxhook && !fxs->neonringing) {
-+ /* RINGing, prepare for OHT */
-+ fxs->ohttimer = OHT_TIMER << 3;
-+ /* OHT mode when idle */
-+ fxs->idletxhookstate = POLARITY_XOR(x) ? SLIC_LF_OHTRAN_REV :
-+ SLIC_LF_OHTRAN_FWD;
-+ } else if (fxs->ohttimer) {
-+ /* check if still OnHook */
-+ if (!fxs->oldrxhook) {
-+ fxs->ohttimer -= DAHDI_CHUNKSIZE;
-+ if (fxs->ohttimer)
-+ continue;
-+
-+ /* Switch to active */
-+ fxs->idletxhookstate = POLARITY_XOR(x) ? SLIC_LF_ACTIVE_REV :
-+ SLIC_LF_ACTIVE_FWD;
-+ /* if currently OHT */
-+ if ((fxs->lasttxhook == SLIC_LF_OHTRAN_FWD) || (fxs->lasttxhook == SLIC_LF_OHTRAN_REV)) {
-+ if (fxs->vmwi_hvac) {
-+ /* force idle polarity Forward if ringing */
-+ fxs->idletxhookstate = SLIC_LF_ACTIVE_FWD;
-+ /* Set ring generator for neon */
-+ si321x_set_ring_generator_mode(wc_dev, x, 1);
-+ fxs->lasttxhook = SLIC_LF_RINGING;
-+ } else {
-+ fxs->lasttxhook = fxs->idletxhookstate;
-+ }
-+ /* Apply the change as appropriate */
-+ a24xx_spi_setreg(wc_dev, x, LINE_STATE, fxs->lasttxhook);
-+ }
-+ } else {
-+ fxs->ohttimer = 0;
-+ /* Switch to active */
-+ fxs->idletxhookstate = POLARITY_XOR(x) ? SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD;
-+ printk("Channel %d OnHookTransfer abort\n",x);
-+ }
-+ }
-+ }
-+ }
-+
-+ if ( ((ints & (1<<16)) && wc_dev->master) || (!wc_dev->master)) { /* it is our interrupts */
-+ wc_dev->intcount++;
-+ switch(ms_per_irq){
-+ case 1:
-+ z = wc_dev->intcount & 0x3;
-+ mode = wc_dev->intcount & 0xc;
-+ for(y = 0; y < wc_dev->max_cards / 4; y++) { /* do some detect operate every 4ms */
-+ x = z + y*4;
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 4:
-+ /* Read first shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ //if(x==0)
-+ //printk("reg 68 of %x is 0x%x\n", x, wc_dev->reg0shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ break;
-+ case 8:
-+ /* Read second shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ //if(x==1)
-+ // printk("reg 64 of %x is 0x%x\n", x, wc_dev->reg1shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ break;
-+ case 12:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & 0xf0)) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ } else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 2:
-+ z = wc_dev->intcount & 0x1;
-+ mode = wc_dev->intcount & 0x6;
-+ for(y = 0; y < wc_dev->max_cards / 2; y++) { /* do some detect operate every 4ms */
-+ x = z + y*2;
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 2:
-+ /* Read first shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ //if(x==0)
-+ //printk("reg 68 of %x is 0x%x\n", x, wc_dev->reg0shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ break;
-+ case 4:
-+ /* Read second shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ //if(x==1)
-+ // printk("reg 64 of %x is 0x%x\n", x, wc_dev->reg1shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ break;
-+ case 6:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>1))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ } else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 4:
-+ mode = wc_dev->intcount & 0x3;
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 0:
-+ /* Rest */
-+ break;
-+ case 1:
-+ /* Read first shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ //if(x==0)
-+ //printk("reg 68 of %x is 0x%x\n", x, wc_dev->reg0shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ break;
-+ case 2:
-+ /* Read second shadow reg */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ //if(x==1)
-+ // printk("reg 64 of %x is 0x%x\n", x, wc_dev->reg1shadow[x]);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO)
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ break;
-+ case 3:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>2))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 8:
-+ mode = wc_dev->intcount & 0x1;
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ switch(mode) {
-+ case 1:
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO){
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ }
-+ break;
-+ case 0:
-+ /* Perform processing */
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>3))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO) {
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ break;
-+ }
-+ }
-+ }
-+ break;
-+ case 16:
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if (wc_dev->cardflag & (1 << x ) ) {
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 68);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 64);
-+ a24xx_proslic_check_hook(wc, x);
-+ if (!(wc_dev->intcount & (0xf0>>4))) {
-+ si321x_proslic_recheck_sanity(wc_dev, x);
-+ }
-+ }
-+ else if (wc_dev->modtype[x] == MOD_TYPE_FXO){
-+ wc_dev->reg0shadow[x] = a24xx_spi_getreg(wc_dev, x, 5);
-+ wc_dev->reg1shadow[x] = a24xx_spi_getreg(wc_dev, x, 29);
-+ a24xx_voicedaa_check_hook(wc, x);
-+ }
-+ }
-+ }
-+ break;
-+ }
-+
-+ if (!(wc_dev->intcount % ( 10000/ms_per_irq ))) {
-+ /* Accept an alarm once per 10 seconds */
-+ for (x=0;x<wc_dev->max_cards;x++)
-+ if (wc_dev->modtype[x] == MOD_TYPE_FXS) {
-+ if (wc_dev->mod[x].fxs.palarms) {
-+ wc_dev->mod[x].fxs.palarms--;
-+ }
-+ }
-+ }
-+ /**/
-+ for(order=0;order < ms_per_irq;order++){
-+ dahdi_transmit(&wc->span);
-+ parser_busy_silent_process(wc, 1);
-+ a24xx_transmit(wc, order);
-+
-+ a24xx_receive(wc, order);
-+ parser_busy_silent_process(wc, 0);
-+ dahdi_receive(&wc->span);
-+ }
-+ }
-+ return 0;
-+}
-+
-+DAHDI_IRQ_HANDLER(a24xx_interrupt)
-+{
-+ /**/
-+ struct a24xx *wc = dev_id;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ int i;
-+
-+ if(!wc_dev->master){
-+ interrupt_onecard_handler(wc);
-+ }else{
-+ if(irq_stub){
-+ for(i=0;i<max_iface_index;i++){
-+ wc = ifaces[i];
-+ if(wc){
-+ wc_dev = &wc->dev;
-+ if( wc_dev->fwversion >= ((1 << 16)|2) ){
-+ interrupt_onecard_handler(wc);
-+ }
-+ }
-+ }
-+ }else
-+ interrupt_onecard_handler(wc);
-+ }
-+
-+
-+ return IRQ_RETVAL(1);
-+}
-+#endif
-+/* Must be called from within an interruptible context */
-+static int set_vmwi(struct a24xx *wc, int chan_idx)
-+{
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ struct fxs *const fxs = &wc_dev->mod[chan_idx].fxs;
-+
-+ if (fxs->vmwi_active_messages) {
-+ fxs->vmwi_lrev =
-+ (fxs->vmwisetting.vmwi_type & DAHDI_VMWI_LREV) ? 1 : 0;
-+ fxs->vmwi_hvdc =
-+ (fxs->vmwisetting.vmwi_type & DAHDI_VMWI_HVDC) ? 1 : 0;
-+ fxs->vmwi_hvac =
-+ (fxs->vmwisetting.vmwi_type & DAHDI_VMWI_HVAC) ? 1 : 0;
-+ } else {
-+ fxs->vmwi_lrev = 0;
-+ fxs->vmwi_hvdc = 0;
-+ fxs->vmwi_hvac = 0;
-+ }
-+
-+ if (debug) {
-+ printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, "
-+ "lrev=%d, hvdc=%d, hvac=%d\n",
-+ chan_idx,
-+ fxs->vmwi_active_messages,
-+ fxs->vmwi_lrev,
-+ fxs->vmwi_hvdc,
-+ fxs->vmwi_hvac
-+ );
-+ }
-+
-+ if (fxs->vmwi_hvac) {
-+ /* Can't change ring generator while in On Hook Transfer mode*/
-+ if (!fxs->ohttimer) {
-+ if (POLARITY_XOR(chan_idx))
-+ fxs->idletxhookstate |= SLIC_LF_REVMASK;
-+ else
-+ fxs->idletxhookstate &= ~SLIC_LF_REVMASK;
-+ /* Set ring generator for neon */
-+ si321x_set_ring_generator_mode(wc_dev, chan_idx, 1);
-+ /* Activate ring to send neon pulses */
-+ fxs->lasttxhook = SLIC_LF_RINGING;
-+ a24xx_spi_setreg(wc_dev, chan_idx, LINE_STATE, fxs->lasttxhook);
-+ }
-+ } else {
-+ if (fxs->neonringing) {
-+ /* Set ring generator for normal ringer */
-+ si321x_set_ring_generator_mode(wc_dev, chan_idx, 0);
-+ /* ACTIVE, polarity determined later */
-+ fxs->lasttxhook = SLIC_LF_ACTIVE_FWD;
-+ } else if ((fxs->lasttxhook == SLIC_LF_RINGING) ||
-+ (fxs->lasttxhook == SLIC_LF_OPEN)) {
-+ /* Can't change polarity while ringing or when open,
-+ set idlehookstate instead */
-+ if (POLARITY_XOR(chan_idx))
-+ fxs->idletxhookstate |= SLIC_LF_REVMASK;
-+ else
-+ fxs->idletxhookstate &= ~SLIC_LF_REVMASK;
-+ if(debug)
-+ printk(KERN_DEBUG "Unable to change polarity on channel"
-+ "%d, lasttxhook=0x%X\n",
-+ chan_idx,
-+ fxs->lasttxhook
-+ );
-+ return 0;
-+ }
-+ if (POLARITY_XOR(chan_idx)) {
-+ fxs->idletxhookstate |= SLIC_LF_REVMASK;
-+ fxs->lasttxhook |= SLIC_LF_REVMASK;
-+ } else {
-+ fxs->idletxhookstate &= ~SLIC_LF_REVMASK;
-+ fxs->lasttxhook &= ~SLIC_LF_REVMASK;
-+ }
-+ a24xx_spi_setreg(wc_dev, chan_idx, LINE_STATE, fxs->lasttxhook);
-+ }
-+ return 0;
-+}
-+
-+static int a24xx_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data)
-+{
-+ struct wctdm_stats stats;
-+ struct wctdm_regs regs;
-+ struct wctdm_regop regop;
-+ struct wctdm_echo_coefs echoregs;
-+ struct dahdi_hwgain hwgain;
-+ struct a24xx *wc = chan->pvt;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ int x;
-+
-+ struct fxs *const fxs = &wc_dev->mod[chan->chanpos - 1].fxs;
-+
-+ switch (cmd) {
-+ case DAHDI_ONHOOKTRANSFER:
-+ if (wc_dev->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) {
-+ return -EINVAL;
-+ }
-+ if (get_user(x, (__user int *)data)) {
-+ return -EFAULT;
-+ }
-+#if 0
-+ /**/
-+ wc_dev->mod[chan->chanpos - 1].fxs.ohttimer = x << 3;
-+ if (reversepolarity) {
-+ wc_dev->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6; /* OHT mode when idle */
-+ } else {
-+ wc_dev->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2;
-+ }
-+ if (wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) {
-+ /* Apply the change if appropriate */
-+ if (reversepolarity) {
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6;
-+ } else {
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook = 0x2;
-+ }
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 64, wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook);
-+ }
-+#endif
-+#if 1
-+ /* Active mode when idle */
-+ wc_dev->mod[chan->chanpos - 1].fxs.idletxhookstate = POLARITY_XOR(chan->chanpos - 1) ?
-+ SLIC_LF_ACTIVE_REV : SLIC_LF_ACTIVE_FWD;
-+ if (wc_dev->mod[chan->chanpos - 1].fxs.neonringing) {
-+ /* keep same Forward polarity */
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook = SLIC_LF_OHTRAN_FWD;
-+ //printk(KERN_INFO "ioctl: Start OnHookTrans, card %d\n",chan->chanpos - 1);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1,
-+ LINE_STATE, wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook);
-+ } else if (wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook == SLIC_LF_ACTIVE_FWD ||
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook == SLIC_LF_ACTIVE_REV) {
-+ /* Apply the change if appropriate */
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook = POLARITY_XOR(chan->chanpos - 1) ?
-+ SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD;
-+ //printk(KERN_INFO "ioctl: Start OnHookTrans, card %d\n",chan->chanpos - 1);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1,
-+ LINE_STATE, wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook);
-+ }
-+#endif
-+ break;
-+#if 1
-+ case DAHDI_VMWI_CONFIG:
-+ if (wc_dev->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
-+ return -EINVAL;
-+ if (copy_from_user(&(fxs->vmwisetting),
-+ (__user void *)data,
-+ sizeof(fxs->vmwisetting)))
-+ return -EFAULT;
-+ //printk("--opvxa24xx:DAHDI_VMWI_CONFIG,card=%d--\n",chan->chanpos - 1);
-+ set_vmwi(wc, chan->chanpos - 1);
-+ break;
-+ case DAHDI_VMWI:
-+ if (wc_dev->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
-+ return -EINVAL;
-+ if (get_user(x, (__user int *) data))
-+ return -EFAULT;
-+ if (0 > x)
-+ return -EFAULT;
-+ fxs->vmwi_active_messages = x;
-+ set_vmwi(wc, chan->chanpos - 1);
-+ //printk("-----opvxa24xx,DAHDI_VMWI,card=%d,set_vmwi------\n",chan->chanpos - 1);
-+ break;
-+#endif
-+ case DAHDI_SETPOLARITY:
-+ if (get_user(x, (__user int *)data)) {
-+ return -EFAULT;
-+ }
-+ if (wc_dev->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) {
-+ return -EINVAL;
-+ }
-+ /* Can't change polarity while ringing or when open */
-+ if ((wc_dev->mod[chan->chanpos -1 ].fxs.lasttxhook == SLIC_LF_RINGING) ||
-+ (wc_dev->mod[chan->chanpos -1 ].fxs.lasttxhook == SLIC_LF_OPEN)) {
-+ return -EINVAL;
-+ }
-+ wc_dev->mod[chan->chanpos -1 ].fxs.reversepolarity = x;
-+#if 0
-+ if ((x && !reversepolarity) || (!x && reversepolarity)) {
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04;
-+ } else {
-+ wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04;
-+ }
-+#endif
-+ if (POLARITY_XOR(chan->chanpos - 1)) {
-+ wc_dev->mod[chan->chanpos -1 ].fxs.lasttxhook |= SLIC_LF_REVMASK;
-+ printk(KERN_INFO "ioctl: Reverse Polarity, card %d\n",
-+ chan->chanpos - 1);
-+ } else {
-+ wc_dev->mod[chan->chanpos -1 ].fxs.lasttxhook &= ~SLIC_LF_REVMASK;
-+ printk(KERN_INFO "ioctl: Normal Polarity, card %d\n",
-+ chan->chanpos - 1);
-+ }
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, LINE_STATE, wc_dev->mod[chan->chanpos - 1].fxs.lasttxhook);
-+ break;
-+ case WCTDM_GET_STATS:
-+ if (wc_dev->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-+ stats.tipvolt = a24xx_spi_getreg(wc_dev, chan->chanpos - 1, 80) * -376;
-+ stats.ringvolt = a24xx_spi_getreg(wc_dev, chan->chanpos - 1, 81) * -376;
-+ stats.batvolt = a24xx_spi_getreg(wc_dev, chan->chanpos - 1, 82) * -376;
-+ } else if (wc_dev->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
-+ stats.tipvolt = (signed char)a24xx_spi_getreg(wc_dev, chan->chanpos - 1, 29) * 1000;
-+ stats.ringvolt = (signed char)a24xx_spi_getreg(wc_dev, chan->chanpos - 1, 29) * 1000;
-+ stats.batvolt = (signed char)a24xx_spi_getreg(wc_dev, chan->chanpos - 1, 29) * 1000;
-+ } else {
-+ return -EINVAL;
-+ }
-+ if (copy_to_user((__user void*)data, &stats, sizeof(stats))) {
-+ return -EFAULT;
-+ }
-+ break;
-+ case WCTDM_GET_REGS:
-+ if (wc_dev->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-+ for (x=0;x<NUM_INDIRECT_REGS;x++) {
-+ regs.indirect[x] = si321x_proslic_getreg_indirect(wc_dev, chan->chanpos -1, x);
-+ }
-+ for (x=0;x<NUM_REGS;x++) {
-+ regs.direct[x] = a24xx_spi_getreg(wc_dev, chan->chanpos - 1, x);
-+ }
-+ } else {
-+ memset(&regs, 0, sizeof(regs));
-+ for (x=0;x<NUM_FXO_REGS;x++)
-+ regs.direct[x] = a24xx_spi_getreg(wc_dev, chan->chanpos - 1, x);
-+ }
-+ if (copy_to_user((__user void *)data, &regs, sizeof(regs))) {
-+ return -EFAULT;
-+ }
-+ break;
-+ case WCTDM_SET_REG:
-+ if (copy_from_user(&regop, (__user void *)data, sizeof(regop))) {
-+ return -EFAULT;
-+ }
-+ if (regop.indirect) {
-+ if (wc_dev->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) {
-+ return -EINVAL;
-+ }
-+ printk(KERN_INFO "Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos);
-+ si321x_proslic_setreg_indirect(wc_dev, chan->chanpos - 1, regop.reg, regop.val);
-+ } else {
-+ regop.val &= 0xff;
-+ printk(KERN_INFO "Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, regop.reg, regop.val);
-+ }
-+ break;
-+ case WCTDM_SET_ECHOTUNE:
-+ printk(KERN_INFO "-- Setting echo registers: \n");
-+ if (copy_from_user(&echoregs, (__user void *)data, sizeof(echoregs))) {
-+ return -EFAULT;
-+ }
-+
-+ if (wc_dev->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
-+ /* Set the ACIM register */
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 30, (fxofullscale==1) ? (echoregs.acim|0x10) : echoregs.acim);
-+
-+ /* Set the digital echo canceller registers */
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 45, echoregs.coef1);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 46, echoregs.coef2);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 47, echoregs.coef3);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 48, echoregs.coef4);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 49, echoregs.coef5);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 50, echoregs.coef6);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 51, echoregs.coef7);
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 52, echoregs.coef8);
-+
-+ printk(KERN_INFO "-- Set echo registers successfully\n");
-+
-+ break;
-+ } else {
-+ return -EINVAL;
-+ }
-+ break;
-+ case DAHDI_SET_HWGAIN:
-+ if (copy_from_user(&hwgain, (__user void *) data, sizeof(hwgain))) {
-+ return -EFAULT;
-+ }
-+
-+ si3050_set_hwgain(wc_dev, chan->chanpos-1, hwgain.newgain, hwgain.tx);
-+
-+ if (debug) {
-+ printk(KERN_DEBUG "Setting hwgain on channel %d to %d for %s direction\n",
-+ chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx");
-+ }
-+ break;
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+
-+}
-+
-+static int a24xx_open(struct dahdi_chan *chan)
-+{
-+ int channo;
-+
-+ struct a24xx *wc = chan->pvt;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ channo = chan->chanpos - 1;
-+
-+ if (!(wc_dev->cardflag & (1 << (chan->chanpos - 1)))) {
-+ return -ENODEV;
-+ }
-+ if (wc_dev->dead) {
-+ return -ENODEV;
-+ }
-+ wc_dev->usecount++;
-+
-+ try_module_get(THIS_MODULE);
-+
-+ return 0;
-+}
-+
-+static inline struct a24xx *a24xx_from_span(struct dahdi_span *span)
-+{
-+ return container_of(span, struct a24xx, span);
-+}
-+
-+static int a24xx_watchdog(struct dahdi_span *span, int event)
-+{
-+ struct a24xx *wc = a24xx_from_span(span);
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ printk(KERN_INFO "opvxa24xx: Restarting DMA\n");
-+ __opvx_a24xx_restart_dma(wc_dev->mem32);
-+
-+ return 0;
-+}
-+
-+static int a24xx_close(struct dahdi_chan *chan)
-+{
-+ struct a24xx *wc = chan->pvt;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ wc_dev->usecount--;
-+
-+ module_put(THIS_MODULE);
-+
-+ if (wc_dev->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
-+ /*
-+ if (reversepolarity) {
-+ wc_dev->mod[chan->chanpos - 1].fxs.idletxhookstate = 5;
-+ }
-+ else {
-+ wc_dev->mod[chan->chanpos - 1].fxs.idletxhookstate = 1;
-+ }*/
-+ int idlehookstate;
-+ idlehookstate = POLARITY_XOR(chan->chanpos - 1)?
-+ SLIC_LF_ACTIVE_REV :
-+ SLIC_LF_ACTIVE_FWD;
-+ wc_dev->mod[chan->chanpos - 1].fxs.idletxhookstate = idlehookstate;
-+ }
-+ /* If we're dead, release us now */
-+ if (!wc_dev->usecount && wc_dev->dead) {
-+ a24xx_release(wc);
-+ }
-+ return 0;
-+}
-+
-+static int a24xx_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
-+{
-+ int reg=0;
-+ struct a24xx *wc = chan->pvt;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ if (wc_dev->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
-+ /* XXX Enable hooksig for FXO XXX */
-+ switch(txsig) {
-+ case DAHDI_TXSIG_START:
-+ case DAHDI_TXSIG_OFFHOOK:
-+ wc_dev->mod[chan->chanpos - 1].fxo.offhook = 1;
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 5, 0x9);
-+ if(cidsupport) {
-+ wc_dev->cid_state[chan->chanpos - 1] = CID_STATE_IDLE;
-+ wc_dev->cid_history_clone_cnt[chan->chanpos - 1] = 0;
-+ wc_dev->cid_history_ptr[chan->chanpos - 1] = 0;
-+ memset(wc_dev->cid_history_buf[chan->chanpos - 1], DAHDI_LIN2X(0, chan), cidbuflen * DAHDI_MAX_CHUNKSIZE);
-+ }
-+ break;
-+ case DAHDI_TXSIG_ONHOOK:
-+ wc_dev->mod[chan->chanpos - 1].fxo.offhook = 0;
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 5, 0x8);
-+ break;
-+ default:
-+ printk(KERN_NOTICE "wcfxo: Can't set tx state to %d\n", txsig);
-+ }
-+ } else {
-+ switch(txsig) {
-+ case DAHDI_TXSIG_ONHOOK:
-+ switch(chan->sig) {
-+ case DAHDI_SIG_EM:
-+ case DAHDI_SIG_FXOKS:
-+ case DAHDI_SIG_FXOLS:
-+ //wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = wc_dev->mod[chan->chanpos-1].fxs.idletxhookstate;
-+ /* Can't change Ring Generator during OHT */
-+ if (!wc_dev->mod[chan->chanpos-1].fxs.ohttimer) {
-+ si321x_set_ring_generator_mode(wc_dev,
-+ chan->chanpos-1, wc_dev->mod[chan->chanpos-1].fxs.vmwi_hvac);
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = wc_dev->mod[chan->chanpos-1].fxs.vmwi_hvac ? SLIC_LF_RINGING : wc_dev->mod[chan->chanpos-1].fxs.idletxhookstate;
-+ } else {
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = wc_dev->mod[chan->chanpos-1].fxs.idletxhookstate;
-+ }
-+ break;
-+ case DAHDI_SIG_FXOGS:
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = 3;
-+ break;
-+ }
-+ break;
-+ case DAHDI_TXSIG_OFFHOOK:
-+ switch(chan->sig) {
-+ case DAHDI_SIG_EM:
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = 5;
-+ break;
-+ default:
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = wc_dev->mod[chan->chanpos-1].fxs.idletxhookstate;
-+ break;
-+ }
-+ break;
-+ case DAHDI_TXSIG_START:
-+ //wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = 4;
-+ si321x_set_ring_generator_mode(wc_dev,
-+ chan->chanpos-1, 0);
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = SLIC_LF_RINGING;
-+ break;
-+ case DAHDI_TXSIG_KEWL:
-+ wc_dev->mod[chan->chanpos-1].fxs.lasttxhook = 0;
-+ break;
-+ default:
-+ printk(KERN_NOTICE "opvxa24xx: Can't set tx state to %d\n", txsig);
-+ }
-+ if (debug) {
-+ printk(KERN_DEBUG "Setting FXS hook state to %d (%02x)\n", txsig, reg);
-+ }
-+
-+#if 1
-+ a24xx_spi_setreg(wc_dev, chan->chanpos - 1, 64, wc_dev->mod[chan->chanpos-1].fxs.lasttxhook);
-+#endif
-+ }
-+ return 0;
-+}
-+
-+#ifdef DAHDI_SPAN_OPS
-+static const struct dahdi_span_ops a24xx_span_ops = {
-+ .owner = THIS_MODULE,
-+ .hooksig = a24xx_hooksig,
-+ .open = a24xx_open,
-+ .close = a24xx_close,
-+ .ioctl = a24xx_ioctl,
-+ .watchdog = a24xx_watchdog,
-+#ifdef VPM_SUPPORT
-+ .echocan_create = a24xx_echocan_create,
-+#endif
-+
-+};
-+#endif
-+
-+static int a24xx_init_spans(struct a24xx *wc)
-+{
-+ int x;
-+ struct a24xx_dev *wc_dev = &(wc->dev);
-+
-+ /* Zapata stuff */
-+ sprintf(wc->span.name, "OPVXA24XX/%d", wc_dev->pos);
-+ snprintf(wc->span.desc, sizeof(wc->span.desc)-1, "%s Board %d", wc_dev->variety, wc_dev->pos + 1);
-+// snprintf(wc->span.location, sizeof(wc->span.location) - 1,
-+// "PCI Bus %02d Slot %02d", wc_dev->dev->bus->number, PCI_SLOT(wc_dev->dev->devfn) + 1);
-+ wc_dev->ddev->location = kasprintf(GFP_KERNEL,
-+ "PCI Bus %02d Slot %02d",
-+ wc_dev->dev->bus->number,
-+ PCI_SLOT(wc_dev->dev->devfn) + 1);
-+
-+ //printk("wc is 0x%x, wc_dev ix 0x%x, ddev is 0x%x\n", wc, &(wc->dev), wc_dev->ddev);
-+ if (!wc_dev->ddev->location) {
-+ dahdi_free_device(wc_dev->ddev);
-+ wc_dev->ddev = NULL;
-+ return -ENOMEM;
-+ }
-+
-+ wc_dev->ddev->manufacturer = "OpenVox"; //Dennis
-+ wc_dev->ddev->devicetype = wc_dev->variety;
-+
-+ if (alawoverride) {
-+ printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
-+ wc->span.deflaw = DAHDI_LAW_ALAW;
-+ } else {
-+ wc->span.deflaw = DAHDI_LAW_MULAW;
-+ }
-+
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ sprintf(wc->chans[x]->name, "OPVXA24XX/%d/%d", wc_dev->pos, x);
-+ wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR;
-+ wc->chans[x]->sigcap |= DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR;
-+ wc->chans[x]->chanpos = x+1;
-+ wc->chans[x]->pvt = wc;
-+ }
-+
-+#ifdef DAHDI_SPAN_MODULE
-+ wc->span.owner = THIS_MODULE;
-+#endif
-+#ifdef DAHDI_SPAN_OPS
-+ wc->span.ops = &a24xx_span_ops;
-+#else
-+ wc->span.hooksig = a24xx_hooksig;
-+ wc->span.open = a24xx_open;
-+ wc->span.close = a24xx_close;
-+ wc->span.ioctl = a24xx_ioctl;
-+ wc->span.watchdog = a24xx_watchdog;
-+#ifdef VPM_SUPPORT
-+ if (vpmsupport)
-+ wc->span.echocan_create = a24xx_echocan_create;
-+#endif
-+ wc->span.pvt = wc;
-+#endif
-+ wc->span.chans = wc->chans;
-+ wc->span.channels = wc_dev->max_cards; /*MAX_NUM_CARDS;*/
-+ wc->span.flags = DAHDI_FLAG_RBS;
-+// init_waitqueue_head(&wc->span.maintq);
-+ list_add_tail(&wc->span.device_node, &wc->dev.ddev->spans);
-+// init_waitqueue_head(&wc->regq)
-+
-+ if (dahdi_register_device(wc_dev->ddev, &wc->dev.dev->dev)) {
-+ printk(KERN_NOTICE "Unable to register span with Dahdi\n");
-+ kfree(wc_dev->ddev->location);
-+ dahdi_free_device(wc_dev->ddev);
-+ wc_dev->ddev = NULL;
-+ printk("dahdi_register_device fail\n");
-+ mdelay(3000);
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static int __devinit a24xx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-+{
-+ int res;
-+ int x;
-+ int y;
-+ struct a24xx *wc;
-+ struct a24xx_desc *d = (struct a24xx_desc *)ent->driver_data;
-+ struct a24xx_dev *wc_dev;
-+ unsigned int fwbuild;
-+ char span_flags[MAX_NUM_CARDS] = { 0, };
-+ int z,index;
-+ static int initd_ifaces=0;
-+
-+ if(!initd_ifaces){
-+ memset((void *)ifaces,0,(sizeof(struct a24xx *))*WC_MAX_IFACES);
-+ initd_ifaces=1;
-+ }
-+ for (x = 0; x < WC_MAX_IFACES; x++) {
-+ if (!ifaces[x]) {
-+ break;
-+ }
-+ }
-+ if (x >= WC_MAX_IFACES) {
-+ printk("Too many interfaces\n");
-+ return -EIO;
-+ }
-+ index = x;
-+
-+ if (pci_enable_device(pdev)) {
-+ res = -EIO;
-+ } else {
-+ int cardcount = 0;
-+
-+ wc = kmalloc(sizeof(struct a24xx), GFP_KERNEL);
-+ if(!wc)
-+ return -ENOMEM;
-+
-+ memset(wc, 0, sizeof(struct a24xx));
-+ wc->dev.ddev = dahdi_create_device();
-+#if 0
-+ printk("wc is 0x%x, ddev is 0x%x\n", wc, wc->dev.ddev);
-+#endif
-+ if (!wc->dev.ddev) {
-+ kfree(wc);
-+ return -ENOMEM;
-+ }
-+ wc_dev = &wc->dev;
-+ wc_dev->ledstate = 0;
-+
-+ for (x=0; x < sizeof(wc->chans)/sizeof(wc->chans[0]); ++x) {
-+ wc->chans[x] = &wc->_chans[x];
-+ }
-+
-+ spin_lock_init(&wc_dev->lock);
-+ wc_dev->curcard = -1;
-+
-+ if(ent->device == 0x0810)
-+ wc_dev->max_cards = 8;
-+ else if(ent->device == 0x1610)
-+ wc_dev->max_cards = 16;
-+ else
-+ wc_dev->max_cards = 24;
-+
-+ wc_dev->mem_region = pci_resource_start(pdev, 0);
-+ wc_dev->mem_len = pci_resource_len(pdev, 0);
-+ wc_dev->mem32 = (unsigned long)ioremap(wc_dev->mem_region, wc_dev->mem_len);
-+ wc_dev->dev = pdev;
-+ wc_dev->pos = x;
-+ wc_dev->variety = d->name;
-+ for (y = 0; y < wc_dev->max_cards; y++) {
-+ wc_dev->flags[y] = d->flags;
-+ }
-+
-+ /* Keep track of whether we need to free the region */
-+ if (request_mem_region(wc_dev->mem_region, wc_dev->mem_len, "opvxa24xx")) {
-+ wc_dev->freeregion = 1;
-+ }
-+
-+ if(debug) {
-+ printk("======= find a card @ mem32 0x%x, size %ud\n", (unsigned int)wc_dev->mem32, (unsigned int)wc_dev->mem_len);
-+ }
-+#if 0
-+ printk("======= manual exit\n");
-+ if(wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ return -ENOMEM;
-+ }
-+#endif
-+
-+ wc_dev->fwversion = __opvx_a24xx_get_version(wc_dev->mem32);
-+ if(wc_dev->max_cards == 24)
-+ wc_dev->card_name = A2410P_Name;
-+ else if(wc_dev->max_cards == 16)
-+ wc_dev->card_name = A1610P_Name;
-+ else if(wc_dev->max_cards == 8)
-+ wc_dev->card_name = A810P_Name;
-+
-+ if(wc_dev->fwversion < ((1 << 16)|1) )
-+ ms_per_irq = 1;
-+
-+ if((ms_per_irq != 1)&&
-+ (ms_per_irq != 2)&&
-+ (ms_per_irq != 4)&&
-+ (ms_per_irq != 8)&&
-+ (ms_per_irq != 16))
-+ ms_per_irq = 1;
-+
-+ if(wc_dev->fwversion > ((1 << 16)|2)){
-+ if(!index)
-+ wc_dev->master = 1; //master card
-+ else
-+ wc_dev->master = 0;
-+ if(!irq_stub)
-+ wc_dev->master = 1;
-+ }else
-+ wc_dev->master = 0;
-+
-+ wc->index = index;
-+
-+ /* Allocate enough memory for two dahdi chunks, receive and transmit. Each sample uses
-+ 8 bits. */
-+ wc_dev->writechunk = pci_alloc_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, &wc_dev->writedma);
-+ if (!wc_dev->writechunk) {
-+ printk("opvxa24xx: Unable to allocate DMA-able memory\n");
-+ if (wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ }
-+ return -ENOMEM;
-+ }
-+
-+ if(debug) {
-+ printk("opvxa24xx: dma buffer allocated at 0x%x, pci(0x%x)\n", (unsigned int)wc_dev->writechunk, (unsigned int)wc_dev->writedma);
-+ }
-+
-+ __a24xx_malloc_chunk(wc_dev,ms_per_irq);
-+
-+ if (a24xx_init_spans(wc)) {
-+ printk(KERN_NOTICE "opvxa24xx: Unable to intialize hardware\n");
-+ /* Free Resources */
-+ if (wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ }
-+ pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
-+ return -ENOMEM;
-+ }
-+
-+ /* Enable bus mastering */
-+ pci_set_master(pdev);
-+
-+ /* Keep track of which device we are */
-+ pci_set_drvdata(pdev, wc);
-+
-+ /* kmalloc ec */
-+ for (x = 0; x < wc_dev->max_cards; x++) {
-+ if (!(wc->ec[x] = kmalloc(sizeof(*wc->ec[x]), GFP_KERNEL))) {
-+ free_wc(wc);
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ /* init hardware */
-+#if 0
-+ a24xx_hardware_init(wc_dev, span_flags);
-+
-+ __opvx_a24xx_setcreg(wc_dev->mem32, 0x4a0, 7, spi_cmd );
-+ int spi_cmd_from_fpga = __opvx_a24xx_getcreg(wc_dev->mem32, 0x4a0, 7);
-+ printk("%s:current spi_cmd is 0x%x\n", __FUNCTION__ , spi_cmd_from_fpga );
-+#endif
-+
-+ res = a24xx_hardware_init_all(wc_dev, span_flags);
-+ if (res < 0) {
-+ /* Free Resources */
-+ if (wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ }
-+ pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
-+ pci_set_drvdata(pdev, NULL);
-+ dahdi_unregister_device(wc->dev.ddev); //Dennis
-+ kfree(wc->dev.ddev->location);
-+ dahdi_free_device(wc->dev.ddev);
-+ free_wc(wc);
-+ return -EIO;
-+ }
-+ for (z = 0; z < wc_dev->max_cards/*MAX_NUM_CARDS*/; z++) {
-+ if (span_flags[z]) {
-+ wc->chans[z]->sigcap = __DAHDI_SIG_FXO | DAHDI_SIG_BROKEN;
-+ }
-+ }
-+
-+ /* init ec module */
-+ if (!wc_dev->vpm) {
-+ a24xx_vpm_init(wc);
-+ }
-+
-+ if(wc_dev->master || ( wc_dev->fwversion < ((1 << 16)|2) ) ){
-+ if (request_irq(pdev->irq, a24xx_interrupt, DAHDI_IRQ_SHARED, "opvxa24xx"/*wc_dev->card_name*/, wc)) {
-+ printk(KERN_NOTICE "Unable to request IRQ %d\n", pdev->irq);
-+ if (wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ }
-+ pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
-+ pci_set_drvdata(pdev, NULL);
-+ free_wc(wc);
-+ return -EIO;
-+ }
-+ }
-+
-+ if(0) { // for debug;
-+
-+ printk("exit after alloc irq\n");
-+ /* Free Resources */
-+ if(wc_dev->master || ( wc_dev->fwversion < ((1 << 16)|2) ))
-+ free_irq(pdev->irq, wc);
-+ if (wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ }
-+ pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
-+ pci_set_drvdata(pdev, NULL);
-+ dahdi_unregister_device(wc->dev.ddev); //Dennis
-+ kfree(wc->dev.ddev->location);
-+ dahdi_free_device(wc->dev.ddev);
-+ free_wc(wc);
-+ return -EIO;
-+ }
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+ for(x=0; x<wc_dev->max_cards; x++) {
-+ wc_dev->voc_buf[x] = kmalloc(voc_buffer_size, GFP_KERNEL);
-+ wc_dev->voc_ptr[x] = 0;
-+ }
-+#endif
-+ if(cidsupport) {
-+ int len = cidbuflen * DAHDI_MAX_CHUNKSIZE;
-+ if(debug) {
-+ printk("cid support enabled, length is %d msec\n", cidbuflen);
-+ }
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ wc_dev->cid_history_buf[x] = kmalloc(len, GFP_KERNEL);
-+ wc_dev->cid_history_ptr[x] = 0;
-+ wc_dev->cid_history_clone_cnt[x] = 0;
-+ wc_dev->cid_state[x] = CID_STATE_IDLE;
-+ }
-+ }
-+
-+ /* set channel sigcap */
-+ a24xx_post_initialize(wc);
-+
-+ init_busydetect(wc, opermode);
-+ init_callerid(wc);
-+
-+ /* Enable interrupts */
-+ __opvx_a24xx_enable_interrupts(wc_dev->mem32);
-+
-+ /* Initialize Write/Buffers to all blank data */
-+ memset((void *)wc_dev->writechunk,0, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2);
-+
-+ /*set irq frequence*/
-+ if(wc_dev->fwversion >= ((1 << 16)|1) )
-+ __opvx_a24xx_set_irq_frq(wc_dev->mem32,ms_per_irq);
-+
-+ if(wc_dev->fwversion > ((1 << 16)|2)){
-+ __opvx_a24xx_set_master(wc_dev->mem32,wc_dev->master^0x01);
-+ }
-+ /* Start DMA */
-+ __opvx_a24xx_start_dma(wc_dev->mem32, wc_dev->writedma);
-+
-+ /* module count */
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ if (wc_dev->cardflag & (1 << x)) {
-+ cardcount++;
-+ }
-+ }
-+ fwbuild = __opvx_a24xx_getcreg(wc_dev->mem32, 0x0, 0xe);
-+ printk(KERN_NOTICE "Found an OpenVox %s: Version %x.%x (%d modules),Build 0x%08x\n", wc_dev->card_name, wc_dev->fwversion>>16, wc_dev->fwversion&0xffff, cardcount,fwbuild );
-+ if(debug) {
-+ printk(KERN_DEBUG "OpenVox %s debug On\n", wc_dev->card_name);
-+ }
-+
-+ ifaces[index] = wc;
-+ max_iface_index++;
-+
-+ res = 0;
-+ }
-+
-+ return res;
-+}
-+
-+
-+static void a24xx_release(struct a24xx *wc)
-+{
-+#ifdef TEST_LOG_INCOME_VOICE
-+ struct file * f = NULL;
-+ mm_segment_t orig_fs;
-+ int i;
-+ char fname[20];
-+#endif
-+ int y;
-+ char *s;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ /*Unregister dahdi_span*/
-+ dahdi_unregister_device(wc_dev->ddev); //Dennis
-+ /* Release mem region and iounmap mem */
-+ if (wc_dev->freeregion) {
-+ release_mem_region(wc_dev->mem_region, wc_dev->mem_len);
-+ iounmap((void *)wc_dev->mem32);
-+ }
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+ for(i=0; i<wc_dev->max_cards; i++) {
-+ sprintf(fname, "//usr//%d.pcm", i);
-+ f = filp_open(fname, O_RDWR|O_CREAT, 00);
-+
-+ if (!f || !f->f_op || !f->f_op->read) {
-+ printk("WARNING: File (read) object is a null pointer!!!\n");
-+ continue;
-+ }
-+
-+ f->f_pos = 0;
-+
-+ orig_fs = get_fs();
-+ set_fs(KERNEL_DS);
-+
-+ if(wc_dev->voc_buf[i]) {
-+ f->f_op->write(f, wc_dev->voc_buf[i], voc_buffer_size, &f->f_pos);
-+ kfree(wc_dev->voc_buf[i]);
-+ }
-+
-+ set_fs(orig_fs);
-+ fput(f);
-+ }
-+#endif
-+
-+ /* Release cid history buffer */
-+ if(cidsupport) {
-+ int x;
-+ for (x = 0; x < wc_dev->max_cards/*MAX_NUM_CARDS*/; x++) {
-+ kfree(wc_dev->cid_history_buf[x]);
-+ }
-+ }
-+
-+ /* Release a24xx */
-+ s = wc_dev->card_name;
-+ for(y = 0; y < max_iface_index; y++)
-+ if(ifaces[y] == wc)
-+ break;
-+
-+
-+ kfree(wc_dev->ddev->location); //Dennis
-+ dahdi_free_device(wc_dev->ddev);
-+ free_wc(wc);
-+ ifaces[y]=NULL;
-+
-+ printk(KERN_INFO "Free an OpenVox %s card\n", s);
-+}
-+
-+static void __devexit a24xx_remove_one(struct pci_dev *pdev)
-+{
-+ struct a24xx *wc = pci_get_drvdata(pdev);
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ if (wc) {
-+ /* In case hardware is still there */
-+ __opvx_a24xx_disable_interrupts(wc_dev->mem32);
-+
-+ /* Wait some time to handle the last irq */
-+ __a24xx_wait_just_a_bit(HZ/10); /* delay 1/10 sec */
-+
-+ /* Stop any DMA */
-+ __opvx_a24xx_stop_dma(wc_dev->mem32);
-+
-+ /* Reset tdm controller */
-+ __opvx_a24xx_reset_tdm(wc_dev->mem32);
-+
-+ /* Release echo canceller */
-+ if (wc_dev->vpm_ec) {
-+ opvx_vpm_release(wc_dev->vpm_ec);
-+ }
-+ wc_dev->vpm_ec = NULL;
-+
-+ if(wc_dev->master || ( wc_dev->fwversion < ((1 << 16)|2) )){
-+ free_irq(pdev->irq, wc);
-+ }
-+ /* Immediately free resources */
-+ pci_free_consistent(pdev, ms_per_irq * DAHDI_MAX_CHUNKSIZE * MAX_NUM_CARDS * 2 * 2, (void *)wc_dev->writechunk, wc_dev->writedma);
-+
-+ destroy_callerid(wc);
-+ destroy_busydetect(wc);
-+
-+ /* Release span, possibly delayed */
-+ if (!wc_dev->usecount) {
-+ a24xx_release(wc);
-+ } else {
-+ wc_dev->dead = 1;
-+ }
-+ }
-+}
-+
-+static struct pci_device_id a24xx_pci_tbl[] = {
-+ { 0x1B74, 0x2410, 0x1B74, 0x0001, 0, 0, (unsigned long) &a2410a }, // Information for A2410 revsion A.
-+ { 0x1B74, 0x1610, 0x1B74, 0x0001, 0, 0, (unsigned long) &a1610a }, // Information for A1610 revsion A.
-+ { 0x1B74, 0x0810, 0x1B74, 0x0001, 0, 0, (unsigned long) &a810a }, // Information for A810 revsion A.
-+ { 0 }
-+};
-+
-+MODULE_DEVICE_TABLE(pci, a24xx_pci_tbl);
-+
-+static struct pci_driver a24xx_driver = {
-+ .name = "opvxa24xx",
-+ .probe = a24xx_init_one,
-+ .remove = __devexit_p(a24xx_remove_one),
-+ .suspend = NULL,
-+ .resume = NULL,
-+ .id_table = a24xx_pci_tbl,
-+};
-+
-+static int __init a24xx_init(void)
-+{
-+ int res;
-+ int x;
-+ for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) {
-+ if (!strcmp(fxo_modes[x].name, opermode)) {
-+ break;
-+ }
-+ }
-+ if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) {
-+ _opermode = x;
-+ } else {
-+ printk(KERN_NOTICE "Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode);
-+ for (x=0;x<sizeof(fxo_modes) / sizeof(fxo_modes[0]); x++) {
-+ printk(KERN_INFO " %s\n", fxo_modes[x].name);
-+ }
-+ printk(KERN_INFO "Note this option is CASE SENSITIVE!\n");
-+ return -ENODEV;
-+ }
-+ if (!strcmp(fxo_modes[_opermode].name, "AUSTRALIA")) {
-+ boostringer=1;
-+ fxshonormode=1;
-+ }
-+ /* for the voicedaa_check_hook defaults, if the user has not overridden
-+ them by specifying them as module parameters, then get the values
-+ from the selected operating mode
-+ */
-+ if (battdebounce == 0) {
-+ battdebounce = fxo_modes[_opermode].battdebounce;
-+ }
-+ if (battalarm == 0) {
-+ battalarm = fxo_modes[_opermode].battalarm;
-+ }
-+ if (battthresh == 0) {
-+ battthresh = fxo_modes[_opermode].battthresh;
-+ }
-+
-+ res = dahdi_pci_module(&a24xx_driver);
-+ if (res) {
-+ return -ENODEV;
-+ }
-+ return 0;
-+}
-+
-+static void __exit a24xx_cleanup(void)
-+{
-+ pci_unregister_driver(&a24xx_driver);
-+}
-+
-+module_param(spi_cmd, int, 0600);
-+module_param(debug, int, 0600);
-+module_param(ec_debug, int, 0600);
-+module_param(vpmsupport, int, 0600);
-+module_param(loopcurrent, int, 0600);
-+module_param(reversepolarity, int, 0600);
-+module_param(robust, int, 0600);
-+module_param(_opermode, int, 0600);
-+module_param(opermode, charp, 0600);
-+module_param(timingonly, int, 0600);
-+module_param(lowpower, int, 0600);
-+module_param(boostringer, int, 0600);
-+module_param(fastringer, int, 0600);
-+module_param(fxshonormode, int, 0600);
-+module_param(battdebounce, uint, 0600);
-+module_param(battalarm, uint, 0600);
-+module_param(battthresh, uint, 0600);
-+module_param(ringdebounce, int, 0600);
-+module_param(fwringdetect, int, 0600);
-+module_param(alawoverride, int, 0600);
-+module_param(fastpickup, int, 0600);
-+module_param(fxotxgain, int, 0600);
-+module_param(fxorxgain, int, 0600);
-+module_param(fxstxgain, int, 0600);
-+module_param(fxsrxgain, int, 0600);
-+module_param(cidsupport, int, 0600);
-+module_param(cidbuflen, int, 0600);
-+module_param(cidtimeout, int, 0600);
-+module_param(fxofullscale, int, 0600);
-+module_param(fixedtimepolarity, int, 0600);
-+module_param(ms_per_irq, int, 0600);
-+module_param(irq_stub, int, 0600);
-+
-+MODULE_DESCRIPTION("OpenVox A2410 Dahdi Driver");
-+MODULE_AUTHOR("MiaoLin <lin.miao@openvox.cn>");
-+MODULE_LICENSE("GPL v2");
-+
-+module_init(a24xx_init);
-+module_exit(a24xx_cleanup);
-+
diff --git a/dahdi-linux-2.10.1-openvox-2.patch b/dahdi-linux-2.10.1-openvox-2.patch
deleted file mode 100644
index 3be86e27c9a..00000000000
--- a/dahdi-linux-2.10.1-openvox-2.patch
+++ /dev/null
@@ -1,5851 +0,0 @@
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/base.h 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/base.h 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,321 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * $Id: base.h 360 2011-04-06 06:11:45Z yangshugang $
-+
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+
-+#ifndef _OPVXA2410P_H
-+#define _OPVXA2410P_H
-+
-+#include <dahdi/kernel.h>
-+#include <linux/firmware.h>
-+
-+#ifndef SLIC_LF_OPEN
-+/* Proslic Linefeed options for register 64 - Linefeed Control */
-+#define SLIC_LF_OPEN 0x0
-+#define SLIC_LF_ACTIVE_FWD 0x1
-+#define SLIC_LF_OHTRAN_FWD 0x2 /* Forward On Hook Transfer */
-+#define SLIC_LF_TIP_OPEN 0x3
-+#define SLIC_LF_RINGING 0x4
-+#define SLIC_LF_ACTIVE_REV 0x5
-+#define SLIC_LF_OHTRAN_REV 0x6 /* Reverse On Hook Transfer */
-+#define SLIC_LF_RING_OPEN 0x7
-+
-+#define SLIC_LF_SETMASK 0x7
-+#define SLIC_LF_OPPENDING 0x10
-+
-+/* Mask used to reverse the linefeed mode between forward and
-+ * reverse polarity. */
-+#define SLIC_LF_REVMASK 0x4
-+#endif
-+
-+struct ec;
-+
-+#define VPM_SUPPORT
-+
-+#define CARDS_PER_MODULE 4
-+#define MOD_TYPE_FXS 0
-+#define MOD_TYPE_FXO 1
-+
-+#define NUM_FXO_REGS 60
-+#define WC_MAX_IFACES 128
-+#define DEFAULT_RING_DEBOUNCE 64 /* Ringer Debounce (64 ms) */
-+
-+/* the constants below control the 'debounce' periods enforced by the
-+ check_hook routines; these routines are called once every 4 interrupts
-+ (the interrupt cycles around the four modules), so the periods are
-+ specified in _4 millisecond_ increments
-+*/
-+#define DEFAULT_BATT_DEBOUNCE 4 /* Battery debounce (64 ms) */
-+#define POLARITY_DEBOUNCE 64 /* Polarity debounce (64 ms) */
-+#define DEFAULT_BATT_THRESH 3 /* Anything under this is "no battery" */
-+
-+#define OHT_TIMER 6000 /* How long after RING to retain OHT */
-+
-+#define NEON_MWI_RNGY_PULSEWIDTH 0x3e8 /*=> period of 250 mS */
-+
-+#define FLAG_3215 (1 << 0)
-+
-+#define MAX_NUM_CARDS 24
-+
-+enum cid_hook_state {
-+ CID_STATE_IDLE = 0,
-+ CID_STATE_RING_DELAY,
-+ CID_STATE_RING_ON,
-+ CID_STATE_RING_OFF,
-+ CID_STATE_WAIT_RING_FINISH
-+};
-+
-+/* if you want to record the last 8 sec voice before the driver unload, uncomment it and rebuild. */
-+/* #define TEST_LOG_INCOME_VOICE */
-+#define voc_buffer_size (8000*8)
-+#define MAX_ALARMS 10
-+#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */
-+#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */
-+#define PEGCOUNT 5 /* 5 cycles of pegging means RING */
-+
-+#define NUM_CAL_REGS 12
-+
-+
-+#define __CMD_RD (1 << 20) /* Read Operation */
-+#define __CMD_WR (1 << 21) /* Write Operation */
-+#define __CMD_FIN (1 << 22) /* Has finished receive */
-+#define __CMD_TX (1 << 23) /* Has been transmitted */
-+
-+#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR)
-+#define CMD_RD(a) (((a) << 8) | __CMD_RD)
-+
-+
-+struct calregs {
-+ unsigned char vals[NUM_CAL_REGS];
-+};
-+
-+enum proslic_power_warn {
-+ PROSLIC_POWER_UNKNOWN = 0,
-+ PROSLIC_POWER_ON,
-+ PROSLIC_POWER_WARNED,
-+};
-+
-+enum battery_state {
-+ BATTERY_UNKNOWN = 0,
-+ BATTERY_PRESENT,
-+ BATTERY_LOST,
-+};
-+
-+struct a24xx_dev {
-+ struct pci_dev *dev;
-+ char *variety;
-+ struct dahdi_device *ddev;
-+ unsigned char ios;
-+ int usecount;
-+ unsigned int intcount;
-+ int dead;
-+ int pos;
-+ int flags[MAX_NUM_CARDS];
-+ int freeregion;
-+ int alt;
-+ int curcard;
-+ int cardflag; /* Bit-map of present cards */
-+ enum proslic_power_warn proslic_power;
-+ spinlock_t lock;
-+
-+ union {
-+ struct fxo {
-+#ifdef AUDIO_RINGCHECK
-+ unsigned int pegtimer;
-+ int pegcount;
-+ int peg;
-+ int ring;
-+#else
-+ int wasringing;
-+ int lastrdtx;
-+#endif
-+ int ringdebounce;
-+ int offhook;
-+ unsigned int battdebounce;
-+ unsigned int battalarm;
-+ enum battery_state battery;
-+ int lastpol;
-+ int polarity;
-+ int polaritydebounce;
-+ } fxo;
-+ struct fxs {
-+ int oldrxhook;
-+ int debouncehook;
-+ int lastrxhook;
-+ int debounce;
-+ int ohttimer;
-+ int idletxhookstate; /* IDLE changing hook state */
-+ int lasttxhook;
-+ int palarms;
-+ struct calregs calregs;
-+ struct dahdi_vmwi_info vmwisetting;
-+ int vmwi_active_messages;
-+ u32 vmwi_lrev:1; /*MWI Line Reversal*/
-+ u32 vmwi_hvdc:1; /*MWI High Voltage DC Idle line*/
-+ u32 vmwi_hvac:1; /*MWI Neon High Voltage AC Idle line*/
-+ u32 neonringing:1;/*Ring Generator is set for NEON*/
-+ int reversepolarity; /* polarity reversal */
-+ spinlock_t lasttxhooklock;
-+ } fxs;
-+ } mod[MAX_NUM_CARDS];
-+
-+ /* Receive hook state and debouncing */
-+ int modtype[MAX_NUM_CARDS];
-+ unsigned char reg0shadow[MAX_NUM_CARDS];
-+ unsigned char reg1shadow[MAX_NUM_CARDS];
-+
-+ unsigned long mem_region; /* 32 bit Region allocated to tiger320 */
-+ unsigned long mem_len; /* Length of 32 bit region */
-+ volatile unsigned long mem32; /* Virtual representation of 32 bit memory area */
-+
-+ dma_addr_t readdma;
-+ dma_addr_t writedma;
-+ volatile unsigned char *writechunk; /* Double-word aligned write memory */
-+ volatile unsigned char *readchunk; /* Double-word aligned read memory */
-+
-+#ifdef TEST_LOG_INCOME_VOICE
-+ char * voc_buf[MAX_NUM_CARDS];
-+ int voc_ptr[MAX_NUM_CARDS];
-+#endif
-+ unsigned short ledstate;
-+ unsigned int fwversion;
-+ int max_cards;
-+ char *card_name;
-+ unsigned int master;
-+
-+ char *cid_history_buf[MAX_NUM_CARDS];
-+ int cid_history_ptr[MAX_NUM_CARDS];
-+ int cid_history_clone_cnt[MAX_NUM_CARDS];
-+ enum cid_hook_state cid_state[MAX_NUM_CARDS];
-+ int cid_ring_on_time[MAX_NUM_CARDS];
-+
-+#ifdef VPM_SUPPORT
-+ struct ec *vpm_ec;
-+ int vpm;
-+
-+ unsigned long dtmfactive;
-+ unsigned long dtmfmask;
-+ unsigned long dtmfmutemask;
-+
-+#endif
-+
-+};
-+
-+struct a24xx_desc {
-+ char *name;
-+ int flags;
-+};
-+
-+struct a24xx {
-+ struct a24xx_dev dev;
-+ struct dahdi_span span;
-+ struct dahdi_chan _chans[MAX_NUM_CARDS];
-+ struct dahdi_chan *chans[MAX_NUM_CARDS];
-+ struct dahdi_echocan_state *ec[32]; /* Echcan state for each channel */
-+ unsigned int index;
-+};
-+
-+/*
-+ * from bin
-+ */
-+extern void __opvx_a24xx_setcreg(unsigned long mem32, unsigned int offset, unsigned int reg, unsigned int val);
-+extern unsigned int __opvx_a24xx_getcreg(unsigned long mem32, unsigned int offset, unsigned char reg);
-+extern unsigned char __opvx_a24xx_read_8bits(unsigned long mem32);
-+
-+extern void __opvx_a24xx_reset_modules(unsigned long mem32, void (*func)(int), int data);
-+extern void __opvx_a24xx_reset_modules_v2(unsigned long mem32, void (*func)(int), int data);
-+extern void __opvx_a24xx_setcard(unsigned long mem32, int card);
-+extern void __opvx_a24xx_reset_spi(void *wc_dev, int card, void (*func)(void*, int));
-+extern void __opvx_a24xx_write_8bits(unsigned long mem32, unsigned char bits);
-+
-+extern void __opvx_a24xx_set_master(unsigned long mem32,unsigned int master);
-+extern unsigned int __opvx_a24xx_get_master(unsigned long mem32);
-+extern void __opvx_a24xx_set_irq_frq(unsigned long mem32,unsigned int frq);
-+extern unsigned int __opvx_a24xx_get_version(unsigned long mem32);
-+extern unsigned int __opvx_a24xx_get_irqstatus(unsigned long mem32);
-+extern void __opvx_a24xx_set_irqstatus(unsigned long mem32, unsigned int value);
-+extern void __opvx_a24xx_clear_irqs(unsigned long mem32);
-+extern void __opvx_a24xx_enable_interrupts(unsigned long mem32);
-+extern void __opvx_a24xx_disable_interrupts(unsigned long mem32);
-+extern unsigned int __opvx_a24xx_get_irqcnt_lo(unsigned long mem32);
-+
-+extern void __opvx_a24xx_restart_dma(unsigned long mem32);
-+extern void __opvx_a24xx_start_dma(unsigned long mem32, unsigned int data);
-+extern void __opvx_a24xx_stop_dma(unsigned long mem32);
-+extern void __opvx_a24xx_reset_tdm(unsigned long mem32);
-+
-+extern void __opvx_a24xx_spi_setreg(void *wc_dev, unsigned long mem32, int card, int modtype, unsigned char reg, unsigned char value, void (*func)(void*, int));
-+extern unsigned char __opvx_a24xx_spi_getreg(void *wc_dev, unsigned long mem32, int card, int modtype, unsigned char reg, void (*func)(void*, int));
-+
-+extern unsigned int __opvx_a24xx_oct_in(unsigned long mem32, unsigned int addr);
-+extern unsigned int __opvx_a24xx_oct_in_v2(unsigned long mem32, unsigned int addr);
-+extern void __opvx_a24xx_oct_out(unsigned long mem32, unsigned int addr, unsigned int value);
-+extern void __opvx_a24xx_oct_out_v2(unsigned long mem32, unsigned int addr, unsigned int value);
-+extern int __opvx_a24xx_check_vpm(unsigned long mem32);
-+extern int __opvx_a24xx_check_vpm_v2(unsigned long mem32);
-+extern void __opvx_a24xx_vpm_setpresent(unsigned long mem32);
-+extern void __opvx_a24xx_vpm_setpresent_v2(unsigned long mem32);
-+
-+extern void __opvx_a24xx_transmit(unsigned long mem32, volatile unsigned char *writechunk, volatile unsigned char **txbuf,unsigned int irq_frq , unsigned int order);
-+extern void __opvx_a24xx_receive(unsigned long mem32, volatile unsigned char *readchunk, volatile unsigned char **rxbuf,unsigned int irq_frq , unsigned int order);
-+
-+extern void __opvx_a24xx_set_chunk(void *readchunk, void *writechunk,unsigned int frq);
-+
-+/*
-+ * from a24xx.c
-+ */
-+extern void __a24xx_wait_just_a_bit(int foo);
-+extern void __a24xx_spi_setreg(struct a24xx_dev *wc_dev, int card, unsigned char reg, unsigned char value);
-+extern unsigned char __a24xx_spi_getreg(struct a24xx_dev *wc_dev, int card, unsigned char reg);
-+extern void a24xx_spi_setreg(struct a24xx_dev *wc_dev, int card, unsigned char reg, unsigned char value);
-+extern unsigned char a24xx_spi_getreg(struct a24xx_dev *wc_dev, int card, unsigned char reg);
-+extern void a24xx_reset_spi(struct a24xx_dev *wc_dev, int card);
-+extern void __a24xx_setcard(void *wc_dev, int card);
-+extern void oct_set_reg(void *data, unsigned int reg, unsigned int val);
-+extern unsigned int oct_get_reg(void *data, unsigned int reg);
-+extern void __a24xx_vpm_setpresent(struct a24xx_dev *wc_dev);
-+extern int __a24xx_proslic_setreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address, unsigned short data);
-+extern int __a24xx_proslic_getreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address);
-+extern int __a24xx_malloc_chunk(struct a24xx_dev *wc_dev,unsigned int frq);
-+
-+/*
-+ * from si321x.c
-+ */
-+extern int si321x_init_ring_generator_mode(struct a24xx_dev *wc_dev, int card);
-+extern int si321x_set_ring_generator_mode(struct a24xx_dev *wc_dev, int card, int mode);
-+extern int si321x_init_proslic(struct a24xx_dev *wc_dev, int card, int fast, int manual, int sane);
-+extern int si321x_init_proslic_all(struct a24xx_dev *wc_dev, int fxs_flag,int fast, int manual, int sane,int *blk_flag);
-+extern int si321x_proslic_setreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address, unsigned short data);
-+extern int si321x_proslic_getreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address);
-+extern void si321x_proslic_recheck_sanity(struct a24xx_dev *wc_dev, int card);
-+
-+/*
-+ * from si3050.c
-+ */
-+int si3050_set_hwgain(struct a24xx_dev *wc_dev, int card, __s32 gain, __u32 tx);
-+int si3050_init_voicedaa(struct a24xx_dev *wc_dev, int card, int fast, int manual, int sane);
-+
-+#endif
-+
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/busydetect.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/busydetect.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,876 @@
-+/*
-+ * OpenVox FXO Detect Busy Voice Driver for DAHDI Telephony interface
-+ *
-+ * Written by kevin.chen
-+
-+ * Copyright (C) 2012-2013 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+/* Rev history
-+ *
-+ * Rev 0.10 remove structure country_busytone
-+ * add GEN_BUSYTONE_ONTIME and GEN_BUSYTONE_OFFTIME
-+ * Rev 0.20 fix bug
-+ * after frequency is set to a valid value, cannot reset the zero value
-+ * Rev 0.30 support new kernel version 3.10.0
-+ *
-+ */
-+
-+#include <linux/proc_fs.h>
-+#include "busydetect.h"
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-+#include <linux/seq_file.h>
-+#endif
-+
-+static const char *module_name = "opvxdsp";
-+static int ref_count = 0;
-+
-+#define MAX_TONE_NUM 3
-+#define TONE_FREQ_NUM 2
-+
-+#define GEN_BUSYTONE_ONTIME 500
-+#define GEN_BUSYTONE_OFFTIME 500
-+
-+#define TONE_THRESHOLD 20548
-+#define SILENT_THRESHOLD 2560
-+#define ENERGY_SCALE (FRAME_SHORT_SIZE >> 1)
-+
-+struct freq_state {
-+ int freq;
-+ /* Calculate the sampling data*/
-+ short prev2;
-+ short prev;
-+ short fac;
-+};
-+
-+struct tone {
-+ int busycount;
-+ int threshold;
-+ int ontime;
-+ int offtime;
-+ struct freq_state fs[TONE_FREQ_NUM];
-+ struct proc_dir_entry *subentry;
-+};
-+
-+struct silent_detect {
-+ int detect_tx;
-+ int detect_rx;
-+ /* Mute timeout */
-+ int length;
-+ int threshold;
-+ struct proc_dir_entry *subentry;
-+
-+ /* Statistics mute sample */
-+ u32 tx_samples;
-+ u32 rx_samples;
-+};
-+
-+struct param {
-+ struct tone tone[MAX_TONE_NUM];
-+ struct silent_detect sd;
-+};
-+
-+struct detect_state {
-+ int index;
-+ u32 length;
-+};
-+
-+struct dsp_info {
-+ /* The read data cache */
-+ short rdata[FRAME_SHORT_SIZE];
-+ int rlen;
-+ /* The write data cache */
-+ short wdata[FRAME_SHORT_SIZE];
-+ int wlen;
-+
-+ struct param param;
-+ struct proc_dir_entry *entry;
-+
-+ u32 energy;
-+ int count;
-+ int detected_tone;
-+ struct detect_state state[3];
-+
-+ /* The busy tone appear */
-+ int appear_busy;
-+
-+ /* Calculate parameters for generate waveform */
-+ /* Read and write two direction */
-+ int phase[2][TONE_FREQ_NUM];
-+ int is_offtime[2];
-+ int offset[2];
-+};
-+
-+struct detect_info {
-+ struct dsp_info dsp[TOTAL_CARDS];
-+
-+ /* Variable for generater waveform */
-+ u32 phase_rate[TONE_FREQ_NUM];
-+ short gain[TONE_FREQ_NUM];
-+ int ontime;
-+ int offtime;
-+};
-+
-+static struct detect_info *di = NULL;
-+
-+static DECLARE_BITMAP(fxo_cardflag, TOTAL_CARDS);
-+static DECLARE_BITMAP(fxs_cardflag, TOTAL_CARDS);
-+
-+static struct proc_dir_entry *opvxdsp_entry;
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Kevin.chen");
-+MODULE_DESCRIPTION("DAHDI detect busy voice");
-+
-+static int detect_is_close(int channo)
-+{
-+ int i;
-+ struct param *param = &di->dsp[channo - 1].param;
-+
-+ for (i = 0; i < MAX_TONE_NUM; i++) {
-+ if (param->tone[i].busycount > 0) {
-+ return 0;
-+ }
-+ }
-+
-+ if (param->sd.length > 0 && (param->sd.detect_tx || param->sd.detect_rx)) {
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+static void reset_dsp_detect_param(struct dsp_info *dsp)
-+{
-+ int i;
-+
-+ dsp->param.sd.tx_samples = 0;
-+ dsp->param.sd.rx_samples = 0;
-+
-+ dsp->detected_tone = -1;
-+ dsp->count = 0;
-+ for (i = 0; i < 3; i++) {
-+ dsp->state[i].index = -1;
-+ dsp->state[i].length = 0;
-+ }
-+}
-+
-+static void reset_dsp_generate_param(struct dsp_info *dsp)
-+{
-+ int i, j;
-+
-+ if (dsp->appear_busy) {
-+ dsp->appear_busy = 0;
-+
-+ for (i = 0; i < 2; i++) {
-+ dsp->is_offtime[i] = 0;
-+ dsp->offset[i] = 0;
-+ for (j = 0; j < TONE_FREQ_NUM; j++) {
-+ dsp->phase[i][j] = 0;
-+ }
-+ }
-+ }
-+}
-+
-+static void update_detect(struct dsp_info *dsp, short s)
-+{
-+ int i, j;
-+ short tmp;
-+ struct freq_state *fs;
-+
-+ for (i = 0; i < MAX_TONE_NUM; i++) {
-+ if (dsp->param.tone[i].busycount <= 0) {
-+ continue;
-+ }
-+
-+ for (j = 0; j < TONE_FREQ_NUM; j++) {
-+ fs = &dsp->param.tone[i].fs[j];
-+ tmp = fs->prev2;
-+ fs->prev2 = fs->prev;
-+ fs->prev = (((int)fs->fac * fs->prev2) >> 14) - tmp + (s >> 7);
-+ }
-+ }
-+}
-+
-+static u32 detect_result(struct freq_state *fs)
-+{
-+ u32 val;
-+
-+ val = fs->prev * fs->prev + fs->prev2 * fs->prev2 - ((fs->fac * fs->prev) >> 14) * fs->prev2;
-+ /* Reset */
-+ fs->prev = fs->prev2 = 0;
-+
-+ return val;
-+}
-+
-+static int busy_detect(struct dsp_info *dsp, int len)
-+{
-+ int i, j;
-+ u32 power, max_power = 0;
-+ int index = -1;
-+
-+ for (i = 0; i < MAX_TONE_NUM; i++) {
-+ power = 0;
-+ for (j = 0; j < TONE_FREQ_NUM; j++) {
-+ power += detect_result(&dsp->param.tone[i].fs[j]);
-+ }
-+
-+ if (dsp->param.tone[i].busycount > 0 &&
-+ dsp->energy > dsp->param.tone[i].threshold &&
-+ power > ENERGY_SCALE * dsp->energy) {
-+ if (power > max_power) {
-+ max_power = power;
-+ index = i;
-+ }
-+ }
-+ }
-+
-+ if (index != -1 && dsp->detected_tone != index) {
-+ dsp->detected_tone = index;
-+ dsp->count = 0;
-+ for (i = 0; i < 3; i++) {
-+ dsp->state[i].index = -1;
-+ dsp->state[i].length = 0;
-+ }
-+ }
-+
-+ if (dsp->state[2].index != index) {
-+ dsp->state[2].index = index;
-+ dsp->state[1].length += len;
-+ } else {
-+ if (dsp->state[1].index != index) {
-+ if (dsp->detected_tone >= 0) {
-+ if (dsp->state[0].index == dsp->detected_tone && dsp->state[1].index == -1) {
-+ if ((dsp->state[0].length >= dsp->param.tone[dsp->detected_tone].ontime * 8 - FRAME_SHORT_SIZE * 2) && \
-+ (dsp->state[0].length <= dsp->param.tone[dsp->detected_tone].ontime * 8 + FRAME_SHORT_SIZE * 2) && \
-+ (dsp->state[1].length >= dsp->param.tone[dsp->detected_tone].offtime * 8 - FRAME_SHORT_SIZE * 2)) {
-+ dsp->count++;
-+ if (dsp->count >= dsp->param.tone[dsp->detected_tone].busycount) {
-+ return 1;
-+ }
-+ }
-+ }
-+ }
-+ memmove(&dsp->state[0], &dsp->state[1], 2 * sizeof(dsp->state[0]));
-+ dsp->state[1].index = index;
-+ dsp->state[1].length = len;
-+ } else {
-+ dsp->state[1].length += len;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int silent_detect(struct dsp_info *dsp, int len, int is_write)
-+{
-+ int res = 0;
-+
-+ if (dsp->param.sd.length <= 0) {
-+ return res;
-+ }
-+
-+ if (dsp->energy < dsp->param.sd.threshold) {
-+ if (is_write) {
-+ dsp->param.sd.tx_samples += len;
-+ if (dsp->param.sd.tx_samples >= dsp->param.sd.length * SAMPLE_PER_SEC) {
-+ res = 1;
-+ }
-+ } else {
-+ dsp->param.sd.rx_samples += len;
-+ if (dsp->param.sd.rx_samples >= dsp->param.sd.length * SAMPLE_PER_SEC) {
-+ res = 1;
-+ }
-+ }
-+ } else {
-+ dsp->param.sd.tx_samples = 0;
-+ dsp->param.sd.rx_samples = 0;
-+ }
-+
-+ return res;
-+}
-+
-+static short calc_amp(u32 *acc, u32 rate, short scale)
-+{
-+ u32 phase, step;
-+ short amp;
-+
-+ phase = *acc;
-+ phase >>= 23;
-+ step = phase & (SIN_DIVISION - 1);
-+ if ((phase & SIN_DIVISION)) {
-+ step = SIN_DIVISION - step;
-+ }
-+
-+ amp = sin_table[step];
-+ if ((phase & (2 * SIN_DIVISION))) {
-+ amp = -amp;
-+ }
-+
-+ *acc += rate;
-+ return (short)(((u32)amp * scale) >> 15);
-+}
-+
-+static short generater_amp(struct dsp_info *dsp, int is_write)
-+{
-+ int i;
-+ short amp = 0;
-+ int index = (is_write == 0) ? 0 : 1;
-+
-+ dsp->offset[index]++;
-+ if (!dsp->is_offtime[index]) {
-+ for (i = 0; i < TONE_FREQ_NUM; i++) {
-+ if (di->phase_rate[i] > 0) {
-+ amp += calc_amp(&dsp->phase[index][i], di->phase_rate[i], di->gain[i]);
-+ }
-+ }
-+ if (dsp->offset[index] >= di->ontime * 8) {
-+ dsp->offset[index] = 0;
-+ dsp->is_offtime[index] = 1;
-+ }
-+ } else {
-+ if (dsp->offset[index] >= di->offtime * 8) {
-+ dsp->offset[index] = 0;
-+ dsp->is_offtime[index] = 0;
-+ }
-+ }
-+
-+ return amp;
-+}
-+
-+static void analysis_dsp(struct dsp_info *dsp, short s[], int len, int is_write)
-+{
-+ int i, res = 0;
-+ u16 temp;
-+
-+ for (i = 0; i < len; i++) {
-+ temp = (s[i] < 0 ? -s[i] : s[i]) >> 7;
-+ dsp->energy += temp * temp;
-+ if (!is_write) {
-+ update_detect(dsp, s[i]);
-+ }
-+ }
-+
-+ if (is_write) {
-+
-+ if (dsp->param.sd.detect_tx) {
-+ res = silent_detect(dsp, len, 1);
-+ }
-+ } else {
-+ res = busy_detect(dsp, len);
-+
-+ /* Read only support the silent detect */
-+ if (!res && dsp->param.sd.detect_rx) {
-+ res = silent_detect(dsp, len, 0);
-+ }
-+ }
-+
-+ dsp->energy = 0;
-+
-+ if (res) {
-+ dsp->appear_busy = 1;
-+ reset_dsp_detect_param(dsp);
-+ }
-+}
-+
-+void parser_busy_silent_process(struct a24xx *wc, int is_write)
-+{
-+ int i, j;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ struct dahdi_chan *chan;
-+ struct dsp_info *dsp;
-+
-+ if (!di) {
-+ /* Initialize this module failed */
-+ return;
-+ }
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ chan = wc->chans[i];
-+ dsp = &di->dsp[chan->channo - 1];
-+ if (chan->channo > TOTAL_CARDS) {
-+ continue;
-+ }
-+ if ((wc_dev->modtype[i] != MOD_TYPE_FXO) ||
-+ (wc_dev->modtype[i] == MOD_TYPE_FXO && !wc_dev->mod[i].fxo.offhook)) {
-+ reset_dsp_generate_param(dsp);
-+ continue;
-+ }
-+
-+ if (detect_is_close(chan->channo)) {
-+ /* The busy tone and silence detection has been closed */
-+ continue;
-+ }
-+
-+ if (is_write) {
-+ if (dsp->appear_busy) {
-+ for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-+ chan->writechunk[j] = DAHDI_LIN2X(generater_amp(dsp, 1), chan);
-+ }
-+ } else {
-+ for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-+ dsp->wdata[dsp->wlen++] = DAHDI_XLAW(chan->writechunk[j], chan);
-+ }
-+ if (dsp->wlen == FRAME_SHORT_SIZE) {
-+ dsp->wlen = 0;
-+ analysis_dsp(dsp, dsp->wdata, FRAME_SHORT_SIZE, 1);
-+ }
-+ }
-+ } else {
-+ if (dsp->appear_busy) {
-+ for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-+ chan->readchunk[j] = DAHDI_LIN2X(generater_amp(dsp, 0), chan);
-+ }
-+ } else {
-+ for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-+ dsp->rdata[dsp->rlen++] = DAHDI_XLAW(chan->readchunk[j], chan);
-+ }
-+ if (dsp->rlen == FRAME_SHORT_SIZE) {
-+ dsp->rlen = 0;
-+ analysis_dsp(dsp, dsp->rdata, FRAME_SHORT_SIZE, 0);
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+static short get_fac(int freq)
-+{
-+ if (freq < MIN_INDEX_FREQ) {
-+ freq = MIN_INDEX_FREQ;
-+ } else if (freq > MAX_INDEX_FREQ) {
-+ freq = MAX_INDEX_FREQ;
-+ }
-+
-+ return fac_table[(freq - MIN_INDEX_FREQ) / STEP_FREQ];
-+}
-+
-+static u32 get_phase_rate(int freq)
-+{
-+ return (freq * 65536 / SAMPLE_PER_SEC) * 65536;
-+}
-+
-+static short get_gain(int level)
-+{
-+ if (level < MIN_INDEX_LEVEL) {
-+ level = MIN_INDEX_LEVEL;
-+ } else if (level > MAX_INDEX_LEVEL) {
-+ level = MAX_INDEX_LEVEL;
-+ }
-+
-+ return gain_table[(level - MIN_INDEX_LEVEL) / STEP_LEVEL];
-+}
-+
-+static void config_proc_param(struct param *param)
-+{
-+ int i, j;
-+
-+ for (i = 0; i < MAX_TONE_NUM; i++) {
-+ param->tone[i].busycount = 0;
-+ param->tone[i].threshold = TONE_THRESHOLD;
-+ param->tone[i].ontime = 0;
-+ param->tone[i].offtime = 0;
-+ for (j = 0; j < TONE_FREQ_NUM; j++) {
-+ param->tone[i].fs[j].freq = 0;
-+ param->tone[i].fs[j].fac = 0;
-+ }
-+ }
-+ param->sd.detect_tx = 0;
-+ param->sd.detect_rx = 0;
-+ param->sd.length = 30;
-+ param->sd.threshold = SILENT_THRESHOLD;
-+}
-+
-+static void init_detect_info(struct detect_info *di, const char *opermode)
-+{
-+ int i, j;
-+
-+ di->ontime = GEN_BUSYTONE_ONTIME;
-+ di->offtime = GEN_BUSYTONE_OFFTIME;
-+ di->phase_rate[0] = get_phase_rate(450);
-+ di->gain[0] = get_gain(-12);
-+
-+ /* Set default parameters */
-+ for (i = 0; i < TOTAL_CARDS; i++) {
-+ config_proc_param(&di->dsp[i].param);
-+
-+ di->dsp[i].detected_tone = -1;
-+ for (j = 0; j < 3; j++) {
-+ di->dsp[i].state[j].index = -1;
-+ }
-+ }
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int write_param_proc(struct file *filp, const char __user *buf,
-+ unsigned long count, void *data)
-+#else
-+static ssize_t write_param_proc(struct file *file, const char __user *buf,
-+ size_t count, loff_t *pos)
-+#endif
-+{
-+ char temp[24];
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+ int *param = (int *)data;
-+#else
-+ int *param = PDE_DATA(file_inode(file));
-+#endif
-+ int value;
-+ int len;
-+
-+ len = count > (sizeof(temp) - 1) ? (sizeof(temp) - 1) : count;
-+
-+ if (copy_from_user(temp, buf, len)) {
-+ return -EFAULT;
-+ }
-+
-+ temp[len] = '\0';
-+
-+ value = simple_strtoul(temp, NULL, 10);
-+ if (value >= 0) {
-+ *param = value;
-+ }
-+
-+ return count;
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int read_param_proc(char *buf, char **start, off_t off, int count,
-+ int *eof, void *data)
-+{
-+ int res;
-+ int *param = (int *)data;
-+
-+ if (off > 0) {
-+ /* We have finished to read, return 0 */
-+ res = 0;
-+ } else {
-+ res = sprintf(buf, "%d", *param);
-+ }
-+
-+ return res;
-+}
-+
-+static void create_param_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ struct proc_dir_entry *entry;
-+
-+ entry = create_proc_entry(name, 0644, base);
-+ if (entry) {
-+ entry->data = data;
-+ entry->read_proc = read_param_proc;
-+ entry->write_proc = write_param_proc;
-+ }
-+}
-+#else
-+static int param_proc_show(struct seq_file *m, void *v)
-+{
-+ int *param = (int *)m->private;
-+
-+ seq_printf(m, "%d", *param);
-+ return 0;
-+}
-+
-+static int open_param_proc(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, param_proc_show, PDE_DATA(inode));
-+}
-+
-+static struct file_operations proc_param_fops = {
-+ .open = open_param_proc,
-+ .read = seq_read,
-+ .write = write_param_proc,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static void create_param_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ proc_create_data(name, 0644, base, &proc_param_fops, data);
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int write_param_freq_proc(struct file *filp, const char __user *buf,
-+ unsigned long count, void *data)
-+#else
-+static ssize_t write_param_freq_proc(struct file *file, const char __user *buf,
-+ size_t count, loff_t *pos)
-+#endif
-+{
-+ char temp[24];
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+ struct freq_state *fs = (struct freq_state *)data;
-+#else
-+ struct freq_state *fs = PDE_DATA(file_inode(file));
-+#endif
-+ int value;
-+ int len;
-+
-+ len = count > (sizeof(temp) - 1) ? (sizeof(temp) - 1) : count;
-+
-+ if (copy_from_user(temp, buf, len)) {
-+ return -EFAULT;
-+ }
-+
-+ temp[len] = '\0';
-+
-+ value = simple_strtoul(temp, NULL, 10);
-+ if (!value || (value >= MIN_INDEX_FREQ && value <= MAX_INDEX_FREQ)) {
-+ fs->freq = value;
-+ if (fs->freq) {
-+ fs->fac = get_fac(fs->freq);
-+ } else {
-+ fs->fac = 0;
-+ }
-+ }
-+
-+ return count;
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int read_param_freq_proc(char *buf, char **start, off_t off, int count,
-+ int *eof, void *data)
-+{
-+ int res;
-+ struct freq_state *fs = (struct freq_state *)data;
-+
-+ if (off > 0) {
-+ /* We have finished to read, return 0 */
-+ res = 0;
-+ } else {
-+ res = sprintf(buf, "%d", fs->freq);
-+ }
-+
-+ return res;
-+}
-+
-+static void create_param_freq_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ struct proc_dir_entry *entry;
-+
-+ entry = create_proc_entry(name, 0644, base);
-+ if (entry) {
-+ entry->data = data;
-+ entry->read_proc = read_param_freq_proc;
-+ entry->write_proc = write_param_freq_proc;
-+ }
-+}
-+#else
-+static int param_freq_proc_show(struct seq_file *m, void *v)
-+{
-+ struct freq_state *fs = (struct freq_state *)m->private;
-+
-+ seq_printf(m, "%d", fs->freq);
-+ return 0;
-+}
-+
-+static int open_param_freq_proc(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, param_freq_proc_show, PDE_DATA(inode));
-+}
-+
-+static struct file_operations proc_param_freq_fops = {
-+ .open = open_param_freq_proc,
-+ .read = seq_read,
-+ .write = write_param_freq_proc,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static void create_param_freq_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ proc_create_data(name, 0644, base, &proc_param_freq_fops, data);
-+}
-+#endif
-+
-+/*
-+ * \brief parameter
-+ * flag: DECLARE_BITMAP structure definition, TOTAL_CARDS length
-+ * is_clean: 0 is to create, 1 is to remove
-+ */
-+static void rebuild_recur_proc(unsigned long *flag, int is_clean)
-+{
-+ int i, j, k;
-+ char temp[24];
-+ struct param *param;
-+ struct proc_dir_entry *entry, *subentry;
-+
-+ if (!opvxdsp_entry) {
-+ return;
-+ }
-+
-+ if (is_clean) {
-+ for (i = 0; i < TOTAL_CARDS; i++) {
-+ if (test_bit(i, flag)) {
-+ entry = di->dsp[i].entry;
-+ if (entry) {
-+ param = &di->dsp[i].param;
-+ for (j = 0; j < MAX_TONE_NUM; j++) {
-+ subentry = param->tone[j].subentry;
-+ if (subentry) {
-+ remove_proc_entry("busycount", subentry);
-+ remove_proc_entry("threshold", subentry);
-+ remove_proc_entry("ontime", subentry);
-+ remove_proc_entry("offtime", subentry);
-+ for (k = 0; k < TONE_FREQ_NUM; k++) {
-+ sprintf(temp, "frequency%d", k + 1);
-+ remove_proc_entry(temp, subentry);
-+ }
-+
-+ sprintf(temp, "tone%d", j + 1);
-+ remove_proc_entry(temp, entry);
-+ }
-+ }
-+ subentry = param->sd.subentry;
-+ if (subentry) {
-+ remove_proc_entry("detect_tx", subentry);
-+ remove_proc_entry("detect_rx", subentry);
-+ remove_proc_entry("length", subentry);
-+ remove_proc_entry("threshold", subentry);
-+ remove_proc_entry("silent_detect", entry);
-+ }
-+
-+ sprintf(temp, "%d", i + 1);
-+ remove_proc_entry(temp, opvxdsp_entry);
-+ }
-+ }
-+ }
-+ } else {
-+ for (i = 0; i < TOTAL_CARDS; i++) {
-+ if (test_bit(i, flag)) {
-+ sprintf(temp, "%d", i + 1);
-+ entry = proc_mkdir(temp, opvxdsp_entry);
-+ di->dsp[i].entry = entry;
-+ if (entry) {
-+ param = &di->dsp[i].param;
-+ for (j = 0; j < MAX_TONE_NUM; j++) {
-+ sprintf(temp, "tone%d", j + 1);
-+ subentry = proc_mkdir(temp, entry);
-+ param->tone[j].subentry = subentry;
-+ if (subentry) {
-+ create_param_proc("busycount", subentry, &param->tone[j].busycount);
-+ create_param_proc("threshold", subentry, &param->tone[j].threshold);
-+ create_param_proc("ontime", subentry, &param->tone[j].ontime);
-+ create_param_proc("offtime", subentry, &param->tone[j].offtime);
-+ for (k = 0; k < TONE_FREQ_NUM; k++) {
-+ sprintf(temp, "frequency%d", k + 1);
-+ create_param_freq_proc(temp, subentry, &param->tone[j].fs[k]);
-+ }
-+ }
-+ }
-+ subentry = proc_mkdir("silent_detect", entry);
-+ param->sd.subentry = subentry;
-+ if (subentry) {
-+ create_param_proc("detect_tx", subentry, &param->sd.detect_tx);
-+ create_param_proc("detect_rx", subentry, &param->sd.detect_rx);
-+ create_param_proc("length", subentry, &param->sd.length);
-+ create_param_proc("threshold", subentry, &param->sd.threshold);
-+ }
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+static void set_chan_cards_bit(struct a24xx *wc)
-+{
-+ int i, channo;
-+ DECLARE_BITMAP(tempflag, TOTAL_CARDS);
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ bitmap_zero(tempflag, TOTAL_CARDS);
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ channo = wc->chans[i]->channo;
-+ if (channo <= TOTAL_CARDS) {
-+ if (wc_dev->modtype[i] == MOD_TYPE_FXO) {
-+ set_bit(channo - 1, fxo_cardflag);
-+ set_bit(channo - 1, tempflag);
-+ }
-+ }
-+ }
-+
-+ rebuild_recur_proc(tempflag, 0);
-+}
-+
-+static void clear_chan_cards_bit(struct a24xx *wc)
-+{
-+ int i, channo;
-+ DECLARE_BITMAP(tempflag, TOTAL_CARDS);
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ bitmap_zero(tempflag, TOTAL_CARDS);
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ channo = wc->chans[i]->channo;
-+ if (channo <= TOTAL_CARDS) {
-+ if (wc_dev->modtype[i] == MOD_TYPE_FXO) {
-+ clear_bit(channo - 1, fxo_cardflag);
-+ set_bit(channo - 1, tempflag);
-+ }
-+ }
-+ }
-+
-+ rebuild_recur_proc(tempflag, 1);
-+}
-+
-+int init_busydetect(struct a24xx *wc, const char *opermode)
-+{
-+ int res = 0;
-+
-+ if (!ref_count++) {
-+ bitmap_zero(fxo_cardflag, TOTAL_CARDS);
-+ bitmap_zero(fxs_cardflag, TOTAL_CARDS);
-+
-+ di = kzalloc(sizeof(*di), GFP_KERNEL);
-+ if (!di) {
-+ printk(KERN_ERR "Not enough memory, A2410P not support the busy tone and silence detection\n");
-+ res = -ENOMEM;
-+ goto out;
-+ }
-+
-+ init_detect_info(di, opermode);
-+
-+ opvxdsp_entry = proc_mkdir(module_name, NULL);
-+
-+ printk(KERN_INFO "A2410P start the busy tone and silence detection\n");
-+ }
-+
-+ set_chan_cards_bit(wc);
-+out:
-+ return res;
-+}
-+
-+void destroy_busydetect(struct a24xx *wc)
-+{
-+ if (ref_count) {
-+ clear_chan_cards_bit(wc);
-+
-+ if (!--ref_count) {
-+ if (di) {
-+ remove_proc_entry(module_name, NULL);
-+ kfree(di);
-+ printk(KERN_INFO "A2410P stop the busy tone and silence detection\n");
-+ }
-+ }
-+ }
-+}
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/busydetect.h 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/busydetect.h 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,313 @@
-+/*
-+ * OpenVox FXO Detect Busy Voice Driver for DAHDI Telephony interface
-+ *
-+ * Written by kevin.chen
-+
-+ * Copyright (C) 2012-2013 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#ifndef _BUSYDETECT_H
-+#define _BUSYDETECT_H
-+
-+#include "base.h"
-+
-+#define FRAME_SHORT_SIZE (DAHDI_CHUNKSIZE * 20)
-+#define SAMPLE_PER_SEC 8000
-+
-+#define TOTAL_CARDS 120
-+
-+#define SIN_DIVISION 128
-+static const short sin_table[] =
-+{
-+ 201,
-+ 603,
-+ 1005,
-+ 1407,
-+ 1809,
-+ 2210,
-+ 2611,
-+ 3012,
-+ 3412,
-+ 3812,
-+ 4211,
-+ 4609,
-+ 5007,
-+ 5404,
-+ 5800,
-+ 6195,
-+ 6590,
-+ 6983,
-+ 7376,
-+ 7767,
-+ 8157,
-+ 8546,
-+ 8933,
-+ 9319,
-+ 9704,
-+ 10088,
-+ 10469,
-+ 10850,
-+ 11228,
-+ 11605,
-+ 11980,
-+ 12354,
-+ 12725,
-+ 13095,
-+ 13463,
-+ 13828,
-+ 14192,
-+ 14553,
-+ 14912,
-+ 15269,
-+ 15624,
-+ 15976,
-+ 16326,
-+ 16673,
-+ 17018,
-+ 17361,
-+ 17700,
-+ 18037,
-+ 18372,
-+ 18703,
-+ 19032,
-+ 19358,
-+ 19681,
-+ 20001,
-+ 20318,
-+ 20632,
-+ 20943,
-+ 21251,
-+ 21555,
-+ 21856,
-+ 22154,
-+ 22449,
-+ 22740,
-+ 23028,
-+ 23312,
-+ 23593,
-+ 23870,
-+ 24144,
-+ 24414,
-+ 24680,
-+ 24943,
-+ 25202,
-+ 25457,
-+ 25708,
-+ 25956,
-+ 26199,
-+ 26439,
-+ 26674,
-+ 26906,
-+ 27133,
-+ 27357,
-+ 27576,
-+ 27791,
-+ 28002,
-+ 28209,
-+ 28411,
-+ 28610,
-+ 28803,
-+ 28993,
-+ 29178,
-+ 29359,
-+ 29535,
-+ 29707,
-+ 29875,
-+ 30038,
-+ 30196,
-+ 30350,
-+ 30499,
-+ 30644,
-+ 30784,
-+ 30920,
-+ 31050,
-+ 31177,
-+ 31298,
-+ 31415,
-+ 31527,
-+ 31634,
-+ 31737,
-+ 31834,
-+ 31927,
-+ 32015,
-+ 32099,
-+ 32177,
-+ 32251,
-+ 32319,
-+ 32383,
-+ 32442,
-+ 32496,
-+ 32546,
-+ 32590,
-+ 32629,
-+ 32664,
-+ 32693,
-+ 32718,
-+ 32738,
-+ 32753,
-+ 32762,
-+ 32767,
-+ 32767
-+};
-+
-+/* Level index range -30 ~ 0, step 1 */
-+#define MIN_INDEX_LEVEL -30
-+#define MAX_INDEX_LEVEL 0
-+#define STEP_LEVEL 1
-+static const short gain_table[] = {
-+ 722,
-+ 810,
-+ 909,
-+ 1020,
-+ 1144,
-+ 1284,
-+ 1440,
-+ 1616,
-+ 1813,
-+ 2034,
-+ 2283,
-+ 2561,
-+ 2874,
-+ 3224,
-+ 3618,
-+ 4059,
-+ 4554,
-+ 5110,
-+ 5734,
-+ 6433,
-+ 7218,
-+ 8099,
-+ 9087,
-+ 10196,
-+ 11440,
-+ 12836,
-+ 14402,
-+ 16160,
-+ 18132,
-+ 20344,
-+ 22826,
-+};
-+
-+/* Frequency index range 300 ~ 700, step 5 */
-+#define MIN_INDEX_FREQ 300
-+#define MAX_INDEX_FREQ 700
-+#define STEP_FREQ 5
-+static const short fac_table[] = {
-+ 31861,
-+ 31830,
-+ 31800,
-+ 31768,
-+ 31737,
-+ 31704,
-+ 31672,
-+ 31638,
-+ 31605,
-+ 31570,
-+ 31536,
-+ 31501,
-+ 31465,
-+ 31429,
-+ 31392,
-+ 31355,
-+ 31318,
-+ 31279,
-+ 31241,
-+ 31202,
-+ 31162,
-+ 31122,
-+ 31082,
-+ 31041,
-+ 30999,
-+ 30958,
-+ 30915,
-+ 30872,
-+ 30829,
-+ 30785,
-+ 30741,
-+ 30696,
-+ 30651,
-+ 30605,
-+ 30559,
-+ 30512,
-+ 30465,
-+ 30417,
-+ 30369,
-+ 30321,
-+ 30272,
-+ 30222,
-+ 30172,
-+ 30122,
-+ 30071,
-+ 30020,
-+ 29968,
-+ 29916,
-+ 29863,
-+ 29810,
-+ 29756,
-+ 29702,
-+ 29648,
-+ 29593,
-+ 29537,
-+ 29481,
-+ 29425,
-+ 29368,
-+ 29311,
-+ 29253,
-+ 29195,
-+ 29136,
-+ 29077,
-+ 29017,
-+ 28957,
-+ 28897,
-+ 28836,
-+ 28775,
-+ 28713,
-+ 28651,
-+ 28588,
-+ 28525,
-+ 28462,
-+ 28398,
-+ 28333,
-+ 28268,
-+ 28203,
-+ 28137,
-+ 28071,
-+ 28005,
-+ 27938,
-+};
-+
-+/* busydetect.c */
-+void parser_busy_silent_process(struct a24xx *wc, int is_write);
-+
-+int init_busydetect(struct a24xx *wc, const char *opermode);
-+void destroy_busydetect(struct a24xx *wc);
-+
-+/* callerid.c */
-+void parser_callerid_process(struct a24xx *wc, int cidbuflen, int cidtimeout);
-+void set_cidstart_desc_from_chan_num(int spanno, int channo, int cid_state);
-+void set_signal_unknown_from_chan_num(int spanno, int channo);
-+int is_callerid_disable(int spanno, int channo);
-+char is_ring_delay_operation(int spanno, int channo);
-+void reset_parser_variable_from_chan_num(int spanno, int channo);
-+
-+int init_callerid(struct a24xx *wc);
-+void destroy_callerid(struct a24xx *wc);
-+
-+#endif /* _BUSYDETECT_H */
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/callerid.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/callerid.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,1429 @@
-+/*
-+ * OpenVox Calling Identity Delivery Analysis Driver for DAHDI Telephony interface
-+ *
-+ * Written by kevin.chen
-+
-+ * Copyright (C) 2012-2013 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+/* Rev history
-+ *
-+ * Rev 0.10 add ringdly_flag variable, deal with special caller id case.
-+ * Rev 0.30 support new kernel version 3.10.0
-+ *
-+ */
-+
-+#include <linux/proc_fs.h>
-+#include <linux/ctype.h>
-+#include <linux/kmod.h>
-+#include "base.h"
-+#include "busydetect.h" /* use sin_table[] */
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
-+#include <linux/seq_file.h>
-+#endif
-+
-+static int cid_debug = 0;
-+module_param(cid_debug, int, 0600);
-+
-+/* Before using this directory, the directory must had been created */
-+static const char *module_name = "opvxdsp";
-+
-+#define MAX_CID_LEN 32
-+#define DTMF_BLOCK_SIZE 102
-+#define MAX_DTMF_DIGITS 64
-+
-+#define DTMF_TIMEOUT_SAMPLES (300 * DAHDI_CHUNKSIZE) /* default 300 msec */
-+
-+/* Support signals for caller id */
-+enum {
-+ /* Signal type for caller id fsk */
-+ CALLERID_BELL202_OR_V23,
-+ CALLERID_V23JP,
-+ MAX_FSK_NUM,
-+ /* Dtmf signal */
-+ CALLERID_DTMF,
-+};
-+
-+/* type for caller id start */
-+enum {
-+ CIDSTART_RING = 1,
-+ CIDSTART_POLARITY,
-+ CIDSTART_POLARITY_IN,
-+ CIDSTART_DTMF,
-+ MAX_CIDSTART,
-+};
-+
-+/* Unknown caller id signal */
-+#define UNKNOWN_CID_SIGNAL -1
-+
-+static const char *signal_desc[] = {
-+ [CALLERID_BELL202_OR_V23] = "bell or v23",
-+ [CALLERID_V23JP] = "v23_jp",
-+ [CALLERID_DTMF] = "dtmf",
-+};
-+static const char *cidstart_desc[] = {
-+ [CIDSTART_RING] = "ring",
-+ [CIDSTART_POLARITY] = "polarity",
-+ [CIDSTART_POLARITY_IN] = "polarity_in",
-+ [CIDSTART_DTMF] = "dtmf",
-+};
-+static const char *unknown_desc = "unknown";
-+
-+static const int dtmf_fac[] = {27978, 26955, 25700, 24217, 19072, 16324, 13084, 9314};
-+static const char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
-+
-+typedef struct freq_state {
-+ short prev2;
-+ short prev;
-+ short fac;
-+}freq_state_t;
-+
-+typedef struct callerid_dtmf {
-+ freq_state_t row[4];
-+ freq_state_t col[4];
-+
-+ int cur_sample;
-+ u32 energy;
-+ u8 digit;
-+ u8 last_hit;
-+
-+ int timeout;
-+
-+ /* Analytical results */
-+ char digits[MAX_DTMF_DIGITS + 1];
-+ int num;
-+}__attribute__((packed))callerid_dtmf_t;
-+
-+typedef struct complex {
-+ int re;
-+ int im;
-+}complex_t;
-+
-+typedef struct callerid_fsk {
-+ int baud_rate;
-+ int baud_frac;
-+ int sig_present;
-+ int last_bit;
-+
-+ int phase_rate[2];
-+ u32 phase_acc[2];
-+
-+ complex_t window[2][24];
-+ complex_t dot[2];
-+ int dot_pos;
-+ int span;
-+
-+ short last_amp;
-+ int power;
-+
-+ /* Analytical results */
-+ u8 name[MAX_CID_LEN];
-+ u8 number[MAX_CID_LEN];
-+
-+ int bit_pos;
-+ u8 msg[256];
-+ int msg_len;
-+ int continuous_one;
-+ int val;
-+}__attribute__((packed))callerid_fsk_t;
-+
-+typedef struct gen_wave {
-+ int bit_no;
-+ int bit_pos;
-+ int byte_no;
-+
-+ int occupied_len;
-+ int premark_len;
-+ int postmark_len;
-+
-+ int msg_len;
-+ u8 msg[256];
-+
-+ int baud_frac;
-+ int baud_rate;
-+
-+ int scaling;
-+ int phase_rates[2];
-+ u32 phase_acc;
-+}__attribute__((packed))gen_wave_t;
-+
-+typedef struct callerid {
-+ /* Initial current signal unknown */
-+ int cur_sig;
-+ /* Generate the signal */
-+ int appear;
-+
-+ /* DTMF signal analysis */
-+ callerid_dtmf_t dtmf;
-+ /* Variety of fsk signal analysis */
-+ callerid_fsk_t fsk[MAX_FSK_NUM];
-+
-+ /* Structuration for generator waveform */
-+ gen_wave_t gw;
-+}__attribute__((packed))callerid_t;
-+
-+struct param {
-+ /* The pointer of signal description from the last detection */
-+ const char *last_signal;
-+ /* The pointer of signal description from the current detection */
-+ const char *detect_signal;
-+ /* Signal the start of caller id */
-+ const char *cidstart;
-+ /* Close the current channel caller id support */
-+ u8 disable;
-+};
-+
-+struct detect_info {
-+ int channo;
-+ callerid_t cid;
-+
-+ /* Initialized to zero do not find any cidstart signal */
-+ char cidstart_type;
-+
-+ /*
-+ * Sometimes time interval is shorter between signal of caller id end and the next
-+ * bell before, so unable to provide a complete signal to asterisk
-+ * Set flag to postpone ring tones appears
-+ */
-+ char ringdly_flag;
-+
-+ struct param param;
-+ struct proc_dir_entry *entry;
-+
-+ struct list_head list;
-+}__attribute__((packed));
-+
-+#define MAX_LIST_SPAN 20
-+static struct list_head di_list[MAX_LIST_SPAN];
-+
-+static void reset_parser_variable_result(callerid_t *cid);
-+
-+static const u16 crc16_table[] = {
-+ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
-+ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
-+ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
-+ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
-+ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
-+ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
-+ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
-+ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
-+ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
-+ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
-+ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
-+ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
-+ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
-+ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
-+ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
-+ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
-+ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
-+ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
-+ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
-+ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
-+ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
-+ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
-+ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
-+ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
-+ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
-+ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
-+ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
-+ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
-+ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
-+ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
-+ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
-+ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
-+};
-+
-+static u16 check_crc16(const u8 *buf, int len)
-+{
-+ int i;
-+ u16 crc = 0;
-+
-+ for (i = 0; i < len; i++) {
-+ crc = (crc >> 8) ^ crc16_table[(crc ^ buf[i]) & 0xff];
-+ }
-+ return crc;
-+}
-+
-+static int get_phase_rate(int freq)
-+{
-+ return (freq * 65536 / SAMPLE_PER_SEC) * 65536;
-+}
-+
-+static short calc_amp(u32 acc)
-+{
-+ u32 phase, step;
-+ short amp;
-+
-+ phase = acc;
-+ phase >>= 23;
-+ step = phase & (SIN_DIVISION - 1);
-+ if ((phase & SIN_DIVISION)) {
-+ step = SIN_DIVISION - step;
-+ }
-+
-+ amp = sin_table[step];
-+ if ((phase & (2 * SIN_DIVISION))) {
-+ amp = -amp;
-+ }
-+ return amp;
-+}
-+
-+static void fsk_put_msg(callerid_fsk_t *fsk, const u8 msg[], int len, int sig_type)
-+{
-+ int i, pos;
-+ int res;
-+
-+ memset(fsk->name, 0, sizeof(fsk->name));
-+ memset(fsk->number, 0, sizeof(fsk->number));
-+ if (sig_type == CALLERID_V23JP) {
-+ pos = 7;
-+ for (i = 0; i < msg[6]; i++) {
-+ if (msg[i + pos] == 0x02) {
-+ i++;
-+ res = (msg[i + pos] <= MAX_CID_LEN) ? msg[i + pos] : MAX_CID_LEN;
-+ memcpy(fsk->number, msg + i + pos + 1, res);
-+ i += msg[i + pos] + 1;
-+ } else {
-+ i++;
-+ i += msg[i + pos] + 1;
-+ }
-+ }
-+ } else {
-+ if (msg[0] == 0x80 || msg[0] == 0x82) {
-+ /* MDMF */
-+ pos = 2;
-+ for (i = 0; i < msg[1];) {
-+ switch (msg[i + pos]) {
-+ case 2:
-+ case 4:
-+ i++;
-+ res = (msg[i + pos] <= MAX_CID_LEN) ? msg[i + pos] : MAX_CID_LEN;
-+ memcpy(fsk->number, msg + i + pos + 1, res);
-+ i += msg[i + pos] + 1;
-+ break;
-+ case 7:
-+ case 8:
-+ i++;
-+ res = (msg[i + pos] <= MAX_CID_LEN) ? msg[i + pos] : MAX_CID_LEN;
-+ memcpy(fsk->name, msg + i + pos + 1, res);
-+ i += msg[i + pos] + 1;
-+ break;
-+ default:
-+ i++;
-+ i += msg[i + pos] + 1;
-+ break;
-+ }
-+ }
-+ } else if (msg[0] == 0x04) {
-+ /* SDMF */
-+ if (msg[1] > 8) {
-+ memcpy(fsk->number, msg + 10, (msg[1] - 8) <= MAX_CID_LEN ? (msg[1] - 8) : MAX_CID_LEN);
-+ }
-+ }
-+ }
-+}
-+
-+static void fsk_put_bit(callerid_fsk_t *fsk, int bit, int sig_type)
-+{
-+ int i, sum;
-+
-+ if (fsk->bit_pos == 0) {
-+ if (!bit) {
-+ /* Start bit */
-+ fsk->bit_pos++;
-+ if (fsk->continuous_one > 10) {
-+ fsk->msg_len = 0;
-+ }
-+ fsk->continuous_one = 0;
-+ } else {
-+ fsk->continuous_one++;
-+ }
-+ } else if (fsk->bit_pos <= 8) {
-+ fsk->val >>= 1;
-+ if (bit) {
-+ fsk->val |= 0x80;
-+ }
-+ fsk->bit_pos++;
-+ } else {
-+ /* Stop bit */
-+ if (bit && fsk->msg_len < 256) {
-+ if (sig_type == CALLERID_V23JP) {
-+ if (fsk->msg_len == 0) {
-+ if (fsk->val == 0x90) {
-+ fsk->msg[fsk->msg_len++] = (u8)fsk->val;
-+ }
-+ } else {
-+ fsk->msg[fsk->msg_len++] = (u8)fsk->val;
-+ }
-+ if (fsk->msg_len >= 11 && fsk->msg_len == ((fsk->msg[6] & 0x7f) + 11)) {
-+ if (check_crc16(fsk->msg + 2, fsk->msg_len - 2) == 0) {
-+ for (i = 0; i < fsk->msg_len - 2; i++) {
-+ fsk->msg[i] &= 0x7f;
-+ }
-+ fsk_put_msg(fsk, fsk->msg, fsk->msg_len - 2, sig_type);
-+ }
-+ fsk->msg_len = 0;
-+ }
-+ } else {
-+ fsk->msg[fsk->msg_len++] = (u8)fsk->val;
-+ if (fsk->msg_len >= 3 && fsk->msg_len == (fsk->msg[1] + 3)) {
-+ sum = 0;
-+ for (i = 0; i < fsk->msg_len - 1; i++) {
-+ sum += fsk->msg[i];
-+ }
-+ if (256 - (sum & 0xff) == fsk->msg[i]) {
-+ fsk_put_msg(fsk, fsk->msg, fsk->msg_len - 1, sig_type);
-+ }
-+ fsk->msg_len = 0;
-+ }
-+ }
-+ } /* if (bit && fsk->msg_len < 256) */
-+
-+ fsk->bit_pos = 0;
-+ fsk->val = 0;
-+ }
-+}
-+
-+static void analysis_fsk(callerid_fsk_t *fsk, short amp[], int len, int sig_type)
-+{
-+ int i, j;
-+ int dot_pos;
-+ int hit_bit;
-+ short x;
-+ int dot;
-+ int sum[2];
-+ complex_t ph;
-+
-+ dot_pos = fsk->dot_pos;
-+
-+ for (i = 0; i < len; i++) {
-+ for (j = 0; j < 2; j++) {
-+ fsk->dot[j].re -= fsk->window[j][dot_pos].re;
-+ fsk->dot[j].im -= fsk->window[j][dot_pos].im;
-+
-+ ph.re = calc_amp(fsk->phase_acc[j] + (1 << 30));
-+ ph.im = calc_amp(fsk->phase_acc[j]);
-+ fsk->phase_acc[j] += fsk->phase_rate[j];
-+ fsk->window[j][dot_pos].re = (ph.re * amp[i]) >> 3;
-+ fsk->window[j][dot_pos].im = (ph.im * amp[i]) >> 3;
-+
-+ fsk->dot[j].re += fsk->window[j][dot_pos].re;
-+ fsk->dot[j].im += fsk->window[j][dot_pos].im;
-+
-+ dot = fsk->dot[j].re >> 15;
-+ sum[j] = dot * dot;
-+ dot = fsk->dot[j].im >> 15;
-+ sum[j] += dot * dot;
-+ }
-+
-+ x = (amp[i] >> 1) - fsk->last_amp;
-+ fsk->power += ((x * x - fsk->power) >> 4);
-+ fsk->last_amp = amp[i] >> 1;
-+ if (fsk->sig_present) {
-+ /* calc result 36380=pow(10.0,(level-14.7)/10.0)*32767.0*32767.0, level=-30 */
-+ if (fsk->power < 36380) {
-+ fsk->sig_present = 0;
-+ fsk->baud_frac = 0;
-+ continue;
-+ }
-+ } else {
-+ /* calc result 115046=pow(10.0,(level-9.7)/10.0)*32767.0*32767.0, level=-30 */
-+ if (fsk->power < 115046) {
-+ fsk->baud_frac = 0;
-+ continue;
-+ }
-+
-+ fsk->sig_present = 1;
-+ fsk->baud_frac = 0;
-+ fsk->last_bit = 0;
-+ }
-+
-+ hit_bit = (sum[0] < sum[1]);
-+ if (fsk->last_bit != hit_bit) {
-+ fsk->last_bit = hit_bit;
-+ fsk->baud_frac = (SAMPLE_PER_SEC >> 1);
-+ }
-+
-+ fsk->baud_frac += fsk->baud_rate;
-+ if (fsk->baud_frac >= SAMPLE_PER_SEC) {
-+ fsk->baud_frac -= SAMPLE_PER_SEC;
-+ fsk_put_bit(fsk, hit_bit, sig_type);
-+ }
-+
-+ if (++dot_pos >= fsk->span) {
-+ dot_pos = 0;
-+ }
-+ }
-+
-+ fsk->dot_pos = dot_pos;
-+}
-+
-+static inline u32 detect_result(freq_state_t *fs)
-+{
-+ u32 val;
-+
-+ val = fs->prev * fs->prev + fs->prev2 * fs->prev2 - ((fs->fac * fs->prev) >> 14) * fs->prev2;
-+ fs->prev = fs->prev2 = 0;
-+
-+ return val;
-+}
-+
-+static inline void update_detect(freq_state_t *fs, short s)
-+{
-+ short tmp;
-+
-+ tmp = fs->prev2;
-+ fs->prev2 = fs->prev;
-+ fs->prev = (((int)fs->fac * fs->prev2) >> 14) - tmp + (s >> 7);
-+}
-+
-+static void get_dtmf_number(callerid_dtmf_t *dtmf, u8 number[])
-+{
-+ int i;
-+ int code;
-+ char *p = dtmf->digits;
-+
-+ if (dtmf->num < 2) {
-+ return;
-+ }
-+
-+ if (p[0] == 'B') {
-+ code = simple_strtoul(p + 1, NULL, 10);
-+ if (code == 0) {
-+ /* Unknown caller id number */
-+ number[0] = 'O';
-+ } else if (code == 10) {
-+ /* Private caller id number */
-+ number[0] = 'P';
-+ }
-+ } else if (p[0] == 'D' && p[2] == '#') {
-+ if (p[1] == '1') {
-+ /* Private caller id number */
-+ number[0] = 'P';
-+ } else if (p[1] == '2' || p[2] == '3') {
-+ /* Unknown caller id number */
-+ number[0] = 'O';
-+ }
-+ } else if (p[0] == 'D' || p[0] == 'A') {
-+ for (i = 1; i < dtmf->num; i++) {
-+ if (p[i] == 'C' || p[i] == '#') {
-+ break;
-+ }
-+ if (isdigit(p[i]) && i <= MAX_CID_LEN) {
-+ number[i - 1] = p[i];
-+ }
-+ }
-+ } else if (isdigit(p[0])) {
-+ for (i = 0; i < dtmf->num; i++) {
-+ if (isdigit(p[i]) && i < MAX_CID_LEN) {
-+ number[i] = p[i];
-+ } else {
-+ break;
-+ }
-+ }
-+ } else {
-+ /* Unknown caller id number */
-+ number[0] = 'O';
-+ }
-+}
-+
-+static void analysis_dtmf(callerid_dtmf_t *dtmf, short s[], int len)
-+{
-+ int i, j, k;
-+ int limit;
-+ short temp;
-+ int row_energy[4];
-+ int col_energy[4];
-+ int best_row, best_col;
-+ u8 hit;
-+
-+ for (i = 0; i < len; i = limit) {
-+ if (len - i >= DTMF_BLOCK_SIZE - dtmf->cur_sample) {
-+ limit = i + DTMF_BLOCK_SIZE - dtmf->cur_sample;
-+ } else {
-+ limit = len;
-+ }
-+
-+ for (j = i; j < limit; j++) {
-+ temp = (s[j] < 0 ? -s[j] : s[j]) >> 7;
-+ dtmf->energy += temp * temp;
-+ for (k = 0; k < 4; k++) {
-+ update_detect(&dtmf->row[k], s[j]);
-+ update_detect(&dtmf->col[k], s[j]);
-+ }
-+ }
-+
-+ dtmf->cur_sample += (limit - i);
-+ if (dtmf->cur_sample < DTMF_BLOCK_SIZE) {
-+ break;
-+ }
-+
-+ row_energy[0] = detect_result(&dtmf->row[0]);
-+ col_energy[0] = detect_result(&dtmf->col[0]);
-+ best_row = 0;
-+ best_col = 0;
-+ for (j = 1; j < 4; j++) {
-+ row_energy[j] = detect_result(&dtmf->row[j]);
-+ if (row_energy[j] > row_energy[best_row]) {
-+ best_row = j;
-+ }
-+ col_energy[j] = detect_result(&dtmf->col[j]);
-+ if (col_energy[j] > col_energy[best_col]) {
-+ best_col = j;
-+ }
-+ }
-+
-+ hit = 0;
-+ if (row_energy[best_row] >= 10438 &&
-+ col_energy[best_col] >= 10438 &&
-+ col_energy[best_col] < row_energy[best_row] * 2 &&
-+ col_energy[best_col] * 6 > row_energy[best_row]) {
-+ for (j = 0; j < 4; j++) {
-+ if ((j != best_row && row_energy[j] * 6 > row_energy[best_row]) ||
-+ (j != best_col && col_energy[j] * 6 > col_energy[best_col])) {
-+ break;
-+ }
-+ }
-+ if (j >= 4 && ((row_energy[best_row] + col_energy[best_col]) > 42 * dtmf->energy)) {
-+ hit = dtmf_positions[(best_row << 2) + best_col];
-+ }
-+ }
-+
-+ if (hit) {
-+ dtmf->timeout = 0;
-+ } else {
-+ dtmf->timeout += DTMF_BLOCK_SIZE;
-+ }
-+
-+ if (hit != dtmf->digit) {
-+ if (dtmf->last_hit != dtmf->digit) {
-+ hit = (hit && hit == dtmf->last_hit) ? hit : 0;
-+ if (hit) {
-+ if (dtmf->num < MAX_DTMF_DIGITS) {
-+ dtmf->digits[dtmf->num++] = (char)hit;
-+ dtmf->digits[dtmf->num] = '\0';
-+ }
-+ }
-+ dtmf->digit = hit;
-+ }
-+ }
-+ dtmf->last_hit = hit;
-+ dtmf->energy = 0;
-+ dtmf->cur_sample = 0;
-+ }
-+}
-+
-+static const u16 mon_yday[2][13] = {
-+ /* Normal year */
-+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
-+ /* Leap year */
-+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
-+};
-+
-+static void get_systime_val(int *mon, int *mday, int *hour, int *min)
-+{
-+ struct timeval tv;
-+ const u16 *ip;
-+ int days, rem, y;
-+ int yg;
-+
-+ do_gettimeofday(&tv);
-+
-+#define SECS_PER_HOUR (60 * 60)
-+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-+ days = tv.tv_sec / SECS_PER_DAY;
-+ rem = tv.tv_sec % SECS_PER_DAY;
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-+ extern struct timezone sys_tz;
-+#endif
-+ rem += (-sys_tz.tz_minuteswest * 60);
-+ while (rem < 0) {
-+ rem += SECS_PER_DAY;
-+ days--;
-+ }
-+ while (rem > SECS_PER_DAY) {
-+ rem -= SECS_PER_DAY;
-+ days++;
-+ }
-+
-+ *hour = rem / SECS_PER_HOUR;
-+ rem %= SECS_PER_HOUR;
-+ *min = rem / 60;
-+
-+#define IS_LEAP(y) (((y) % 4 == 0) && ((y) % 100 != 0 || (y) % 400 == 0))
-+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-+#define LEAP_BETWEEN(y) (DIV(y, 4) - DIV(y, 100) + DIV(y, 400))
-+ y = 1970;
-+ while (days < 0 || days >= (IS_LEAP(y) ? 366 : 365)) {
-+ yg = y + DIV(days, 365);
-+ days -= ((yg - y) * 365 + LEAP_BETWEEN(yg - 1) - LEAP_BETWEEN(y - 1));
-+ y = yg;
-+ }
-+
-+ ip = mon_yday[IS_LEAP(y)];
-+ for (y = 11; days < ip[y]; y--) {
-+ continue;
-+ }
-+ days -= ip[y];
-+
-+ *mon = y + 1;
-+ *mday = days + 1;
-+}
-+
-+static int build_msg(u8 *msg, const char *number, const char *name)
-+{
-+ int i, res;
-+ int len;
-+ int mon, mday, hour, min;
-+ int sum = 0;
-+ u8 *ptr = msg + 2;
-+
-+ get_systime_val(&mon, &mday, &hour, &min);
-+ res = sprintf(ptr, "\001\010%02d%02d%02d%02d", mon, mday, hour, min);
-+ ptr += res;
-+
-+ if (strlen(number)) {
-+ len = strlen(number);
-+ res = sprintf(ptr, "\002%c", len);
-+ ptr += res;
-+ for (i = 0; i < len; i++) {
-+ ptr[i] = number[i];
-+ }
-+ ptr[i] = '\0';
-+ ptr += len;
-+ } else {
-+ res = sprintf(ptr, "\004\001O");
-+ ptr += res;
-+ }
-+
-+ if (strlen(name)) {
-+ len = strlen(name);
-+ res = sprintf(ptr, "\007%c", len);
-+ ptr += res;
-+ for (i = 0; i < len; i++) {
-+ ptr[i] = name[i];
-+ }
-+ ptr[i] = '\0';
-+ ptr += len;
-+ } else {
-+ res = sprintf(ptr, "\010\001O");
-+ ptr += res;
-+ }
-+
-+ msg[0] = 0x80;
-+ msg[1] = ptr - msg - 2;
-+
-+ for (i = 0; i < ptr - msg; i++) {
-+ sum += msg[i];
-+ }
-+ msg[ptr - msg] = 256 - (sum & 0xff);
-+ ptr++;
-+
-+ return (ptr - msg);
-+}
-+
-+static int fsk_get_bit(gen_wave_t *gw)
-+{
-+ int bit;
-+
-+ if (gw->bit_no < gw->occupied_len) {
-+ bit = gw->bit_no & 1;
-+ gw->bit_no++;
-+ } else if (gw->bit_no < gw->occupied_len + gw->premark_len) {
-+ bit = 1;
-+ gw->bit_no++;
-+ } else if (gw->bit_no == gw->occupied_len + gw->premark_len) {
-+ if (gw->bit_pos == 0) {
-+ /* Start bit */
-+ bit = 0;
-+ gw->bit_pos++;
-+ } else if (gw->bit_pos <= 8) {
-+ bit = (gw->msg[gw->byte_no] >> (gw->bit_pos - 1)) & 1;
-+ gw->bit_pos++;
-+ } else {
-+ /* Stop bit */
-+ bit = 1;
-+ gw->bit_pos = 0;
-+ if (++gw->byte_no >= gw->msg_len) {
-+ gw->bit_no++;
-+ }
-+ }
-+ } else if (gw->bit_no <= gw->occupied_len + gw->premark_len + gw->postmark_len) {
-+ bit = 1;
-+ gw->bit_no++;
-+ } else {
-+ /* Completion */
-+ bit = -1;
-+ }
-+
-+ return bit;
-+}
-+
-+static short generater_amp(u32 *phase_acc, int phase_rate, int scale)
-+{
-+ short amp;
-+
-+ amp = (short)(((int)calc_amp(*phase_acc) * scale) >> 15);
-+ *phase_acc += phase_rate;
-+ return amp;
-+}
-+
-+static int fsk_gen(gen_wave_t *gw, short amp[], int len)
-+{
-+ int i = 0;
-+ int bit = 0;
-+ static int cur_bit = 1;
-+ int cur_phase_rate;
-+
-+ cur_phase_rate = gw->phase_rates[cur_bit];
-+ while (i < len) {
-+ if ((gw->baud_frac += gw->baud_rate) >= SAMPLE_PER_SEC) {
-+ gw->baud_frac -= SAMPLE_PER_SEC;
-+ bit = fsk_get_bit(gw);
-+ if (bit == -1) {
-+ /* Completion */
-+ cur_bit = 1;
-+ break;
-+ }
-+ cur_bit = bit & 1;
-+ cur_phase_rate = gw->phase_rates[cur_bit];
-+ }
-+ amp[i++] = generater_amp(&gw->phase_acc, cur_phase_rate, gw->scaling);
-+ }
-+
-+ return bit;
-+}
-+
-+static void analysis_all_signal(callerid_t *cid, short s[], int len)
-+{
-+ int i;
-+
-+ analysis_dtmf(&cid->dtmf, s, len);
-+ for (i = 0; i < MAX_FSK_NUM; i++) {
-+ analysis_fsk(&cid->fsk[i], s, len, i);
-+ }
-+}
-+
-+static void analysis_current_signal(callerid_t *cid, short s[], int len)
-+{
-+ switch (cid->cur_sig) {
-+ case CALLERID_BELL202_OR_V23:
-+ case CALLERID_V23JP:
-+ analysis_fsk(&cid->fsk[cid->cur_sig], s, len, cid->cur_sig);
-+ break;
-+ case CALLERID_DTMF:
-+ analysis_dtmf(&cid->dtmf, s, len);
-+ break;
-+ default: /* UNKNOWN_CID_SIGNAL */
-+ /* signal of caller id is unknown, re-check */
-+ analysis_all_signal(cid, s, len);
-+ break;
-+ }
-+}
-+
-+static struct detect_info *get_detect_info_from_chan_num(int spanno, int channo)
-+{
-+ struct detect_info *di;
-+
-+ if (spanno <= 0 || spanno > MAX_LIST_SPAN) {
-+ return NULL;
-+ }
-+
-+ list_for_each_entry(di, &di_list[spanno - 1], list) {
-+ if (di->channo == channo) {
-+ /* Find the corresponding matching */
-+ return di;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+static void set_signal_desc(struct detect_info *di)
-+{
-+ di->param.last_signal = di->param.detect_signal;
-+
-+ switch (di->cid.cur_sig) {
-+ case CALLERID_BELL202_OR_V23:
-+ case CALLERID_V23JP:
-+ case CALLERID_DTMF:
-+ di->param.detect_signal = signal_desc[di->cid.cur_sig];
-+ break;
-+ default: /* UNKNOWN_CID_SIGNAL */
-+ di->param.detect_signal = unknown_desc;
-+ break;
-+ }
-+}
-+
-+void set_signal_unknown_from_chan_num(int spanno, int channo)
-+{
-+ struct detect_info *di;
-+
-+ di = get_detect_info_from_chan_num(spanno, channo);
-+ if (di) {
-+ /* Default standard does not analyze the current signal */
-+ di->cid.cur_sig = UNKNOWN_CID_SIGNAL;
-+ set_signal_desc (di);
-+ /* set the ring delay flag */
-+ if (di->cid.dtmf.num > 1) {
-+ di->ringdly_flag = 1;
-+ } else {
-+ di->ringdly_flag = di->cid.appear > 0 ? 1 : 0;
-+ }
-+ }
-+}
-+
-+char is_ring_delay_operation(int spanno, int channo)
-+{
-+ struct detect_info *di;
-+
-+ di = get_detect_info_from_chan_num(spanno, channo);
-+ if (di) {
-+ return di->ringdly_flag;
-+ } else {
-+ return 0;
-+ }
-+}
-+
-+static void clear_cidstart_type(struct detect_info *di)
-+{
-+ di->cidstart_type = 0;
-+}
-+
-+static void set_cidstart_desc_force(struct detect_info *di, int type)
-+{
-+ if (type >= CIDSTART_RING && type < MAX_CIDSTART) {
-+ di->cidstart_type = type;
-+ di->param.cidstart = cidstart_desc[type];
-+ }
-+}
-+
-+static void set_cidstart_desc(struct detect_info *di, int type)
-+{
-+ if (!di->cidstart_type) {
-+ /* Cidstart signal has not yet appeared */
-+ if (type >= CIDSTART_RING && type < MAX_CIDSTART) {
-+ di->cidstart_type = type;
-+ di->param.cidstart = cidstart_desc[type];
-+ }
-+ }
-+}
-+
-+void set_cidstart_desc_from_chan_num(int spanno, int channo, int cid_state)
-+{
-+ int type;
-+ struct detect_info *di;
-+
-+ if(cid_state == CID_STATE_IDLE) {
-+ type = CIDSTART_POLARITY;
-+ } else {
-+ type = CIDSTART_POLARITY_IN;
-+ }
-+
-+ di = get_detect_info_from_chan_num(spanno, channo);
-+ if (di) {
-+ set_cidstart_desc(di, type);
-+ }
-+}
-+
-+int is_callerid_disable(int spanno, int channo)
-+{
-+ int res = 0;
-+ struct detect_info *di;
-+
-+ di = get_detect_info_from_chan_num(spanno, channo);
-+ if (di) {
-+ res = di->param.disable;
-+ }
-+
-+ return res;
-+}
-+
-+static void print_cidinfo(u8 *number, u8 *name)
-+{
-+ struct timeval tv;
-+ int mon, mday, hour, min;
-+
-+ do_gettimeofday(&tv);
-+ get_systime_val(&mon, &mday, &hour, &min);
-+ printk(KERN_INFO "cid infor: %02d-%02d %02d:%02d number=%s, name=%s\n", mon, mday, hour, min, number, name);
-+}
-+
-+static void check_callerid_signal(struct detect_info *di, int timeout)
-+{
-+ int i, res = 0;
-+ callerid_fsk_t *fsk;
-+ u8 name[MAX_CID_LEN + 1];
-+ u8 number[MAX_CID_LEN + 1];
-+ callerid_t *cid = &di->cid;
-+
-+ if (cid->appear) {
-+ /* Last time we have found signal of caller id, directly to exit */
-+ return;
-+ }
-+ memset(name, 0, sizeof(name));
-+ memset(number, 0, sizeof(number));
-+ if (cid->dtmf.num > 1) {
-+ if (cid->dtmf.timeout >= timeout) {
-+ get_dtmf_number(&cid->dtmf, number);
-+ cid->cur_sig = CALLERID_DTMF;
-+ set_cidstart_desc(di, CIDSTART_DTMF);
-+ res = 1;
-+ }
-+ } else {
-+ for (i = 0; i < MAX_FSK_NUM; i++) {
-+ fsk = &cid->fsk[i];
-+ if (strlen(fsk->number)) {
-+ memcpy(number, fsk->number, MAX_CID_LEN);
-+ memcpy(name, fsk->name, MAX_CID_LEN);
-+ if (cid->dtmf.num == 1) {
-+ set_cidstart_desc_force(di, CIDSTART_DTMF);
-+ }
-+ cid->cur_sig = i;
-+ res = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (res) {
-+ if (strlen(number)) {
-+ cid->gw.msg_len = build_msg(cid->gw.msg, number, name);
-+ cid->appear = 1;
-+ set_signal_desc(di);
-+ if (cid_debug) {
-+ print_cidinfo(number, name);
-+ }
-+ }
-+ }
-+}
-+
-+void reset_parser_variable_from_chan_num(int spanno, int channo)
-+{
-+ struct detect_info *di;
-+
-+ di = get_detect_info_from_chan_num(spanno, channo);
-+ if (di) {
-+ reset_parser_variable_result(&di->cid);
-+ }
-+}
-+
-+static int generate_callerid(callerid_t *cid, short s[], int len)
-+{
-+ if (fsk_gen(&cid->gw, s, len) == -1) {
-+ /* Signal of caller id stop transmission */
-+ reset_parser_variable_result(cid);
-+ return 0;
-+ } else {
-+ return 1;
-+ }
-+}
-+
-+void parser_callerid_process(struct a24xx *wc, int cidbuflen, int cidtimeout)
-+{
-+ int i, j;
-+ /* Analytical work to ensure that within the ring tones */
-+#define LENGTH_PER_PTR (10 * DAHDI_CHUNKSIZE)
-+ short data[LENGTH_PER_PTR];
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ struct dahdi_chan *chan;
-+ struct detect_info *di;
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ if (wc_dev->modtype[i] == MOD_TYPE_FXO && !wc_dev->mod[i].fxo.offhook) {
-+ chan = wc->chans[i];
-+ if (wc_dev->cid_state[i] == CID_STATE_IDLE ||
-+ wc_dev->cid_state[i] == CID_STATE_RING_DELAY) {
-+ /* We need copy data to the caller id voice buffer */
-+ memcpy(wc_dev->cid_history_buf[i] + wc_dev->cid_history_ptr[i], chan->readchunk, DAHDI_CHUNKSIZE);
-+ wc_dev->cid_history_ptr[i] = (wc_dev->cid_history_ptr[i] + DAHDI_CHUNKSIZE)%(cidbuflen * DAHDI_MAX_CHUNKSIZE);
-+ di = get_detect_info_from_chan_num(wc->span.spanno, chan->channo);
-+ if (di && !di->param.disable) {
-+ /* Empty data to prevent interference */
-+ memset(chan->readchunk, DAHDI_LIN2X(0, chan), DAHDI_CHUNKSIZE);
-+ }
-+ } else if (wc_dev->cid_state[i] == CID_STATE_RING_ON) {
-+ di = get_detect_info_from_chan_num(wc->span.spanno, chan->channo);
-+ if (di) {
-+ if (wc_dev->cid_history_clone_cnt[i] > 0) {
-+ for (j = 0; j < LENGTH_PER_PTR; j++) {
-+ data[j] = DAHDI_XLAW(*(u8 *)(wc_dev->cid_history_buf[i] + wc_dev->cid_history_ptr[i] + j), chan);
-+ }
-+ analysis_current_signal(&di->cid, data, LENGTH_PER_PTR);
-+ wc_dev->cid_history_clone_cnt[i] -= (LENGTH_PER_PTR / DAHDI_CHUNKSIZE);
-+ if (wc_dev->cid_history_clone_cnt[i] < 0) {
-+ wc_dev->cid_history_clone_cnt[i] = 0;
-+ }
-+ wc_dev->cid_history_ptr[i] = (wc_dev->cid_history_ptr[i] + LENGTH_PER_PTR)%(cidbuflen * DAHDI_MAX_CHUNKSIZE);
-+ } else if (wc_dev->cid_history_clone_cnt[i] == 0) {
-+ check_callerid_signal(di, 0);
-+ wc_dev->cid_history_clone_cnt[i] = -1;
-+ }
-+ }
-+ } else if (wc_dev->cid_state[i] == CID_STATE_RING_OFF) {
-+ di = get_detect_info_from_chan_num(wc->span.spanno, chan->channo);
-+ if (di) {
-+ if (di->cid.appear) {
-+ set_cidstart_desc(di, CIDSTART_RING);
-+ if (generate_callerid(&di->cid, data, DAHDI_CHUNKSIZE)) {
-+ if (!di->param.disable) {
-+ /* Create effective caller id signal */
-+ for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-+ chan->readchunk[j] = DAHDI_LIN2X(data[j], chan);
-+ }
-+ }
-+ } else {
-+ clear_cidstart_type(di);
-+ wc_dev->cid_state[i] = CID_STATE_WAIT_RING_FINISH;
-+ wc_dev->cid_history_clone_cnt[i] = cidtimeout;
-+ }
-+ } else {
-+ for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-+ data[j] = DAHDI_XLAW(chan->readchunk[j], chan);
-+ if (!di->param.disable) {
-+ /* Empty data to prevent repeated parsing */
-+ chan->readchunk[j] = DAHDI_LIN2X(0, chan);
-+ }
-+ }
-+ analysis_current_signal(&di->cid, data, DAHDI_CHUNKSIZE);
-+ check_callerid_signal(di, DTMF_TIMEOUT_SAMPLES);
-+ } /* if (di->cid.appear) */
-+ }
-+ } else if (wc_dev->cid_state[i] == CID_STATE_WAIT_RING_FINISH) {
-+ if (wc_dev->cid_history_clone_cnt[i] > 0) {
-+ wc_dev->cid_history_clone_cnt[i]--;
-+ } else {
-+ wc_dev->cid_state[i] = CID_STATE_IDLE;
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+static void reset_parser_variable_result(callerid_t *cid)
-+{
-+ int i;
-+ callerid_dtmf_t *dtmf;
-+ callerid_fsk_t *fsk;
-+ gen_wave_t *gw;
-+
-+ /* Generate the signal reset */
-+ cid->appear = 0;
-+
-+ /* Reset the dtmf analytical variables and results */
-+ dtmf = &cid->dtmf;
-+ memset(dtmf, 0, sizeof(*dtmf));
-+ for (i = 0; i < 4; i++) {
-+ dtmf->row[i].fac = dtmf_fac[i];
-+ dtmf->col[i].fac = dtmf_fac[4 + i];
-+ }
-+
-+ /* Reset the variety of fsk analytical variables and results */
-+ for (i = 0; i < MAX_FSK_NUM; i++) {
-+ fsk = &cid->fsk[i];
-+ memset(fsk, 0, sizeof(*fsk));
-+ fsk->baud_rate = 1200;
-+ fsk->span = SAMPLE_PER_SEC / fsk->baud_rate;
-+ if (i == CALLERID_BELL202_OR_V23) {
-+ fsk->phase_rate[0] = get_phase_rate(2200);
-+ fsk->phase_rate[1] = get_phase_rate(1200);
-+ } else {
-+ fsk->phase_rate[0] = get_phase_rate(2100);
-+ fsk->phase_rate[1] = get_phase_rate(1300);
-+ }
-+ }
-+
-+ /* Reset the waveform analytical variables and results */
-+ fsk = &cid->fsk[CALLERID_BELL202_OR_V23];
-+ gw = &cid->gw;
-+ memset(gw, 0, sizeof(*gw));
-+ gw->occupied_len = 300;
-+ gw->premark_len = 180;
-+ gw->postmark_len = 60;
-+ gw->scaling = 2873; /* pow(10.0,(level-3.14)/20.0)*32767.0, level=-14 */
-+ gw->baud_rate = fsk->baud_rate;
-+ gw->phase_rates[0] = fsk->phase_rate[0];
-+ gw->phase_rates[1] = fsk->phase_rate[1];
-+}
-+
-+static void init_callerid_info(struct detect_info *di, int channo)
-+{
-+ /* Save channel number */
-+ di->channo = channo;
-+
-+ INIT_LIST_HEAD(&di->list);
-+
-+ /* Initial description of the parameters are unknown */
-+ di->param.detect_signal = unknown_desc;
-+ di->param.last_signal = unknown_desc;
-+ di->param.cidstart = unknown_desc;
-+
-+ /* Initial signal is unknown */
-+ di->cid.cur_sig = UNKNOWN_CID_SIGNAL;
-+
-+ /* Initialize dtmf, variety of fsk, waveform parameters */
-+ reset_parser_variable_result(&di->cid);
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int read_param_proc(char *buf, char **start, off_t off, int count,
-+ int *eof, void *data)
-+{
-+ int res;
-+ const char **p = (const char **)data;
-+
-+ if (off > 0) {
-+ /* We have finished to read, return 0 */
-+ res = 0;
-+ } else {
-+ res = sprintf(buf, "%s", *p);
-+ }
-+
-+ return res;
-+}
-+
-+static void create_param_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ struct proc_dir_entry *entry;
-+
-+ entry = create_proc_entry(name, 0444, base);
-+ if (entry) {
-+ entry->data = (void *)data;
-+ entry->read_proc = read_param_proc;
-+ }
-+}
-+#else
-+static int param_proc_show(struct seq_file *m, void *v)
-+{
-+ const char **p = (const char **)m->private;
-+
-+ seq_printf(m, "%s", *p);
-+ return 0;
-+}
-+
-+static int open_param_proc(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, param_proc_show, PDE_DATA(inode));
-+}
-+
-+static struct file_operations proc_param_fops = {
-+ .open = open_param_proc,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static void create_param_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ proc_create_data(name, 0444, base, &proc_param_fops, data);
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int write_param_off_proc(struct file *file, const char __user *buf,
-+ unsigned long count, void *data)
-+#else
-+static ssize_t write_param_off_proc(struct file *file, const char __user *buf,
-+ size_t count, loff_t *pos)
-+#endif
-+{
-+ char temp[24];
-+ int newval, len;
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+ u8 *val = (u8 *)data;
-+#else
-+ u8 *val = PDE_DATA(file_inode(file));
-+#endif
-+
-+ len = count > (sizeof(temp) - 1) ? (sizeof(temp) - 1) : count;
-+
-+ if (copy_from_user(temp, buf, len)) {
-+ return -EFAULT;
-+ }
-+
-+ temp[len] = '\0';
-+
-+ newval = simple_strtoul(temp, NULL, 10);
-+ *val = newval > 0 ? 1 : 0;
-+
-+ return count;
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static int read_param_off_proc(char *buf, char **start, off_t off, int count,
-+ int *eof, void *data)
-+{
-+ int res;
-+ u8 *val = (u8 *)data;
-+
-+ if (off > 0) {
-+ /* We have finished to read, return 0 */
-+ res = 0;
-+ } else {
-+ res = sprintf(buf, "%d", *val);
-+ }
-+
-+ return res;
-+}
-+
-+static void create_param_off_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ struct proc_dir_entry *entry;
-+
-+ entry = create_proc_entry(name, 0644, base);
-+ if (entry) {
-+ entry->data = data;
-+ entry->read_proc = read_param_off_proc;
-+ entry->write_proc = write_param_off_proc;
-+ }
-+}
-+#else
-+static int param_off_proc_show(struct seq_file *m, void *v)
-+{
-+ u8 *val = (u8 *)m->private;
-+
-+ seq_printf(m, "%d", *val);
-+ return 0;
-+}
-+
-+static int open_param_off_proc(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, param_off_proc_show, PDE_DATA(inode));
-+}
-+
-+static struct file_operations proc_param_off_fops = {
-+ .open = open_param_off_proc,
-+ .read = seq_read,
-+ .write = write_param_off_proc,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static void create_param_off_proc(const char *name, struct proc_dir_entry *base, void *data)
-+{
-+ proc_create_data(name, 0644, base, &proc_param_off_fops, data);
-+}
-+#endif
-+
-+/*
-+ * \brief parameter
-+ * is_clean: 0 is to create, 1 is to remove
-+ */
-+static void rebuild_callerid_proc(struct detect_info *di, int is_clean)
-+{
-+ char temp[24];
-+ struct proc_dir_entry *entry;
-+
-+ if (is_clean) {
-+ entry = di->entry;
-+ if (entry) {
-+ remove_proc_entry("last_signal", entry);
-+ remove_proc_entry("detect_signal", entry);
-+ remove_proc_entry("cidstart", entry);
-+ remove_proc_entry("disable", entry);
-+
-+ sprintf(temp, "%s/%d/opencid", module_name, di->channo);
-+ remove_proc_entry(temp, NULL);
-+ }
-+ } else {
-+ sprintf(temp, "%s/%d/opencid", module_name, di->channo);
-+ entry = proc_mkdir(temp, NULL);
-+ di->entry = entry;
-+ if (entry) {
-+ create_param_proc("last_signal", entry, &di->param.last_signal);
-+ create_param_proc("detect_signal", entry, &di->param.detect_signal);
-+ create_param_proc("cidstart", entry, &di->param.cidstart);
-+ create_param_off_proc("disable", entry, &di->param.disable);
-+ }
-+ }
-+}
-+
-+static void release_callerid_resource(struct a24xx *wc)
-+{
-+ int i;
-+ struct detect_info *cur, *next;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+
-+ if (wc->span.spanno <= 0 || wc->span.spanno > MAX_LIST_SPAN) {
-+ return;
-+ }
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ if (wc_dev->modtype[i] == MOD_TYPE_FXO) {
-+ list_for_each_entry_safe(cur, next, &di_list[wc->span.spanno - 1], list) {
-+ if (cur->channo == wc->chans[i]->channo) {
-+ /* Find the corresponding matching */
-+ list_del(&cur->list);
-+ rebuild_callerid_proc(cur, 1);
-+ kfree(cur);
-+ break;
-+ }
-+ }
-+ }
-+ }
-+}
-+
-+/* Called after created the top-level parameters directory "module_name" */
-+int init_callerid(struct a24xx *wc)
-+{
-+ int i, res = 0;
-+ struct detect_info *di;
-+ struct a24xx_dev *wc_dev = &wc->dev;
-+ static int first_in = 1;
-+
-+ if (first_in) {
-+ first_in = 0;
-+ for (i = 0; i < MAX_LIST_SPAN; i++) {
-+ INIT_LIST_HEAD(&di_list[i]);
-+ }
-+ }
-+
-+ if (wc->span.spanno <= 0 || wc->span.spanno > MAX_LIST_SPAN) {
-+ return -ENXIO;
-+ }
-+
-+ for (i = 0; i < wc_dev->max_cards; i++) {
-+ if (wc_dev->modtype[i] == MOD_TYPE_FXO) {
-+ di = kzalloc(sizeof(*di), GFP_KERNEL);
-+ if (!di) {
-+ printk(KERN_ERR "Not enough memory, A2410P not support the calling identity delivery analysis");
-+ res = -ENOMEM;
-+ goto out;
-+ }
-+
-+ init_callerid_info(di, wc->chans[i]->channo);
-+ rebuild_callerid_proc(di, 0);
-+
-+ list_add(&di->list, &di_list[wc->span.spanno - 1]);
-+ }
-+ }
-+
-+ return 0;
-+out:
-+ release_callerid_resource(wc);
-+ return res;
-+}
-+
-+/* Called before the release of the top-level parameters directory "module_name" */
-+void destroy_callerid(struct a24xx *wc)
-+{
-+ release_callerid_resource(wc);
-+}
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/ec3000.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/ec3000.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,589 @@
-+/*
-+ * Copyright (C) 2005-2006 Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ * Mark liu <mark.liu@openvox.cn>
-+ *
-+ * $Id: ec3000.c 159 2010-12-08 03:27:04Z liuyuan $
-+ * 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/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/string.h>
-+#include <linux/time.h>
-+#include <linux/version.h>
-+
-+#include "ec3000.h"
-+#include "oct6100api/oct6100_api.h"
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
-+#include <linux/config.h>
-+#endif
-+
-+/* API for Octasic access */
-+UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
-+{
-+ /* 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
-+ printk("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)
-+{
-+ 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
-+#define SOUT_DTMF_2 0x40000012
-+#define SOUT_DTMF_3 0x40000013
-+#define SOUT_DTMF_A 0x4000001A
-+#define SOUT_DTMF_4 0x40000014
-+#define SOUT_DTMF_5 0x40000015
-+#define SOUT_DTMF_6 0x40000016
-+#define SOUT_DTMF_B 0x4000001B
-+#define SOUT_DTMF_7 0x40000017
-+#define SOUT_DTMF_8 0x40000018
-+#define SOUT_DTMF_9 0x40000019
-+#define SOUT_DTMF_C 0x4000001C
-+#define SOUT_DTMF_STAR 0x4000001E
-+#define SOUT_DTMF_0 0x40000010
-+#define SOUT_DTMF_POUND 0x4000001F
-+#define SOUT_DTMF_D 0x4000001D
-+
-+#define ROUT_G168_2100GB_ON 0x10000000
-+#define ROUT_G168_2100GB_WSPR 0x10000002
-+#define ROUT_SOUT_G168_2100HB_END 0x50000003
-+#define ROUT_G168_1100GB_ON 0x10000004
-+
-+#define ROUT_DTMF_1 0x10000011
-+#define ROUT_DTMF_2 0x10000012
-+#define ROUT_DTMF_3 0x10000013
-+#define ROUT_DTMF_A 0x1000001A
-+#define ROUT_DTMF_4 0x10000014
-+#define ROUT_DTMF_5 0x10000015
-+#define ROUT_DTMF_6 0x10000016
-+#define ROUT_DTMF_B 0x1000001B
-+#define ROUT_DTMF_7 0x10000017
-+#define ROUT_DTMF_8 0x10000018
-+#define ROUT_DTMF_9 0x10000019
-+#define ROUT_DTMF_C 0x1000001C
-+#define ROUT_DTMF_STAR 0x1000001E
-+#define ROUT_DTMF_0 0x10000010
-+#define ROUT_DTMF_POUND 0x1000001F
-+#define ROUT_DTMF_D 0x1000001D
-+
-+#if 0
-+#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE
-+#else
-+#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN
-+#endif
-+
-+struct ec {
-+ tPOCT6100_INSTANCE_API pApiInstance;
-+ UINT32 aulEchoChanHndl[ 128 ];
-+ int chanflags[128];
-+ int ecmode[128];
-+ int numchans;
-+};
-+
-+#define FLAG_DTMF (1 << 0)
-+#define FLAG_MUTE (1 << 1)
-+#define FLAG_ECHO (1 << 2)
-+
-+static unsigned int tones[] = {
-+ SOUT_DTMF_1,
-+ SOUT_DTMF_2,
-+ SOUT_DTMF_3,
-+ SOUT_DTMF_A,
-+ SOUT_DTMF_4,
-+ SOUT_DTMF_5,
-+ SOUT_DTMF_6,
-+ SOUT_DTMF_B,
-+ SOUT_DTMF_7,
-+ SOUT_DTMF_8,
-+ SOUT_DTMF_9,
-+ SOUT_DTMF_C,
-+ SOUT_DTMF_STAR,
-+ SOUT_DTMF_0,
-+ SOUT_DTMF_POUND,
-+ SOUT_DTMF_D,
-+ SOUT_G168_1100GB_ON,
-+
-+ ROUT_DTMF_1,
-+ ROUT_DTMF_2,
-+ ROUT_DTMF_3,
-+ ROUT_DTMF_A,
-+ ROUT_DTMF_4,
-+ ROUT_DTMF_5,
-+ ROUT_DTMF_6,
-+ ROUT_DTMF_B,
-+ ROUT_DTMF_7,
-+ ROUT_DTMF_8,
-+ ROUT_DTMF_9,
-+ ROUT_DTMF_C,
-+ ROUT_DTMF_STAR,
-+ ROUT_DTMF_0,
-+ ROUT_DTMF_POUND,
-+ ROUT_DTMF_D,
-+ ROUT_G168_1100GB_ON,
-+};
-+static void opvx_vpm_setecmode(struct ec *ec, int channel, int mode)
-+{
-+ tOCT6100_CHANNEL_MODIFY *modify;
-+ UINT32 ulResult;
-+
-+ if (ec->ecmode[channel] == mode)
-+ return;
-+ modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
-+ if (!modify) {
-+ printk("opvxa24xx: Unable to allocate memory for setec!\n");
-+ return;
-+ }
-+ Oct6100ChannelModifyDef(modify);
-+ modify->ulEchoOperationMode = mode;
-+ modify->ulChannelHndl = ec->aulEchoChanHndl[channel];
-+ ulResult = Oct6100ChannelModify(ec->pApiInstance, modify);
-+ if (ulResult != GENERIC_OK) {
-+ printk("Failed to apply echo can changes on channel %d, 0x%x!\n", channel, ulResult);
-+ } else {
-+#ifdef OCTASIC_DEBUG
-+ printk("Echo can on channel %d set to %d\n", channel, mode);
-+#endif
-+ ec->ecmode[channel] = mode;
-+ }
-+ kfree(modify);
-+}
-+
-+void opvx_vpm_setdtmf(struct ec *ec, int channel, int detect, int mute)
-+{
-+ tOCT6100_CHANNEL_MODIFY *modify;
-+ UINT32 ulResult;
-+
-+ modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL);
-+ if (!modify) {
-+ printk("opvxa24xx: Unable to allocate memory for setdtmf!\n");
-+ return;
-+ }
-+ Oct6100ChannelModifyDef(modify);
-+ modify->ulChannelHndl = ec->aulEchoChanHndl[channel];
-+ if (mute) {
-+ ec->chanflags[channel] |= FLAG_MUTE;
-+ modify->VqeConfig.fDtmfToneRemoval = TRUE;
-+ } else {
-+ ec->chanflags[channel] &= ~FLAG_MUTE;
-+ modify->VqeConfig.fDtmfToneRemoval = FALSE;
-+ }
-+ if (detect)
-+ ec->chanflags[channel] |= FLAG_DTMF;
-+ else
-+ ec->chanflags[channel] &= ~FLAG_DTMF;
-+ if (ec->chanflags[channel] & (FLAG_DTMF|FLAG_MUTE)) {
-+ if (!(ec->chanflags[channel] & FLAG_ECHO)) {
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE);
-+ }
-+ } else {
-+ if (!(ec->chanflags[channel] & FLAG_ECHO))
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_DIGITAL);
-+ }
-+
-+ ulResult = Oct6100ChannelModify(ec->pApiInstance, modify);
-+ if (ulResult != GENERIC_OK) {
-+ printk("Failed to apply dtmf mute changes on channel %d!\n", channel);
-+ }
-+/* printk("VPM450m: Setting DTMF on channel %d: %s / %s\n", channel, (detect ? "DETECT" : "NO DETECT"), (mute ? "MUTE" : "NO MUTE")); */
-+ kfree(modify);
-+}
-+
-+
-+void opvx_vpm_setec(struct ec *ec, int channel, int eclen)
-+{
-+ if (eclen) {
-+ ec->chanflags[channel] |= FLAG_ECHO;
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_NORMAL);
-+ } else {
-+ ec->chanflags[channel] &= ~FLAG_ECHO;
-+ if (ec->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) {
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE);
-+ } else
-+ opvx_vpm_setecmode(ec, channel, cOCT6100_ECHO_OP_MODE_DIGITAL);
-+ }
-+/* printk("VPM450m: Setting EC on channel %d to %d\n", channel, eclen); */
-+}
-+
-+int opvx_vpm_checkirq(struct ec *ec)
-+{
-+ tOCT6100_INTERRUPT_FLAGS InterruptFlags;
-+
-+ Oct6100InterruptServiceRoutineDef(&InterruptFlags);
-+ Oct6100InterruptServiceRoutine(ec->pApiInstance, &InterruptFlags);
-+
-+ return InterruptFlags.fToneEventsPending ? 1 : 0;
-+}
-+
-+int opvx_vpm_getdtmf(struct ec *ec, int *channel, int *tone, int *start)
-+{
-+ tOCT6100_TONE_EVENT tonefound;
-+ tOCT6100_EVENT_GET_TONE tonesearch;
-+ UINT32 ulResult;
-+
-+ Oct6100EventGetToneDef(&tonesearch);
-+ tonesearch.pToneEvent = &tonefound;
-+ tonesearch.ulMaxToneEvent = 1;
-+ ulResult = Oct6100EventGetTone(ec->pApiInstance, &tonesearch);
-+ if (tonesearch.ulNumValidToneEvent) {
-+ if (channel)
-+ *channel = tonefound.ulUserChanId;
-+ if (tone) {
-+ switch(tonefound.ulToneDetected) {
-+ case SOUT_DTMF_1:
-+ *tone = '1';
-+ break;
-+ case SOUT_DTMF_2:
-+ *tone = '2';
-+ break;
-+ case SOUT_DTMF_3:
-+ *tone = '3';
-+ break;
-+ case SOUT_DTMF_A:
-+ *tone = 'A';
-+ break;
-+ case SOUT_DTMF_4:
-+ *tone = '4';
-+ break;
-+ case SOUT_DTMF_5:
-+ *tone = '5';
-+ break;
-+ case SOUT_DTMF_6:
-+ *tone = '6';
-+ break;
-+ case SOUT_DTMF_B:
-+ *tone = 'B';
-+ break;
-+ case SOUT_DTMF_7:
-+ *tone = '7';
-+ break;
-+ case SOUT_DTMF_8:
-+ *tone = '8';
-+ break;
-+ case SOUT_DTMF_9:
-+ *tone = '9';
-+ break;
-+ case SOUT_DTMF_C:
-+ *tone = 'C';
-+ break;
-+ case SOUT_DTMF_STAR:
-+ *tone = '*';
-+ break;
-+ case SOUT_DTMF_0:
-+ *tone = '0';
-+ break;
-+ case SOUT_DTMF_POUND:
-+ *tone = '#';
-+ break;
-+ case SOUT_DTMF_D:
-+ *tone = 'D';
-+ break;
-+ case SOUT_G168_1100GB_ON:
-+ *tone = 'f';
-+ break;
-+ default:
-+#ifdef OCTASIC_DEBUG
-+ printk("Unknown tone value %08x\n", tonefound.ulToneDetected);
-+#endif
-+ *tone = 'u';
-+ break;
-+ }
-+ }
-+ if (start)
-+ *start = (tonefound.ulEventType == cOCT6100_TONE_PRESENT);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+unsigned int opvx_vpm_getcapacity(void *wc)
-+{
-+ UINT32 ulResult;
-+
-+ tOCT6100_API_GET_CAPACITY_PINS CapacityPins;
-+
-+ Oct6100ApiGetCapacityPinsDef(&CapacityPins);
-+ CapacityPins.pProcessContext = wc;
-+ CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR;
-+ CapacityPins.fEnableMemClkOut = TRUE;
-+ CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
-+
-+ ulResult = Oct6100ApiGetCapacityPins(&CapacityPins);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk("Failed to get chip capacity, code %08x!\n", ulResult);
-+ return 0;
-+ }
-+
-+ return CapacityPins.ulCapacityValue;
-+}
-+
-+struct ec *opvx_vpm_init(void *wc, int *isalaw, int numspans, const struct firmware *firmware)
-+{
-+ tOCT6100_CHIP_OPEN *ChipOpen;
-+ tOCT6100_GET_INSTANCE_SIZE InstanceSize;
-+ tOCT6100_CHANNEL_OPEN *ChannelOpen;
-+ UINT32 ulResult;
-+ struct ec *ec;
-+ int x,y,law;
-+#ifdef CONFIG_4KSTACKS
-+ unsigned long flags;
-+#endif
-+
-+ if (!(ec = kmalloc(sizeof(struct ec), GFP_KERNEL)))
-+ return NULL;
-+
-+ memset(ec, 0, sizeof(struct ec));
-+
-+ if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) {
-+ kfree(ec);
-+ return NULL;
-+ }
-+
-+ memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN));
-+
-+ if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) {
-+ kfree(ec);
-+ kfree(ChipOpen);
-+ return NULL;
-+ }
-+
-+ memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN));
-+
-+ for (x=0;x<128;x++)
-+ ec->ecmode[x] = -1;
-+
-+ ec->numchans = numspans * 32;
-+ printk("OpenVox VPM: echo cancellation for %d channels\n", ec->numchans);
-+
-+ Oct6100ChipOpenDef(ChipOpen);
-+
-+ /* Setup Chip Open Parameters */
-+ ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;
-+ Oct6100GetInstanceSizeDef(&InstanceSize);
-+
-+ ChipOpen->pProcessContext = wc;
-+
-+ ChipOpen->pbyImageFile = firmware->data;
-+ ChipOpen->ulImageSize = firmware->size;
-+ ChipOpen->fEnableMemClkOut = TRUE;
-+ ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
-+ ChipOpen->ulMaxChannels = ec->numchans;
-+ ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
-+ ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB;
-+ ChipOpen->ulNumMemoryChips = 1;
-+ ChipOpen->ulMaxTdmStreams = 4;
-+ ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ;
-+ ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
-+#if 0
-+ ChipOpen->fEnableAcousticEcho = TRUE;
-+#endif
-+
-+ ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk("Failed to get instance size, code %08x!\n", ulResult);
-+ kfree(ec);
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return NULL;
-+ }
-+
-+
-+ ec->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize);
-+ if (!ec->pApiInstance) {
-+ printk("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize);
-+ kfree(ec);
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return NULL;
-+ }
-+
-+ /* I don't know what to curse more in this comment, the problems caused by
-+ * the 4K kernel stack limit change or the octasic API for being so darn
-+ * stack unfriendly. Stupid, stupid, stupid. So we disable IRQs so we
-+ * don't run the risk of overflowing the stack while we initialize the
-+ * octasic. */
-+#ifdef CONFIG_4KSTACKS
-+ local_irq_save(flags);
-+#endif
-+ ulResult = Oct6100ChipOpen(ec->pApiInstance, ChipOpen);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk("Failed to open chip, code %08x!\n", ulResult);
-+#ifdef CONFIG_4KSTACKS
-+ local_irq_restore(flags);
-+#endif
-+ kfree(ec);
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return NULL;
-+ }
-+ for (x=0;x<128;x++) {
-+ /* execute this loop always on 4 span cards but
-+ * on 2 span cards only execute for the channels related to our spans */
-+ //if (( numspans > 2) || ((x & 0x03) <2)) {
-+ //if ((x & 0x03) < numspans) {
-+ if ( x < ec->numchans) {
-+ if (isalaw[x / 24]) // each span have 24 channels, it is spec for the 24 channel card. miaolin
-+ law = cOCT6100_PCM_A_LAW;
-+ else
-+ law = cOCT6100_PCM_U_LAW;
-+ Oct6100ChannelOpenDef(ChannelOpen);
-+ ChannelOpen->pulChannelHndl = &ec->aulEchoChanHndl[x];
-+ ChannelOpen->ulUserChanId = x;
-+ ChannelOpen->TdmConfig.ulRinPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulRinStream = 0;
-+ ChannelOpen->TdmConfig.ulRinTimeslot = x;
-+ ChannelOpen->TdmConfig.ulSinPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulSinStream = 1;
-+ ChannelOpen->TdmConfig.ulSinTimeslot = x;
-+ ChannelOpen->TdmConfig.ulSoutPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulSoutStream = 2;
-+ ChannelOpen->TdmConfig.ulSoutTimeslot = x;
-+ ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
-+ ChannelOpen->TdmConfig.ulRoutStream = 3;
-+ ChannelOpen->TdmConfig.ulRoutTimeslot = x;
-+ ChannelOpen->VqeConfig.fEnableNlp = TRUE;
-+ ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
-+ ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
-+
-+ ChannelOpen->fEnableToneDisabler = TRUE;
-+ ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL;
-+
-+ ulResult = Oct6100ChannelOpen(ec->pApiInstance, ChannelOpen);
-+ if (ulResult != GENERIC_OK) {
-+ printk("Failed to open channel %d!\n", x);
-+ }
-+ for (y=0;y<sizeof(tones) / sizeof(tones[0]); y++) {
-+ tOCT6100_TONE_DETECTION_ENABLE enable;
-+ Oct6100ToneDetectionEnableDef(&enable);
-+ enable.ulChannelHndl = ec->aulEchoChanHndl[x];
-+ enable.ulToneNumber = tones[y];
-+ if (Oct6100ToneDetectionEnable(ec->pApiInstance, &enable) != GENERIC_OK)
-+ printk("Failed to enable tone detection on channel %d for tone %d!\n", x, y);
-+ }
-+ }
-+ }
-+
-+#ifdef CONFIG_4KSTACKS
-+ local_irq_restore(flags);
-+#endif
-+ kfree(ChipOpen);
-+ kfree(ChannelOpen);
-+ return ec;
-+}
-+
-+void opvx_vpm_release(struct ec *ec)
-+{
-+ UINT32 ulResult;
-+ tOCT6100_CHIP_CLOSE ChipClose;
-+
-+ Oct6100ChipCloseDef(&ChipClose);
-+ ulResult = Oct6100ChipClose(ec->pApiInstance, &ChipClose);
-+ if (ulResult != cOCT6100_ERR_OK) {
-+ printk("Failed to close chip, code %08x!\n", ulResult);
-+ }
-+ vfree(ec->pApiInstance);
-+ kfree(ec);
-+}
-+
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/ec3000.h 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/ec3000.h 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,50 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * Written by mark.liu<mark.liu@openvox.cn>
-+ * $Id: ec3000.h 165 2010-12-09 05:38:49Z liuyuan $
-+ *
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#ifndef _EC3000_H_
-+#define _EC3000_H_
-+
-+#include <linux/firmware.h>
-+
-+struct ec;
-+
-+/* From driver */
-+unsigned int oct_get_reg(void *data, unsigned int reg);
-+void oct_set_reg(void *data, unsigned int reg, unsigned int val);
-+
-+/* From vpm450m */
-+extern void opvx_vpm_setec(struct ec *ec, int channel, int eclen);
-+extern void opvx_vpm_setdtmf(struct ec *ec, int channel, int detect, int mute);
-+extern int opvx_vpm_getdtmf(struct ec *ec, int *channel, int *tone, int *start);
-+extern int opvx_vpm_checkirq(struct ec *ec);
-+extern unsigned int opvx_vpm_getcapacity(void *wc);
-+
-+extern struct ec *opvx_vpm_init(void *wc, int *isalaw, int numspans, const struct firmware *firmware);
-+extern void opvx_vpm_release(struct ec *ec);
-+
-+#endif
-+
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/private.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/private.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,513 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * Written by mark.liu<mark.liu@openvox.cn>
-+ * $Id: private.c 446 2011-05-12 04:01:57Z liuyuan $
-+ *
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+//#ifdef VPM_SUPPORT
-+/* ec debug */
-+extern int ec_debug;
-+extern int vpmsupport;
-+//#endif
-+#define PEDANTIC_OCTASIC_CHECKING
-+
-+#define ZT_CHUNKSIZE 8
-+#define ZT_MIN_CHUNKSIZE ZT_CHUNKSIZE
-+#define ZT_DEFAULT_CHUNKSIZE ZT_CHUNKSIZE
-+#define ZT_MAX_CHUNKSIZE ZT_CHUNKSIZE
-+
-+#define MAX_NUM_CARDS 24
-+
-+#define CARDS_PER_MODULE 4
-+#define MOD_TYPE_FXS 0
-+#define MOD_TYPE_FXO 1
-+
-+
-+/* register base address */
-+#define REG_BASE 0x00000000
-+#define PIO_BASE 0x000004e0
-+#define TDM0_BASE 0x00000400
-+#define SPI_PCM_BASE 0x000004a0
-+#define TDM_MEM_BASE 0x00001000
-+#define PCI_BASE 0x00004000
-+
-+/* swap memory offset */
-+#define OPVX_RUN 0x0
-+#define OPVX_FWREADY 0x1
-+#define OPVX_FWVERSION 0x2
-+#define OPVX_DMA_REG 0x3
-+#define OPVX_ERR_REG 0x4
-+#define OPVX_IRQ_CNT_LO 0x5
-+#define OPVX_IRQ_CNT_HI 0x6
-+#define OPVX_BURST_SIZE 0x7
-+#define OPVX_BURST_INTERVAL 0x8
-+#define OPVX_PCI_IRQ_FRQ 0x9
-+#define OPVX_CARD_MASTER 0xa
-+#define OPVX_IRQ_COMMAND 0xb
-+#define OPVX_VPM_PRESENT 0x12
-+#define V2_OPVX_PIO_DATA 0x1c
-+#define OPVX_TEST 0x1f
-+#define V2_EC_BASE 0x00000100
-+
-+/* irq status register */
-+#define OPVX_IRQ_STATUS (0x40>>2) /* irq status register */
-+#define OPVX_IRQ_ENABLE (0x50>>2) /* irq status register */
-+
-+/* PIO register offset */
-+#define OPVX_PIO_DATA 0
-+#define OPVX_PIO_DIR 1
-+#define OPVX_PIO_CNTL 2
-+
-+/* SPI register offset */
-+#define OPVX_SPI_IN 0
-+#define OPVX_SPI_OUT 1
-+#define OPVX_SPI_STATUS 2
-+#define OPVX_SPI_CNTL 3
-+#define OPVX_SPI_CS 5
-+/* ec controller base addr */
-+#define EC_BASE 0x00000540
-+
-+#define OPVX_EC_CNTL 0
-+#define OPVX_EC_DATA 1
-+#define OPVX_EC_VPM 2
-+
-+/* echo canceller stuff */
-+#define BIT_EC_ADDR_STAGE (1<<0)
-+#define BIT_EC_CS (1<<1)
-+#define BIT_EC_WR (1<<2)
-+#define BIT_EC_RD (1<<3)
-+#define BIT_EC_ALE (1<<4)
-+#define BIT_EC_RDY (1<<5)
-+#define BIT_EC_DAS (1<<6)
-+#define BIT_EC_IRQ (1<<7)
-+
-+#define BIT_EC_PRESENT (1<<0)
-+
-+void __opvx_a24xx_setcreg(unsigned long mem32, unsigned int offset, unsigned int reg, unsigned int val)
-+{
-+ //printk("writing offset %d, reg %d at %d, value %d\n", offset, reg, offset + (reg<<2), val);
-+ unsigned int *p = (unsigned int*)(mem32 + offset + (reg<<2));
-+ *p = val;
-+}
-+
-+unsigned int __opvx_a24xx_getcreg(unsigned long mem32, unsigned int offset, unsigned char reg)
-+{
-+ //printk("reding offset %d, reg %d at %d\n", offset, reg, offset + (reg<<2));
-+ volatile unsigned int *p = (unsigned int*)(mem32 + offset + (reg<<2));
-+ return (*p);
-+}
-+
-+unsigned char __opvx_a24xx_read_8bits(unsigned long mem32)
-+{
-+ unsigned int res=0;
-+
-+ while((__opvx_a24xx_getcreg(mem32, SPI_PCM_BASE, OPVX_SPI_STATUS)&0x40)!=0x40);
-+ __opvx_a24xx_setcreg(mem32, SPI_PCM_BASE, OPVX_SPI_OUT, 0); /* we have to write something so the spi can work */
-+ while( (__opvx_a24xx_getcreg(mem32, SPI_PCM_BASE, OPVX_SPI_STATUS)&0x80) != 0x80); /* wait rx finish */
-+ res = __opvx_a24xx_getcreg(mem32, SPI_PCM_BASE, OPVX_SPI_IN);
-+
-+ return res&0xff;
-+}
-+
-+void __opvx_a24xx_start_dma(unsigned long mem32, unsigned int data)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_DMA_REG, data);
-+}
-+
-+void __opvx_a24xx_stop_dma(unsigned long mem32)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_DMA_REG, 0xffffffff); // -1 means stop dma.
-+}
-+
-+void __opvx_a24xx_restart_dma(unsigned long mem32)
-+{
-+ /* Reset Master and TDM */
-+ // TODO: do our work here.
-+}
-+
-+void __opvx_a24xx_reset_tdm(unsigned long mem32)
-+{
-+ /* Reset TDM */
-+ //TODO: do our work here;
-+}
-+
-+void __opvx_a24xx_set_irq_frq(unsigned long mem32,unsigned int frq)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_PCI_IRQ_FRQ,frq);
-+}
-+void __opvx_a24xx_set_master(unsigned long mem32,unsigned int master)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_CARD_MASTER,master);
-+}
-+unsigned int __opvx_a24xx_get_master(unsigned long mem32)
-+{
-+ return __opvx_a24xx_getcreg(mem32, REG_BASE, OPVX_CARD_MASTER);
-+}
-+
-+unsigned int __opvx_a24xx_get_version(unsigned long mem32)
-+{
-+ return __opvx_a24xx_getcreg(mem32, REG_BASE, OPVX_FWVERSION);
-+}
-+
-+unsigned int __opvx_a24xx_get_irqstatus(unsigned long mem32)
-+{
-+ return __opvx_a24xx_getcreg(mem32, PCI_BASE, OPVX_IRQ_STATUS);
-+}
-+
-+void __opvx_a24xx_set_irqstatus(unsigned long mem32, unsigned int value)
-+{
-+ __opvx_a24xx_setcreg(mem32, PCI_BASE, OPVX_IRQ_STATUS, value); // clear interrupt register.
-+}
-+
-+void __opvx_a24xx_clear_irqs(unsigned long mem32)
-+{
-+ __opvx_a24xx_setcreg(mem32, PCI_BASE, OPVX_IRQ_STATUS, 0xffffffff); /* clear all pending irqs */
-+ __opvx_a24xx_setcreg(mem32, SPI_PCM_BASE, OPVX_SPI_CNTL, 0); /* init spi port */
-+}
-+
-+void __opvx_a24xx_enable_interrupts(unsigned long mem32)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_BURST_INTERVAL, 0);
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_BURST_SIZE, 2);
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_RUN, 1);
-+}
-+
-+void __opvx_a24xx_disable_interrupts(unsigned long mem32)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_RUN, 0);
-+}
-+
-+unsigned int __opvx_a24xx_get_irqcnt_lo(unsigned long mem32)
-+{
-+ return __opvx_a24xx_getcreg(mem32, REG_BASE, OPVX_IRQ_CNT_LO);
-+}
-+
-+void __opvx_a24xx_reset_modules(unsigned long mem32, void (*func)(int), int data)
-+{
-+ __opvx_a24xx_setcreg(mem32, PIO_BASE, OPVX_PIO_DIR, 0xffffffff); /* all io as output */
-+ __opvx_a24xx_setcreg(mem32, PIO_BASE, OPVX_PIO_CNTL, 0); /* disable irq */
-+
-+// if(debug) {
-+// printk("opvxa24xx: raise reset\n");
-+// }
-+
-+ __opvx_a24xx_setcreg(mem32, PIO_BASE, OPVX_PIO_DATA, 0x1); /* GPIO0 As reset*/
-+ /* Wait for 1 second */
-+
-+ (*func)(data/2); /* delay 1/2 sec */
-+
-+ __opvx_a24xx_setcreg(mem32, PIO_BASE, OPVX_PIO_DATA, 0x0); /* GPIO0 As reset*/
-+// if(debug) {
-+// printk("opvxa24xx: pull down reset\n");
-+// }
-+
-+ (*func)(data/2); /* delay 1/2 sec */
-+
-+ __opvx_a24xx_setcreg(mem32, PIO_BASE, OPVX_PIO_DATA, 0x1); /* GPIO0 As reset*/
-+// if(debug) {
-+// printk("opvxa24xx: raise reset finally\n");
-+// }
-+
-+ (*func)(data/2); /* delay 1/2 sec */
-+}
-+
-+
-+void __opvx_a24xx_write_8bits(unsigned long mem32, unsigned char bits)
-+{
-+ volatile unsigned int t;
-+
-+ while((__opvx_a24xx_getcreg(mem32, SPI_PCM_BASE, OPVX_SPI_STATUS)&0x40)!=0x40);
-+ __opvx_a24xx_setcreg(mem32, SPI_PCM_BASE, OPVX_SPI_OUT, bits); /* we have to write something so the spi can work */
-+ while( (__opvx_a24xx_getcreg(mem32, SPI_PCM_BASE, OPVX_SPI_STATUS)&0x40) != 0x40); /* wait tx finish */
-+ t = __opvx_a24xx_getcreg(mem32, SPI_PCM_BASE, OPVX_SPI_IN);
-+}
-+
-+static inline void __reset_spi(void *wc_dev)
-+{
-+ return; /* we do nothing here */
-+}
-+
-+
-+void __opvx_a24xx_setcard(unsigned long mem32, int card)
-+{
-+ __opvx_a24xx_setcreg(mem32, SPI_PCM_BASE, OPVX_SPI_CS, 1<<(card/CARDS_PER_MODULE));
-+}
-+
-+void __opvx_a24xx_reset_spi(void *wc_dev, int card, void (*func)(void*, int))
-+{
-+ (*func)(wc_dev, card);
-+ __reset_spi(wc_dev);
-+ __reset_spi(wc_dev);
-+}
-+
-+static inline int __opvx_a24xx_hit_fxo_daisy(int number_daisy)
-+{
-+ int cid;
-+
-+ if (number_daisy==0) {
-+ cid=0;
-+ } else if (number_daisy==1) {
-+ cid=0x8;
-+ } else if (number_daisy==2) {
-+ cid=0x4;
-+ } else if (number_daisy==3) {
-+ cid=0xc;
-+ } else {
-+ cid= -1;
-+ }
-+
-+ return cid;
-+}
-+
-+void __opvx_a24xx_spi_setreg(void *wc_dev, unsigned long mem32, int card, int modtype, unsigned char reg, unsigned char value, void (*func)(void*, int))
-+{
-+ (*func)(wc_dev, card);
-+ if (modtype == MOD_TYPE_FXO) {
-+ __opvx_a24xx_write_8bits(mem32, 0x20 | __opvx_a24xx_hit_fxo_daisy(card%CARDS_PER_MODULE)); // fxo daisy operate.
-+ __opvx_a24xx_write_8bits(mem32, reg & 0x7f);
-+ } else {
-+ __opvx_a24xx_write_8bits(mem32, 1<<(card%CARDS_PER_MODULE)); // fxs daisy operate.
-+ __opvx_a24xx_write_8bits(mem32, reg & 0x7f);
-+ }
-+ __opvx_a24xx_write_8bits(mem32, value);
-+}
-+
-+unsigned char __opvx_a24xx_spi_getreg(void *wc_dev, unsigned long mem32, int card, int modtype, unsigned char reg, void (*func)(void*, int))
-+{
-+ (*func)(wc_dev, card);
-+ if (modtype == MOD_TYPE_FXO) {
-+ __opvx_a24xx_write_8bits(mem32, 0x60 | __opvx_a24xx_hit_fxo_daisy(card%CARDS_PER_MODULE)); // fxo daisy operate.
-+ __opvx_a24xx_write_8bits(mem32, reg & 0x7f);
-+ } else {
-+ __opvx_a24xx_write_8bits(mem32, 1<<(card%CARDS_PER_MODULE)); // fxs daisy operate.
-+ __opvx_a24xx_write_8bits(mem32, reg | 0x80);
-+ }
-+ return __opvx_a24xx_read_8bits(mem32);
-+}
-+
-+
-+static inline void __a24xx_raw_oct_out(unsigned long mem32, const unsigned int addr, const unsigned int value)
-+{
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE | BIT_EC_WR);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE | BIT_EC_WR | BIT_EC_ALE);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_DATA, value);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, BIT_EC_WR | BIT_EC_ALE | BIT_EC_CS);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, 0);
-+}
-+
-+static inline unsigned int __a24xx_raw_oct_in(unsigned long mem32, const unsigned int addr)
-+{
-+ unsigned int ret;
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE | BIT_EC_WR);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE | BIT_EC_WR | BIT_EC_ALE);
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, (addr<<16) | BIT_EC_ADDR_STAGE | BIT_EC_ALE);
-+#endif
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, BIT_EC_RD | BIT_EC_ALE | BIT_EC_CS);
-+ ret = __opvx_a24xx_getcreg(mem32, EC_BASE, OPVX_EC_DATA);
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_CNTL, 0);
-+
-+ return ret&0xffff;
-+}
-+
-+unsigned int __opvx_a24xx_oct_in(unsigned long mem32, unsigned int addr)
-+{
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ int count = 1000;
-+#endif
-+ __a24xx_raw_oct_out(mem32, 0x0008, (addr >> 20));
-+ __a24xx_raw_oct_out(mem32, 0x000a, (addr >> 4) & ((1 << 16) - 1));
-+ __a24xx_raw_oct_out(mem32, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1));
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ while((__a24xx_raw_oct_in(mem32, 0x0000) & (1 << 8)) && --count);
-+ if (count != 1000) {
-+// printk("Yah, read can be slow...\n");
-+ }
-+ if (!count) {
-+// printk("Read timed out!\n");
-+ }
-+#endif
-+ return __a24xx_raw_oct_in(mem32, 0x0004);
-+}
-+
-+void __opvx_a24xx_oct_out(unsigned long mem32, unsigned int addr, unsigned int value)
-+{
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ int count = 1000;
-+#endif
-+ __a24xx_raw_oct_out(mem32, 0x0008, (addr >> 20));
-+ __a24xx_raw_oct_out(mem32, 0x000a, (addr >> 4) & ((1 << 16) - 1));
-+ __a24xx_raw_oct_out(mem32, 0x0004, value);
-+ __a24xx_raw_oct_out(mem32, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1);
-+#ifdef PEDANTIC_OCTASIC_CHECKING
-+ while((__a24xx_raw_oct_in(mem32, 0x0000) & (1 << 8)) && --count);
-+ if (count != 1000) {
-+// printk("Yah, write can be slow\n");
-+ }
-+ if (!count) {
-+// printk("Write timed out!\n");
-+ }
-+#endif
-+}
-+
-+int __opvx_a24xx_check_vpm(unsigned long mem32)
-+{
-+ unsigned int check1, check2;
-+
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_VPM, 0); //disable vpm support at first.
-+
-+ if (!vpmsupport) {
-+// printk("OpenVox VPM: Support Disabled\n");
-+ return -1;
-+ }
-+
-+ __a24xx_raw_oct_out(mem32, 0x000a, 0x5678);
-+ __a24xx_raw_oct_out(mem32, 0x0004, 0x1234);
-+ check1 = __a24xx_raw_oct_in(mem32, 0x0004);
-+ check2 = __a24xx_raw_oct_in(mem32, 0x000a);
-+
-+// if (ec_debug) {
-+// printk("OCT Result: %04x/%04x\n", __a24xx_raw_oct_in(mem32, 0x0004), __a24xx_raw_oct_in(mem32, 0x000a));
-+// }
-+
-+ if (__a24xx_raw_oct_in(mem32, 0x0004) != 0x1234) {
-+// printk("OpenVox VPM: Not Present\n");
-+ return -2;
-+ }
-+
-+ return 0;
-+}
-+
-+void __opvx_a24xx_vpm_setpresent(unsigned long mem32)
-+{
-+ __opvx_a24xx_setcreg(mem32, EC_BASE, OPVX_EC_VPM, BIT_EC_PRESENT);
-+}
-+
-+void __opvx_a24xx_set_chunk(void *readchunk, void *writechunk,unsigned int frq,int buf_mult)
-+{
-+ unsigned char *tmp;
-+ tmp = *((unsigned char **)(writechunk)) + frq * ZT_MAX_CHUNKSIZE * (MAX_NUM_CARDS) * 2; /* in bytes */
-+ *(char **)readchunk = tmp;
-+}
-+
-+void __opvx_a24xx_transmit(unsigned long mem32, volatile unsigned char *writechunk, volatile unsigned char **txbuf,unsigned int irq_frq , unsigned int order)
-+{
-+ unsigned int int_cnt_lo = __opvx_a24xx_get_irqcnt_lo(mem32);
-+
-+ if (int_cnt_lo & 0x01) {
-+ /* Write is at interrupt address. Start writing from normal offset */
-+ *txbuf = writechunk + ZT_CHUNKSIZE * MAX_NUM_CARDS * order;
-+ } else {
-+ *txbuf = writechunk + ZT_CHUNKSIZE * MAX_NUM_CARDS * irq_frq + ZT_CHUNKSIZE * MAX_NUM_CARDS * order;
-+ }
-+}
-+
-+void __opvx_a24xx_receive(unsigned long mem32, volatile unsigned char *readchunk, volatile unsigned char **rxbuf,unsigned int irq_frq , unsigned int order)
-+{
-+ unsigned int int_cnt_lo = __opvx_a24xx_get_irqcnt_lo(mem32);
-+
-+ if (int_cnt_lo & 0x01) {
-+ /* Read is at interrupt address. Valid data is available at normal offset */
-+ *rxbuf = readchunk + ZT_CHUNKSIZE * MAX_NUM_CARDS * order;
-+ } else {
-+ *rxbuf = readchunk + ZT_CHUNKSIZE * MAX_NUM_CARDS * irq_frq + ZT_CHUNKSIZE * MAX_NUM_CARDS * order;
-+ }
-+}
-+
-+void __opvx_a24xx_reset_modules_v2(unsigned long mem32, void (*func)(int), int data)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, V2_OPVX_PIO_DATA, 0x02020200); /* gpio bit[1] set to 1*/
-+ (*func)(data/2); /* delay 1/2 sec */
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, V2_OPVX_PIO_DATA, 0x02020000); /* gpio bit[1] set to 0*/
-+ (*func)(data/2); /* delay 1/2 sec */
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, V2_OPVX_PIO_DATA, 0x02020200); /* gpio bit[1] set to 1*/
-+ (*func)(data/2); /* delay 1/2 sec */
-+}
-+
-+unsigned int __opvx_a24xx_oct_in_v2(unsigned long mem32, unsigned int addr)
-+{
-+ int count = 1000;
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x0008, (addr >> 20));
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x000a, (addr >> 4) & ((1 << 16) - 1));
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1));
-+ while((__opvx_a24xx_getcreg(mem32, V2_EC_BASE, 0x0000) & (1 << 8)) && --count);
-+ if (count != 1000) {
-+// printk("Yah, read can be slow...\n");
-+ }
-+ if (!count) {
-+// printk("Read timed out!\n");
-+ }
-+ return __opvx_a24xx_getcreg(mem32,V2_EC_BASE, 0x0004);
-+}
-+
-+
-+void __opvx_a24xx_oct_out_v2(unsigned long mem32, unsigned int addr, unsigned int value)
-+{
-+ int count = 1000;
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x0008, (addr >> 20));
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x000a, (addr >> 4) & ((1 << 16) - 1));
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x0004, value);
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1);
-+ while((__opvx_a24xx_getcreg(mem32,V2_EC_BASE, 0x0000) & (1 << 8)) && --count);
-+ if (count != 1000) {
-+// printk("Yah, write can be slow\n");
-+ }
-+ if (!count) {
-+// printk("Write timed out!\n");
-+ }
-+}
-+
-+int __opvx_a24xx_check_vpm_v2(unsigned long mem32)
-+{
-+ unsigned int check1, check2;
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_VPM_PRESENT, 0); //disable vpm support at first.
-+
-+ if (!vpmsupport) {
-+// printk("OpenVox VPM: Support Disabled\n");
-+ return -1;
-+ }
-+
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x000a, 0x5678);
-+ __opvx_a24xx_setcreg(mem32, V2_EC_BASE, 0x0004, 0x1234);
-+ check1 = __opvx_a24xx_getcreg(mem32, V2_EC_BASE, 0x0004);
-+ check2 = __opvx_a24xx_getcreg(mem32, V2_EC_BASE, 0x000a);
-+
-+// if (ec_debug) {
-+// printk("OCT Result: %04x/%04x\n", __opvx_a24xx_getcreg(mem32, V2_EC_BASE, 0x0004), __opvx_a24xx_getcreg(mem32, V2_EC_BASE, 0x000a));
-+// }
-+
-+ if (__opvx_a24xx_getcreg(mem32, V2_EC_BASE, 0x0004) != 0x1234) {
-+// printk("OpenVox VPM: Not Present\n");
-+ return -2;
-+ }
-+ return 0;
-+}
-+
-+void __opvx_a24xx_vpm_setpresent_v2(unsigned long mem32)
-+{
-+ __opvx_a24xx_setcreg(mem32, REG_BASE, OPVX_VPM_PRESENT, BIT_EC_PRESENT);
-+
-+}
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/si3050.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/si3050.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,228 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * Written by mark.liu<mark.liu@openvox.cn>
-+ * $Id: si3050.c 301 2011-01-19 05:20:32Z yangshugang $
-+ *
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/param.h>
-+#include <linux/jiffies.h>
-+
-+#include "fxo_modes.h"
-+#include "base.h"
-+
-+extern int debug;
-+extern int alawoverride;
-+extern int fxofullscale; /* fxo full scale tx/rx, register 30, acim */
-+extern int fwringdetect;
-+extern int _opermode;
-+extern int fxotxgain;
-+extern int fxorxgain;
-+extern int fastpickup;
-+
-+static int si3050_voicedaa_insane(struct a24xx_dev *wc_dev, int card)
-+{
-+ int blah;
-+ blah = a24xx_spi_getreg(wc_dev, card, 2);
-+ if (blah != 0x3) {
-+ return -2;
-+ }
-+ blah = a24xx_spi_getreg(wc_dev, card, 11);
-+ if (debug) {
-+ printk("VoiceDAA System: %02x\n", blah & 0xf);
-+ }
-+ return 0;
-+}
-+
-+/*********************************************************************
-+ * Set the hwgain on the analog modules
-+ *
-+ * card = the card position for this module (0-23)
-+ * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35)
-+ * tx = (0 for rx; 1 for tx)
-+ *
-+ *******************************************************************/
-+int si3050_set_hwgain(struct a24xx_dev *wc_dev, int card, __s32 gain, __u32 tx)
-+{
-+ if (!(wc_dev->modtype[card] == MOD_TYPE_FXO)) {
-+ printk("Cannot adjust gain. Unsupported module type!\n");
-+ return -1;
-+ }
-+ if (tx) {
-+ if (debug) {
-+ printk("setting FXO tx gain for card=%d to %d\n", card, gain);
-+ }
-+ if (gain >= -150 && gain <= 0) {
-+ a24xx_spi_setreg(wc_dev, card, 38, 16 + (gain/-10));
-+ a24xx_spi_setreg(wc_dev, card, 40, 16 + (-gain%10));
-+ } else if (gain <= 120 && gain > 0) {
-+ a24xx_spi_setreg(wc_dev, card, 38, gain/10);
-+ a24xx_spi_setreg(wc_dev, card, 40, (gain%10));
-+ } else {
-+ printk("FXO tx gain is out of range (%d)\n", gain);
-+ return -1;
-+ }
-+ } else { /* rx */
-+ if (debug) {
-+ printk("setting FXO rx gain for card=%d to %d\n", card, gain);
-+ }
-+ if (gain >= -150 && gain <= 0) {
-+ a24xx_spi_setreg(wc_dev, card, 39, 16+ (gain/-10));
-+ a24xx_spi_setreg(wc_dev, card, 41, 16 + (-gain%10));
-+ } else if (gain <= 120 && gain > 0) {
-+ a24xx_spi_setreg(wc_dev, card, 39, gain/10);
-+ a24xx_spi_setreg(wc_dev, card, 41, (gain%10));
-+ } else {
-+ printk("FXO rx gain is out of range (%d)\n", gain);
-+ return -1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int si3050_init_voicedaa(struct a24xx_dev *wc_dev, int card, int fast, int manual, int sane)
-+{
-+ unsigned char reg16=0, reg26=0, reg30=0, reg31=0;
-+ unsigned char ch;
-+ long newjiffies;
-+
-+ wc_dev->modtype[card] = MOD_TYPE_FXO;
-+ /* Sanity check the ProSLIC */
-+ a24xx_reset_spi(wc_dev, card);
-+ if (!sane && si3050_voicedaa_insane(wc_dev, card)) {
-+ return -2;
-+ }
-+
-+ /* Software reset */
-+ a24xx_spi_setreg(wc_dev, card, 1, 0x80);
-+
-+ /* Wait just a bit */
-+ __a24xx_wait_just_a_bit(HZ/10);
-+
-+ /* Enable PCM, ulaw */
-+ if (alawoverride) {
-+ a24xx_spi_setreg(wc_dev, card, 33, 0x20);
-+ } else {
-+ a24xx_spi_setreg(wc_dev, card, 33, 0x28);
-+ }
-+
-+ /* Set On-hook speed, Ringer impedence, and ringer threshold */
-+ reg16 |= (fxo_modes[_opermode].ohs << 6);
-+ reg16 |= (fxo_modes[_opermode].rz << 1);
-+ reg16 |= (fxo_modes[_opermode].rt);
-+ a24xx_spi_setreg(wc_dev, card, 16, reg16);
-+
-+ if(fwringdetect) {
-+ /* Enable ring detector full-wave rectifier mode */
-+ a24xx_spi_setreg(wc_dev, card, 18, 2);
-+ a24xx_spi_setreg(wc_dev, card, 24, 0);
-+ } else {
-+ /* Set to the device defaults */
-+ a24xx_spi_setreg(wc_dev, card, 18, 0);
-+ a24xx_spi_setreg(wc_dev, card, 24, 0x19);
-+ }
-+
-+ /* Set DC Termination:
-+ Tip/Ring voltage adjust, minimum operational current, current limitation */
-+ reg26 |= (fxo_modes[_opermode].dcv << 6);
-+ reg26 |= (fxo_modes[_opermode].mini << 4);
-+ reg26 |= (fxo_modes[_opermode].ilim << 1);
-+ a24xx_spi_setreg(wc_dev, card, 26, reg26);
-+
-+ /* Set AC Impedence */
-+ reg30 = (fxofullscale==1) ? (fxo_modes[_opermode].acim|0x10) : (fxo_modes[_opermode].acim);
-+ a24xx_spi_setreg(wc_dev, card, 30, reg30);
-+
-+ /* Misc. DAA parameters */
-+ if (fastpickup) {
-+ reg31 = 0xb3;
-+ } else {
-+ reg31 = 0xa3;
-+ }
-+
-+ reg31 |= (fxo_modes[_opermode].ohs2 << 3);
-+ a24xx_spi_setreg(wc_dev, card, 31, reg31);
-+
-+ /* Set Transmit/Receive timeslot */
-+ //printk("set card %d to %d\n", card, (3-(card%4)) * 8 + (card/4) * 64);
-+ a24xx_spi_setreg(wc_dev, card, 34, (card%4) * 8 + (card/4) * 32);
-+ a24xx_spi_setreg(wc_dev, card, 35, 0x00);
-+ a24xx_spi_setreg(wc_dev, card, 36, (card%4) * 8 + (card/4) * 32);
-+ a24xx_spi_setreg(wc_dev, card, 37, 0x00);
-+
-+ /* Enable ISO-Cap */
-+ a24xx_spi_setreg(wc_dev, card, 6, 0x00);
-+
-+ if (fastpickup) {
-+ a24xx_spi_setreg(wc_dev, card, 17, a24xx_spi_getreg(wc_dev, card, 17) | 0x20);
-+ }
-+
-+ /* Wait 1000ms for ISO-cap to come up */
-+ newjiffies = jiffies;
-+ newjiffies += 2 * HZ;
-+ while((jiffies < newjiffies) && !(a24xx_spi_getreg(wc_dev, card, 11) & 0xf0)) {
-+ __a24xx_wait_just_a_bit(HZ/10);
-+ }
-+
-+ /*if (!(a24xx_spi_getreg(wc_dev, card, 11) & 0xf0)) {*/
-+ ch = a24xx_spi_getreg(wc_dev, card, 11);
-+ if( ch == 0xff ) {
-+ printk("VoiceDAA not installed at card %d\n", card);
-+ return -1;
-+ }
-+ if (!(ch & 0xf0)) {
-+ printk("VoiceDAA did not bring up ISO link properly!\n");
-+ return -1;
-+ }
-+ if (debug) {
-+ printk("ISO-Cap is now up, line side: %02x rev %02x\n",
-+ a24xx_spi_getreg(wc_dev, card, 11) >> 4,
-+ (a24xx_spi_getreg(wc_dev, card, 13) >> 2) & 0xf);
-+ }
-+ /* Enable on-hook line monitor */
-+ a24xx_spi_setreg(wc_dev, card, 5, 0x08);
-+
-+ /* Take values for fxotxgain and fxorxgain and apply them to module */
-+ si3050_set_hwgain(wc_dev, card, fxotxgain, 1);
-+ si3050_set_hwgain(wc_dev, card, fxorxgain, 0);
-+
-+ /* NZ -- crank the tx gain up by 7 dB */
-+ if (!strcmp(fxo_modes[_opermode].name, "NEWZEALAND")) {
-+ printk("Adjusting gain\n");
-+ si3050_set_hwgain(wc_dev, card, 7, 1);
-+ }
-+
-+ if(debug) {
-+ printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n",
-+ (a24xx_spi_getreg(wc_dev, card, 38)/16) ? -(a24xx_spi_getreg(wc_dev, card, 38) - 16) : a24xx_spi_getreg(wc_dev, card, 38),
-+ (a24xx_spi_getreg(wc_dev, card, 40)/16) ? -(a24xx_spi_getreg(wc_dev, card, 40) - 16) : a24xx_spi_getreg(wc_dev, card, 40),
-+ (a24xx_spi_getreg(wc_dev, card, 39)/16) ? -(a24xx_spi_getreg(wc_dev, card, 39) - 16) : a24xx_spi_getreg(wc_dev, card, 39),
-+ (a24xx_spi_getreg(wc_dev, card, 41)/16) ? -(a24xx_spi_getreg(wc_dev, card, 41) - 16) : a24xx_spi_getreg(wc_dev, card, 41));
-+ }
-+
-+ /* battery state still unknown */
-+ return 0;
-+
-+}
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxa24xx/si321x.c 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxa24xx/si321x.c 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,1469 @@
-+/*
-+ * OpenVox A24xx FXS/FXO Interface Driver for Zapata Telephony interface
-+ *
-+ * Written by MiaoLin<miaolin@openvox.cn>
-+ * Written by mark.liu<mark.liu@openvox.cn>
-+ * $Id: si321x.c 482 2011-06-02 08:58:56Z liuyuan $
-+ *
-+ * Copyright (C) 2005-2010 OpenVox Communication Co. Ltd,
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include <linux/param.h>
-+#include <linux/jiffies.h>
-+#include <linux/sched.h>
-+
-+#include "proslic.h"
-+#include "fxo_modes.h"
-+#include "base.h"
-+
-+/* module param */
-+extern int debug;
-+extern int loopcurrent;
-+extern int reversepolarity;
-+extern int fxstxgain;
-+extern int fxsrxgain;
-+extern int boostringer;
-+extern int fastringer;
-+extern int lowpower;
-+extern int _opermode;
-+extern int alawoverride;
-+extern int fxshonormode;
-+
-+static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 };
-+
-+/* indirect_resg */
-+static alpha indirect_regs[] =
-+{
-+{0,255,"DTMF_ROW_0_PEAK",0x55C2},
-+{1,255,"DTMF_ROW_1_PEAK",0x51E6},
-+{2,255,"DTMF_ROW2_PEAK",0x4B85},
-+{3,255,"DTMF_ROW3_PEAK",0x4937},
-+{4,255,"DTMF_COL1_PEAK",0x3333},
-+{5,255,"DTMF_FWD_TWIST",0x0202},
-+{6,255,"DTMF_RVS_TWIST",0x0202},
-+{7,255,"DTMF_ROW_RATIO_TRES",0x0198},
-+{8,255,"DTMF_COL_RATIO_TRES",0x0198},
-+{9,255,"DTMF_ROW_2ND_ARM",0x0611},
-+{10,255,"DTMF_COL_2ND_ARM",0x0202},
-+{11,255,"DTMF_PWR_MIN_TRES",0x00E5},
-+{12,255,"DTMF_OT_LIM_TRES",0x0A1C},
-+{13,0,"OSC1_COEF",0x7B30},
-+{14,1,"OSC1X",0x0063},
-+{15,2,"OSC1Y",0x0000},
-+{16,3,"OSC2_COEF",0x7870},
-+{17,4,"OSC2X",0x007D},
-+{18,5,"OSC2Y",0x0000},
-+{19,6,"RING_V_OFF",0x0000},
-+{20,7,"RING_OSC",0x7EF0},
-+{21,8,"RING_X",0x0160},
-+{22,9,"RING_Y",0x0000},
-+{23,255,"PULSE_ENVEL",0x2000},
-+{24,255,"PULSE_X",0x2000},
-+{25,255,"PULSE_Y",0x0000},
-+//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower
-+{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower
-+{27,14,"XMIT_DIGITAL_GAIN",0x4000},
-+//{27,14,"XMIT_DIGITAL_GAIN",0x2000},
-+{28,15,"LOOP_CLOSE_TRES",0x1000},
-+{29,16,"RING_TRIP_TRES",0x3600},
-+{30,17,"COMMON_MIN_TRES",0x1000},
-+{31,18,"COMMON_MAX_TRES",0x0200},
-+{32,19,"PWR_ALARM_Q1Q2",0x0ff4},
-+{33,20,"PWR_ALARM_Q3Q4",0x6e7e},
-+{34,21,"PWR_ALARM_Q5Q6",0x0ff4},
-+{35,22,"LOOP_CLOSURE_FILTER",0x8000},
-+{36,23,"RING_TRIP_FILTER",0x0320},
-+{37,24,"TERM_LP_POLE_Q1Q2",0x0012},
-+{38,25,"TERM_LP_POLE_Q3Q4",0x0012},
-+{39,26,"TERM_LP_POLE_Q5Q6",0x0012},
-+{40,27,"CM_BIAS_RINGING",0x0C00},
-+{41,64,"DCDC_MIN_V",0x0C00},
-+{42,255,"DCDC_XTRA",0x1000},
-+{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
-+};
-+
-+static int si321x_powerup_proslic(struct a24xx_dev *wc_dev, int card, int fast)
-+{
-+ unsigned char vbat;
-+ unsigned long origjiffies;
-+ int lim;
-+
-+ /* Set period of DC-DC converter to 1/64 khz */
-+ a24xx_spi_setreg(wc_dev, card, 92, 0xff /* was 0xff */);
-+
-+ /* Wait for VBat to powerup */
-+ origjiffies = jiffies;
-+
-+ /* Disable powerdown */
-+ a24xx_spi_setreg(wc_dev, card, 14, 0);
-+
-+ /* If fast, don't bother checking anymore */
-+ if (fast)
-+ return 0;
-+
-+ while((vbat = a24xx_spi_getreg(wc_dev, card, 82)) < 0xc0) {
-+ /* Wait no more than 500ms */
-+ if ((jiffies - origjiffies) > HZ/2) {
-+ break;
-+ }
-+ }
-+
-+ if (vbat < 0xc0) {
-+ if (wc_dev->proslic_power == PROSLIC_POWER_UNKNOWN) {
-+ printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE A24xxP??\n",
-+ card, (int)(((jiffies - origjiffies) * 1000 / HZ)),
-+ vbat * 375);
-+ }
-+ wc_dev->proslic_power = PROSLIC_POWER_WARNED;
-+ return -1;
-+ } else if (debug) {
-+ printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
-+ card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));
-+ }
-+ wc_dev->proslic_power = PROSLIC_POWER_ON;
-+
-+ /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */
-+ /* If out of range, just set it to the default value */
-+ lim = (loopcurrent - 20) / 3;
-+ if ( loopcurrent > 41 ) {
-+ lim = 0;
-+ if (debug) {
-+ printk("Loop current out of range! Setting to default 20mA!\n");
-+ }
-+ }
-+ else if (debug) {
-+ printk("Loop current set to %dmA!\n",(lim*3)+20);
-+ }
-+ a24xx_spi_setreg(wc_dev,card,LOOP_I_LIMIT,lim);
-+
-+ /* Engage DC-DC converter */
-+ a24xx_spi_setreg(wc_dev, card, 93, 0x19 /* was 0x19 */);
-+#if 0
-+ origjiffies = jiffies;
-+ while(0x80 & opvx_a24xx_spi_getreg(wc_dev, card, 93)) {
-+ if ((jiffies - origjiffies) > 2 * HZ) {
-+ printk("Timeout waiting for DC-DC calibration on module %d\n", card);
-+ return -1;
-+ }
-+ }
-+
-+#if 0
-+ /* Wait a full two seconds */
-+ while((jiffies - origjiffies) < 2 * HZ);
-+
-+ /* Just check to be sure */
-+ vbat = opvx_a24xx_spi_getreg(wc_dev, card, 82);
-+ printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
-+ card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));
-+#endif
-+#endif
-+ return 0;
-+
-+}
-+
-+/*return not OK modules flag*/
-+static int si321x_powerup_proslic_all(struct a24xx_dev *wc_dev, int flag, int fast)
-+{
-+ unsigned long origjiffies;
-+ struct stat{
-+ unsigned char vbat;
-+ unsigned long jifs;
-+ };
-+
-+ struct stat stats[24];
-+ int lim;
-+ int tmp_flag,x;
-+
-+
-+ for(x=0; x < wc_dev->max_cards; x++){
-+ if(flag & (1 << x)){
-+ /* Set period of DC-DC converter to 1/64 khz */
-+ a24xx_spi_setreg(wc_dev, x, 92, 0xff /* was 0xff */);
-+
-+ /* Disable powerdown */
-+ a24xx_spi_setreg(wc_dev, x, 14, 0);
-+
-+ stats[x].vbat = 0;
-+ stats[x].jifs = 0;
-+ }
-+ }
-+
-+ /* Wait for VBat to powerup */
-+ origjiffies = jiffies;
-+
-+ /* If fast, don't bother checking anymore */
-+ if (fast)
-+ return 0;
-+
-+ tmp_flag = flag;
-+ while( ((jiffies - origjiffies) <= HZ/2) && tmp_flag){ /* Wait no more than 500ms */
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(tmp_flag & (1 << x)){
-+ //stats[x].vbat = a24xx_spi_getreg(wc_dev, x, 82);
-+ stats[x].vbat = a24xx_spi_getreg(wc_dev, x, 82);
-+ if(stats[x].vbat >= 0xc0){
-+ stats[x].jifs = jiffies - origjiffies;
-+ tmp_flag &=~(1 << x);
-+ }
-+ }
-+ }
-+ }
-+
-+ for(x=0; x < wc_dev->max_cards; x++){
-+ if(flag & (1 << x)){
-+ if(stats[x].vbat < 0xc0){
-+ if (wc_dev->proslic_power == PROSLIC_POWER_UNKNOWN){
-+ printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE A24xxP??\n",
-+ x, (int)(((jiffies - origjiffies) * 1000 / HZ)),
-+ stats[x].vbat * 375);
-+ }
-+ //wc_dev->proslic_power = PROSLIC_POWER_WARNED;
-+ }
-+ else if(debug){
-+ printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
-+ x, stats[x].vbat * 376 / 1000, stats[x].vbat, (int)((stats[x].jifs * 1000 / HZ)));
-+ }
-+ }
-+ }
-+ if(tmp_flag == flag){
-+ wc_dev->proslic_power = PROSLIC_POWER_WARNED;
-+ return tmp_flag;
-+ }
-+
-+ wc_dev->proslic_power = PROSLIC_POWER_ON;
-+
-+ /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */
-+ /* If out of range, just set it to the default value */
-+ lim = (loopcurrent - 20) / 3;
-+ if ( loopcurrent > 41 ) {
-+ lim = 0;
-+ if (debug) {
-+ printk("Loop current out of range! Setting to default 20mA!\n");
-+ }
-+ }
-+ else if (debug) {
-+ printk("Loop current set to %dmA!\n",(lim*3)+20);
-+ }
-+ flag &= ~tmp_flag;
-+
-+ for(x=0;x < wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ a24xx_spi_setreg(wc_dev,x,LOOP_I_LIMIT,lim);
-+
-+ /* Engage DC-DC converter */
-+ a24xx_spi_setreg(wc_dev, x, 93, 0x19 /* was 0x19 */);
-+ }
-+ }
-+
-+ return tmp_flag;
-+}
-+
-+static int si321x_proslic_insane(struct a24xx_dev *wc_dev, int card)
-+{
-+ int blah,insane_report;
-+ insane_report=0;
-+
-+ blah = a24xx_spi_getreg(wc_dev, card, 0);
-+ if (debug) {
-+ printk("ProSLIC on module %d, product %d, version %d (0x%x)\n", card, (blah & 0x30) >> 4, (blah & 0xf), blah&0xff);
-+ }
-+
-+#if 0
-+ if ((blah & 0x30) >> 4) {
-+ printk("ProSLIC on module %d is not a 3210.\n", card);
-+ return -1;
-+ }
-+#endif
-+ if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) {
-+ /* SLIC not loaded */
-+ return -1;
-+ }
-+ if ((blah & 0xf) < 2) {
-+ printk("ProSLIC 3210 version %d is too old\n", blah & 0xf);
-+ return -1;
-+ }
-+ if (a24xx_spi_getreg(wc_dev, card, 1) & 0x80) {
-+ /* ProSLIC 3215, not a 3210 */
-+ wc_dev->flags[card] |= FLAG_3215;
-+ }
-+
-+ blah = a24xx_spi_getreg(wc_dev, card, 8);
-+ if (blah != 0x2) {
-+ printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah);
-+ return -1;
-+ } else if ( insane_report) {
-+ printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah);
-+ }
-+
-+ blah = a24xx_spi_getreg(wc_dev, card, 64);
-+ if (blah != 0x0) {
-+ printk("ProSLIC on module %d insane (2)\n", card);
-+ return -1;
-+ } else if ( insane_report) {
-+ printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah);
-+ }
-+
-+ blah = a24xx_spi_getreg(wc_dev, card, 11);
-+ if (blah != 0x33) {
-+ printk("ProSLIC on module %d insane (3)\n", card);
-+ return -1;
-+ } else if ( insane_report) {
-+ printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah);
-+ }
-+
-+ /* Just be sure it's setup right. */
-+ a24xx_spi_setreg(wc_dev, card, 30, 0);
-+
-+ if (debug) {
-+ printk("ProSLIC on module %d seems sane.\n", card);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+#if 1
-+static int si321x_proslic_calibrate(struct a24xx_dev *wc_dev, int card)
-+{
-+ unsigned long origjiffies;
-+ int x;
-+ /* Perform all calibrations */
-+ a24xx_spi_setreg(wc_dev, card, 97, 0x1f);
-+
-+ /* Begin, no speedup */
-+ a24xx_spi_setreg(wc_dev, card, 96, 0x5f);
-+
-+ /* Wait for it to finish */
-+ origjiffies = jiffies;
-+ while(a24xx_spi_getreg(wc_dev, card, 96)) {
-+ if ((jiffies - origjiffies) > 2 * HZ) {
-+ printk("Timeout waiting for calibration of module %d\n", card);
-+ return -1;
-+ }
-+ }
-+
-+ if (debug) {
-+ /* Print calibration parameters */
-+ printk("Calibration Vector Regs 98 - 107: \n");
-+ for (x=98;x<108;x++) {
-+ printk("%d: %02x\n", x, a24xx_spi_getreg(wc_dev, card, x));
-+ }
-+ }
-+ return 0;
-+}
-+#endif
-+
-+/*return not OK cards flag*/
-+static int si321x_proslic_calibrate_all(struct a24xx_dev *wc_dev, int flag)
-+{
-+ unsigned long origjiffies;
-+ int i,x,tmp_flag;
-+
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ /* Perform all calibrations */
-+ a24xx_spi_setreg(wc_dev, x, 97, 0x1f);
-+
-+ /* Begin, no speedup */
-+ a24xx_spi_setreg(wc_dev, x, 96, 0x5f);
-+ }
-+ }
-+
-+ /* Wait for it to finish */
-+ origjiffies = jiffies;
-+ tmp_flag = flag;
-+
-+ while(((jiffies - origjiffies) < 2 * HZ) && tmp_flag){
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(tmp_flag & (1 << x)){
-+ if(!a24xx_spi_getreg(wc_dev, x, 96)){
-+ tmp_flag &= ~(1 << x);
-+ }
-+ }
-+ }
-+ }
-+
-+ if (debug) {
-+ /* Print calibration parameters */
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ printk("Calibration Vector Regs 98 - 107: \n");
-+ for (i=98;i<108;i++) {
-+ printk("Module %d %d: %02x\n", x,i, a24xx_spi_getreg(wc_dev, x, i));
-+ }
-+ }
-+ }
-+ }
-+ return tmp_flag;
-+}
-+
-+static int si321x_proslic_powerleak_test(struct a24xx_dev *wc_dev, int card)
-+{
-+ unsigned long origjiffies;
-+ unsigned char vbat;
-+
-+ /* Turn off linefeed */
-+ a24xx_spi_setreg(wc_dev, card, 64, 0);
-+
-+ /* Power down */
-+ a24xx_spi_setreg(wc_dev, card, 14, 0x10);
-+
-+ /* Wait for one second */
-+ origjiffies = jiffies;
-+
-+ while((vbat = a24xx_spi_getreg(wc_dev, card, 82)) > 0x6) {
-+ if ((jiffies - origjiffies) >= (HZ/2)) {
-+ break;
-+ }
-+ }
-+
-+ if (vbat < 0x06) {
-+ printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card,
-+ 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ));
-+ return -1;
-+ } else if (debug) {
-+ printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000);
-+ }
-+ return 0;
-+}
-+
-+/* return OK cards flag*/
-+static int si321x_proslic_powerleak_test_all(struct a24xx_dev *wc_dev, int flag)
-+{
-+ unsigned long origjiffies;
-+ struct stat{
-+ unsigned char vbat;
-+ unsigned long jifs;
-+ };
-+
-+ struct stat stats[24];
-+ int x,tmp_flag=0;
-+
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ /* Turn off linefeed */
-+ a24xx_spi_setreg(wc_dev, x, 64, 0);
-+
-+ /* Power down */
-+ a24xx_spi_setreg(wc_dev, x, 14, 0x10);
-+ }
-+ stats[x].vbat=0;
-+ stats[x].jifs=0;
-+ }
-+
-+ /* Wait for one second */
-+ origjiffies = jiffies;
-+
-+ tmp_flag = flag;
-+ while(((jiffies - origjiffies) < (HZ/2)) && tmp_flag){
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(tmp_flag & (1 << x)){
-+ if((stats[x].vbat = a24xx_spi_getreg(wc_dev, x, 82)) < 0x6){
-+ tmp_flag &= ~(1 << x);
-+ stats[x].jifs = jiffies - origjiffies;
-+ }
-+ }
-+ }
-+ }
-+
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ if (stats[x].vbat < 0x06) {
-+ printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", x,
-+ 376 * stats[x].vbat / 1000, stats[x].vbat, (int)(stats[x].jifs * 1000 / HZ));
-+ } else if (debug) {
-+ printk("Post-leakage voltage: %d volts\n", 376 * stats[x].vbat / 1000);
-+ }
-+ }
-+ }
-+
-+ return tmp_flag;
-+}
-+
-+static int si321x_proslic_manual_calibrate(struct a24xx_dev *wc_dev, int card)
-+{
-+ unsigned long origjiffies;
-+ unsigned char i;
-+
-+ a24xx_spi_setreg(wc_dev, card, 21, 0);//(0) Disable all interupts in DR21
-+ a24xx_spi_setreg(wc_dev, card, 22, 0);//(0)Disable all interupts in DR21
-+ a24xx_spi_setreg(wc_dev, card, 23, 0);//(0)Disable all interupts in DR21
-+ a24xx_spi_setreg(wc_dev, card, 64, 0);//(0)
-+
-+ a24xx_spi_setreg(wc_dev, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration.
-+ a24xx_spi_setreg(wc_dev, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM
-+
-+ origjiffies=jiffies;
-+ while( a24xx_spi_getreg(wc_dev,card,96)!=0 ){
-+ if((jiffies-origjiffies)>80)
-+ return -1;
-+ }
-+ //Initialized DR 98 and 99 to get consistant results.
-+ // 98 and 99 are the results registers and the search should have same intial conditions.
-+
-+ /*******************************The following is the manual gain mismatch calibration****************************/
-+ /*******************************This is also available as a function *******************************************/
-+ // Delay 10ms
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<1);
-+ si321x_proslic_setreg_indirect(wc_dev, card, 88,0);
-+ si321x_proslic_setreg_indirect(wc_dev,card,89,0);
-+ si321x_proslic_setreg_indirect(wc_dev,card,90,0);
-+ si321x_proslic_setreg_indirect(wc_dev,card,91,0);
-+ si321x_proslic_setreg_indirect(wc_dev,card,92,0);
-+ si321x_proslic_setreg_indirect(wc_dev,card,93,0);
-+
-+ a24xx_spi_setreg(wc_dev, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time
-+ a24xx_spi_setreg(wc_dev, card, 99,0x10);
-+
-+ for ( i=0x1f; i>0; i--) {
-+ a24xx_spi_setreg(wc_dev, card, 98,i);
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<4);
-+ if((a24xx_spi_getreg(wc_dev,card,88)) == 0)
-+ break;
-+ } // for
-+
-+ for ( i=0x1f; i>0; i--) {
-+ a24xx_spi_setreg(wc_dev, card, 99,i);
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<4);
-+ if((a24xx_spi_getreg(wc_dev,card,89)) == 0)
-+ break;
-+ }//for
-+
-+ /*******************************The preceding is the manual gain mismatch calibration****************************/
-+ /**********************************The following is the longitudinal Balance Cal***********************************/
-+ a24xx_spi_setreg(wc_dev,card,64,1);
-+ while((jiffies-origjiffies)<10); // Sleep 100?
-+
-+ a24xx_spi_setreg(wc_dev, card, 64, 0);
-+ a24xx_spi_setreg(wc_dev, card, 23, 0x4); // enable interrupt for the balance Cal
-+ a24xx_spi_setreg(wc_dev, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration
-+ a24xx_spi_setreg(wc_dev, card, 96,0x40);
-+
-+ a24xx_spi_getreg(wc_dev,card,96); /* Read Reg 96 just cause */
-+
-+ a24xx_spi_setreg(wc_dev, card, 21, 0xFF);
-+ a24xx_spi_setreg(wc_dev, card, 22, 0xFF);
-+ a24xx_spi_setreg(wc_dev, card, 23, 0xFF);
-+
-+ /**The preceding is the longitudinal Balance Cal***/
-+ return(0);
-+
-+}
-+
-+/*return not OK cards flag*/
-+static int si321x_proslic_manual_calibrate_all(struct a24xx_dev *wc_dev, int flag)
-+{
-+ unsigned long origjiffies;
-+ unsigned char i;
-+ int x,tmp_flag;
-+
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ a24xx_spi_setreg(wc_dev, x, 21, 0);//(0) Disable all interupts in DR21
-+ a24xx_spi_setreg(wc_dev, x, 22, 0);//(0)Disable all interupts in DR21
-+ a24xx_spi_setreg(wc_dev, x, 23, 0);//(0)Disable all interupts in DR21
-+ a24xx_spi_setreg(wc_dev, x, 64, 0);//(0)
-+
-+ a24xx_spi_setreg(wc_dev, x, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration.
-+ a24xx_spi_setreg(wc_dev, x, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM
-+ }
-+ }
-+
-+ origjiffies=jiffies;
-+
-+ /*remove not OK cards flag*/
-+ tmp_flag = flag;
-+ while(((jiffies-origjiffies)< 80) && tmp_flag){
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(tmp_flag & (1 << x)){
-+ if(a24xx_spi_getreg(wc_dev,x,96) == 0){
-+ tmp_flag &= ~(1 << x);
-+ }
-+ }
-+ }
-+ }
-+
-+ flag &= ~tmp_flag;
-+
-+ //Initialized DR 98 and 99 to get consistant results.
-+ // 98 and 99 are the results registers and the search should have same intial conditions.
-+
-+ /*******************************The following is the manual gain mismatch calibration****************************/
-+ /*******************************This is also available as a function *******************************************/
-+ // Delay 10ms
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<1);
-+
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ si321x_proslic_setreg_indirect(wc_dev,x,88,0);
-+ si321x_proslic_setreg_indirect(wc_dev,x,89,0);
-+ si321x_proslic_setreg_indirect(wc_dev,x,90,0);
-+ si321x_proslic_setreg_indirect(wc_dev,x,91,0);
-+ si321x_proslic_setreg_indirect(wc_dev,x,92,0);
-+ si321x_proslic_setreg_indirect(wc_dev,x,93,0);
-+
-+ a24xx_spi_setreg(wc_dev, x, 98,0x10); // This is necessary if the calibration occurs other than at reset time
-+ a24xx_spi_setreg(wc_dev, x, 99,0x10);
-+
-+ for ( i=0x1f; i>0; i--) {
-+ a24xx_spi_setreg(wc_dev, x, 98,i);
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<4);
-+ if((a24xx_spi_getreg(wc_dev,x,88)) == 0)
-+ break;
-+ } // for
-+
-+ for ( i=0x1f; i>0; i--) {
-+ a24xx_spi_setreg(wc_dev, x, 99,i);
-+ origjiffies=jiffies;
-+ while((jiffies-origjiffies)<4);
-+ if((a24xx_spi_getreg(wc_dev,x,89)) == 0)
-+ break;
-+ }//for
-+
-+ /*******************************The preceding is the manual gain mismatch calibration****************************/
-+ /**********************************The following is the longitudinal Balance Cal***********************************/
-+ a24xx_spi_setreg(wc_dev,x,64,1);
-+ }
-+ }
-+
-+ while((jiffies-origjiffies)<10); // Sleep 100?
-+
-+ for(x=0;x<wc_dev->max_cards;x++){
-+ if(flag & (1 << x)){
-+ a24xx_spi_setreg(wc_dev, x, 64, 0);
-+ a24xx_spi_setreg(wc_dev, x, 23, 0x4); // enable interrupt for the balance Cal
-+ a24xx_spi_setreg(wc_dev, x, 97, 0x1); // this is a singular calibration bit for longitudinal calibration
-+ a24xx_spi_setreg(wc_dev, x, 96,0x40);
-+
-+ a24xx_spi_getreg(wc_dev,x,96); /* Read Reg 96 just cause */
-+
-+ a24xx_spi_setreg(wc_dev, x, 21, 0xFF);
-+ a24xx_spi_setreg(wc_dev, x, 22, 0xFF);
-+ a24xx_spi_setreg(wc_dev, x, 23, 0xFF);
-+ }
-+ }
-+
-+ /**The preceding is the longitudinal Balance Cal***/
-+ return tmp_flag;
-+}
-+
-+static int si321x_proslic_verify_indirect_regs(struct a24xx_dev *wc_dev, int card)
-+{
-+ int passed = 1;
-+ unsigned short i, initial;
-+ int j;
-+
-+ for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++) {
-+ if((j = si321x_proslic_getreg_indirect(wc_dev, card, (unsigned char) indirect_regs[i].address)) < 0) {
-+ printk("Failed to read indirect register %d\n", i);
-+ return -1;
-+ }
-+ initial= indirect_regs[i].initial;
-+
-+ if ( j != initial && (!(wc_dev->flags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) {
-+ printk("!!!!!!! %s iREG %X = %X should be %X\n",
-+ indirect_regs[i].name,indirect_regs[i].address,j,initial );
-+ passed = 0;
-+ }
-+ }
-+
-+ if (passed) {
-+ if (debug) {
-+ printk("Init Indirect Registers completed successfully.\n");
-+ }
-+ } else {
-+ printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n");
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static int si321x_proslic_init_indirect_regs(struct a24xx_dev *wc_dev, int card)
-+{
-+ unsigned char i;
-+
-+ for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++) {
-+ if(si321x_proslic_setreg_indirect(wc_dev, card, indirect_regs[i].address,indirect_regs[i].initial)) {
-+ return -1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int si321x_set_ring_generator_mode(struct a24xx_dev *wc_dev, int card, int mode)
-+{
-+ int reg20, reg21, reg74; /* RCO, RNGX, VBATH */
-+ struct fxs *const fxs = &wc_dev->mod[card].fxs;
-+
-+ fxs->neonringing = mode; /* track ring generator mode */
-+
-+ if (mode) { /* Neon */
-+ if (debug)
-+ printk(KERN_DEBUG "NEON ring on chan %d, "
-+ "lasttxhook was 0x%x\n", card, fxs->lasttxhook);
-+ /* Must be in FORWARD ACTIVE before setting ringer */
-+ fxs->lasttxhook = SLIC_LF_ACTIVE_FWD;
-+ a24xx_spi_setreg(wc_dev, card, LINE_STATE, fxs->lasttxhook);
-+
-+ si321x_proslic_setreg_indirect(wc_dev, card, 22,
-+ NEON_MWI_RNGY_PULSEWIDTH);
-+ si321x_proslic_setreg_indirect(wc_dev, card, 21,
-+ 0x7bef); /* RNGX (91.5Vpk) */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 20,
-+ 0x009f); /* RCO (RNGX, t rise)*/
-+
-+ a24xx_spi_setreg(wc_dev, card, 34, 0x19); /* Ringing Osc. Control */
-+ a24xx_spi_setreg(wc_dev, card, 74, 0x3f); /* VBATH 94.5V */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 29, 0x4600); /* RPTP */
-+ /* A write of 0x04 to register 64 will turn on the VM led */
-+ } else {
-+ a24xx_spi_setreg(wc_dev, card, 34, 0x00); /* Ringing Osc. Control */
-+ /* RNGY Initial Phase */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 22, 0x0000);
-+ si321x_proslic_setreg_indirect(wc_dev, card, 29, 0x3600); /* RPTP */
-+ /* A write of 0x04 to register 64 will turn on the ringer */
-+
-+ if (fastringer) {
-+ /* Speed up Ringer */
-+ reg20 = 0x7e6d;
-+ reg74 = 0x32; /* Default */
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ reg74 = 0x3f;
-+ reg21 = 0x0247; /* RNGX */
-+ if (debug)
-+ printk(KERN_DEBUG "Boosting fast ringer"
-+ " on chan %d (89V peak)\n",
-+ card);
-+ } else if (lowpower) {
-+ reg21 = 0x014b; /* RNGX */
-+ if (debug)
-+ printk(KERN_DEBUG "Reducing fast ring "
-+ "power on chan %d (50V peak)\n",
-+ card);
-+ } else if (fxshonormode &&
-+ fxo_modes[_opermode].ring_x) {
-+ reg21 = fxo_modes[_opermode].ring_x;
-+ if (debug)
-+ printk(KERN_DEBUG "fxshonormode: fast "
-+ "ring_x power on chan %d\n",
-+ card);
-+ } else {
-+ reg21 = 0x01b9;
-+ if (debug)
-+ printk(KERN_DEBUG "Speeding up ringer "
-+ "on chan %d (25Hz)\n",
-+ card);
-+ }
-+ /* VBATH */
-+ a24xx_spi_setreg(wc_dev, card, 74, reg74);
-+ /*RCO*/
-+ si321x_proslic_setreg_indirect(wc_dev, card, 20, reg20);
-+ /*RNGX*/
-+ si321x_proslic_setreg_indirect(wc_dev, card, 21, reg21);
-+
-+ } else {
-+ /* Ringer Speed */
-+ if (fxshonormode && fxo_modes[_opermode].ring_osc) {
-+ reg20 = fxo_modes[_opermode].ring_osc;
-+ if (debug)
-+ printk(KERN_DEBUG "fxshonormode: "
-+ "ring_osc speed on chan %d\n",
-+ card);
-+ } else {
-+ reg20 = 0x7ef0; /* Default */
-+ }
-+
-+ reg74 = 0x32; /* Default */
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ reg74 = 0x3f;
-+ reg21 = 0x1d1;
-+ if (debug)
-+ printk(KERN_DEBUG "Boosting ringer on "
-+ "chan %d (89V peak)\n",
-+ card);
-+ } else if (lowpower) {
-+ reg21 = 0x108;
-+ if (debug)
-+ printk(KERN_DEBUG "Reducing ring power "
-+ "on chan %d (50V peak)\n",
-+ card);
-+ } else if (fxshonormode &&
-+ fxo_modes[_opermode].ring_x) {
-+ reg21 = fxo_modes[_opermode].ring_x;
-+ if (debug)
-+ printk(KERN_DEBUG "fxshonormode: ring_x"
-+ " power on chan %d\n",
-+ card);
-+ } else {
-+ reg21 = 0x160;
-+ if (debug)
-+ printk(KERN_DEBUG "Normal ring power on"
-+ " chan %d\n",
-+ card);
-+ }
-+ /* VBATH */
-+ a24xx_spi_setreg(wc_dev, card, 74, reg74);
-+ /* RCO */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 20, reg20);
-+ /* RNGX */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 21, reg21);
-+ }
-+ }
-+ return 0;
-+}
-+
-+int si321x_init_ring_generator_mode(struct a24xx_dev *wc_dev, int card){
-+ a24xx_spi_setreg(wc_dev, card, 34, 0x00); /* Ringing Osc. Control */
-+ /* neon trapezoid timers */
-+ a24xx_spi_setreg(wc_dev, card, 48, 0xe0); /* Active Timer low byte */
-+ a24xx_spi_setreg(wc_dev, card, 49, 0x01); /* Active Timer high byte */
-+ a24xx_spi_setreg(wc_dev, card, 50, 0xF0); /* Inactive Timer low byte */
-+ a24xx_spi_setreg(wc_dev, card, 51, 0x05); /* Inactive Timer high byte */
-+
-+ si321x_set_ring_generator_mode(wc_dev, card, 0);
-+
-+ return 0;
-+}
-+
-+int si321x_init_proslic(struct a24xx_dev *wc_dev, int card, int fast, int manual, int sane)
-+{
-+ unsigned short tmp[5];
-+ unsigned char r19, r9;
-+ int x;
-+ int fxsmode=0;
-+
-+ /* Sanity check the ProSLIC */
-+ if (!sane && si321x_proslic_insane(wc_dev, card)) {
-+ return -2;
-+ }
-+
-+ /* default messages to none and method to FSK */
-+ memset(&wc_dev->mod[card].fxs.vmwisetting, 0, sizeof(wc_dev->mod[card].fxs.vmwisetting));
-+ wc_dev->mod[card].fxs.vmwi_lrev = 0;
-+ wc_dev->mod[card].fxs.vmwi_hvdc = 0;
-+ wc_dev->mod[card].fxs.vmwi_hvac = 0;
-+
-+ /* By default, don't send on hook */
-+ if (reversepolarity) {
-+ wc_dev->mod[card].fxs.idletxhookstate = 5;
-+ } else {
-+ wc_dev->mod[card].fxs.idletxhookstate = 1;
-+ }
-+
-+ if (sane) {
-+ /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */
-+ a24xx_spi_setreg(wc_dev, card, 14, 0x10);
-+ }
-+
-+ if (si321x_proslic_init_indirect_regs(wc_dev, card)) {
-+ printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card);
-+ return -1;
-+ }
-+
-+ /* Clear scratch pad area */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 97,0);
-+
-+ /* Clear digital loopback */
-+ a24xx_spi_setreg(wc_dev, card, 8, 0);
-+
-+ /* Revision C optimization */
-+ a24xx_spi_setreg(wc_dev, card, 108, 0xeb);
-+
-+ /* Disable automatic VBat switching for safety to prevent
-+ Q7 from accidently turning on and burning out. */
-+ a24xx_spi_setreg(wc_dev, card, 67, 0x07); /* Note, if pulse dialing has problems at high REN loads
-+ change this to 0x17 */
-+
-+ /* Turn off Q7 */
-+ a24xx_spi_setreg(wc_dev, card, 66, 1);
-+
-+ /* Flush ProSLIC digital filters by setting to clear, while
-+ saving old values */
-+ for (x=0;x<5;x++) {
-+ tmp[x] = si321x_proslic_getreg_indirect(wc_dev, card, x + 35);
-+ si321x_proslic_setreg_indirect(wc_dev, card, x + 35, 0x8000);
-+ }
-+
-+ /* Power up the DC-DC converter */
-+ if (si321x_powerup_proslic(wc_dev, card, fast)) { ////////////****************
-+ printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card);
-+ return -1;
-+ }
-+
-+ if (!fast) {
-+ /* Check for power leaks */
-+ if (si321x_proslic_powerleak_test(wc_dev, card)) {///////****************
-+ printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card);
-+ }
-+ /* Power up again */
-+ if (si321x_powerup_proslic(wc_dev, card, fast)) { ////////////****************
-+ printk("Unable to do FINAL ProSLIC powerup on module %d\n", card);
-+ return -1;
-+ }
-+#ifndef NO_CALIBRATION
-+ /* Perform calibration */
-+ if(manual) {
-+ if (si321x_proslic_manual_calibrate(wc_dev, card)) { //////////****************
-+ //printk("Proslic failed on Manual Calibration\n");
-+ if (si321x_proslic_manual_calibrate(wc_dev, card)) { ////////////****************
-+ printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n");
-+ return -1;
-+ }
-+ printk("Proslic Passed Manual Calibration on Second Attempt\n");
-+ }
-+ }
-+ else {
-+ if(si321x_proslic_calibrate(wc_dev, card)) { ///////****************
-+ //printk("ProSlic died on Auto Calibration.\n");
-+ if (si321x_proslic_calibrate(wc_dev, card)) { ////////////****************
-+ printk("Proslic Failed on Second Attempt to Auto Calibrate\n");
-+ return -1;
-+ }
-+ printk("Proslic Passed Auto Calibration on Second Attempt\n");
-+ }
-+ }
-+ /* Perform DC-DC calibration */
-+ a24xx_spi_setreg(wc_dev, card, 93, 0x99);
-+ r19 = a24xx_spi_getreg(wc_dev, card, 107);
-+ if ((r19 < 0x2) || (r19 > 0xd)) {
-+ printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19);
-+ a24xx_spi_setreg(wc_dev, card, 107, 0x8);
-+ }
-+
-+ /* Save calibration vectors */
-+ for (x=0;x<NUM_CAL_REGS;x++) {
-+ wc_dev->mod[card].fxs.calregs.vals[x] = a24xx_spi_getreg(wc_dev, card, 96 + x);
-+ }
-+#endif
-+
-+ } else {
-+ /* Restore calibration registers */
-+ for (x=0;x<NUM_CAL_REGS;x++) {
-+ a24xx_spi_setreg(wc_dev, card, 96 + x, wc_dev->mod[card].fxs.calregs.vals[x]);
-+ }
-+ }
-+ /* Calibration complete, restore original values */
-+ for (x=0;x<5;x++) {
-+ si321x_proslic_setreg_indirect(wc_dev, card, x + 35, tmp[x]);
-+ }
-+
-+ if (si321x_proslic_verify_indirect_regs(wc_dev, card)) {
-+ printk(KERN_INFO "Indirect Registers failed verification.\n");
-+ return -1;
-+ }
-+
-+
-+#if 0
-+ /* Disable Auto Power Alarm Detect and other "features" */
-+ a24xx_spi_setreg(wc_dev, card, 67, 0x0e);
-+ blah = opvx_a24xx_spi_getreg(wc_dev, card, 67);
-+#endif
-+
-+#if 0
-+ if (si321x_proslic_setreg_indirect(wc_dev, card, 97, 0x0)) { // Stanley: for the bad recording fix
-+ printk(KERN_INFO "ProSlic IndirectReg Died.\n");
-+ return -1;
-+ }
-+#endif
-+
-+ if (alawoverride) {
-+ a24xx_spi_setreg(wc_dev, card, 1, 0x20);
-+ } else {
-+ a24xx_spi_setreg(wc_dev, card, 1, 0x28);
-+ }
-+ // U-Law 8-bit interface
-+ a24xx_spi_setreg(wc_dev, card, 2, (card%4) * 8 + (card/4) * 32); // Tx Start count low byte 0
-+ a24xx_spi_setreg(wc_dev, card, 3, 0); // Tx Start count high byte 0
-+ a24xx_spi_setreg(wc_dev, card, 4, (card%4) * 8 + (card/4) * 32); // Rx Start count low byte 0
-+ a24xx_spi_setreg(wc_dev, card, 5, 0); // Rx Start count high byte 0
-+ a24xx_spi_setreg(wc_dev, card, 18, 0xff); // clear all interrupt
-+ a24xx_spi_setreg(wc_dev, card, 19, 0xff);
-+ a24xx_spi_setreg(wc_dev, card, 20, 0xff);
-+ a24xx_spi_setreg(wc_dev, card, 73, 0x04);
-+ if (fxshonormode) {
-+ fxsmode = acim2tiss[fxo_modes[_opermode].acim];
-+ a24xx_spi_setreg(wc_dev, card, 10, 0x08 | fxsmode);
-+ if (fxo_modes[_opermode].ring_osc) {
-+ si321x_proslic_setreg_indirect(wc_dev, card, 20, fxo_modes[_opermode].ring_osc);
-+ }
-+ if (fxo_modes[_opermode].ring_x) {
-+ si321x_proslic_setreg_indirect(wc_dev, card, 21, fxo_modes[_opermode].ring_x);
-+ }
-+ }
-+ if (lowpower) {
-+ a24xx_spi_setreg(wc_dev, card, 72, 0x10);
-+ }
-+
-+#if 0
-+ a24xx_spi_setreg(wc_dev, card, 21, 0x00); // enable interrupt
-+ a24xx_spi_setreg(wc_dev, card, 22, 0x02); // Loop detection interrupt
-+ a24xx_spi_setreg(wc_dev, card, 23, 0x01); // DTMF detection interrupt
-+#endif
-+
-+#if 0
-+ /* Enable loopback */
-+ a24xx_spi_setreg(wc_dev, card, 8, 0x2);
-+ a24xx_spi_setreg(wc_dev, card, 14, 0x0);
-+ a24xx_spi_setreg(wc_dev, card, 64, 0x0);
-+ a24xx_spi_setreg(wc_dev, card, 1, 0x08);
-+#endif
-+
-+ if (fastringer) {
-+ /* Speed up Ringer */
-+ si321x_proslic_setreg_indirect(wc_dev, card, 20, 0x7e6d);
-+ si321x_proslic_setreg_indirect(wc_dev, card, 21, 0x01b9);
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ a24xx_spi_setreg(wc_dev, card, 74, 0x3f);
-+ if (si321x_proslic_setreg_indirect(wc_dev, card, 21, 0x247)) {
-+ return -1;
-+ }
-+ printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1);
-+ } else if (lowpower) {
-+ if (si321x_proslic_setreg_indirect(wc_dev, card, 21, 0x14b)) {
-+ return -1;
-+ }
-+ printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1);
-+ } else {
-+ printk("Speeding up ringer on slot %d (25Hz)\n", card + 1);
-+ }
-+ } else {
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ a24xx_spi_setreg(wc_dev, card, 74, 0x3f);
-+ if (si321x_proslic_setreg_indirect(wc_dev, card, 21, 0x1d1)) {
-+ return -1;
-+ }
-+ printk("Boosting ringer on slot %d (89V peak)\n", card + 1);
-+ } else if (lowpower) {
-+ if (si321x_proslic_setreg_indirect(wc_dev, card, 21, 0x108)) {
-+ return -1;
-+ }
-+ printk("Reducing ring power on slot %d (50V peak)\n", card + 1);
-+ }
-+ }
-+ if (si321x_init_ring_generator_mode(wc_dev, card)) {
-+ return -1;
-+ }
-+ if(fxstxgain || fxsrxgain) {
-+ r9 = a24xx_spi_getreg(wc_dev, card, 9);
-+ switch (fxstxgain) {
-+ case 35:
-+ r9+=8;
-+ break;
-+ case -35:
-+ r9+=4;
-+ break;
-+ case 0:
-+ break;
-+ }
-+
-+ switch (fxsrxgain) {
-+ case 35:
-+ r9+=2;
-+ break;
-+ case -35:
-+ r9+=1;
-+ break;
-+ case 0:
-+ break;
-+ }
-+ a24xx_spi_setreg(wc_dev,card,9,r9);
-+ }
-+
-+ if(debug) {
-+ printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",
-+ ((a24xx_spi_getreg(wc_dev, card, 9)/8) == 1) ? "3.5":
-+ (((a24xx_spi_getreg(wc_dev, card, 9)/4) == 1) ? "-3.5":"0.0"),
-+ ((a24xx_spi_getreg(wc_dev, card, 9)/2) == 1) ?"3.5":((a24xx_spi_getreg(wc_dev,card,9)%2) ? "-3.5":"0.0")
-+ );
-+ }
-+
-+ a24xx_spi_setreg(wc_dev, card, 64, 0x01);
-+
-+ return 0;
-+}
-+
-+/***
-+*return
-+ ret_flag : not OK cards flag
-+ blk_flag : not installed cards flag
-+***/
-+int si321x_init_proslic_all(struct a24xx_dev *wc_dev, int fxs_flag,int fast, int manual, int sane,int *blk_flag)
-+{
-+ int flag=fxs_flag,tmp_flag=0,ret_flag=0;
-+ unsigned short tmp[24][5];
-+ unsigned char r19, r9;
-+ int x,i;
-+ int fxsmode=0;
-+
-+
-+ for(i=0;i<wc_dev->max_cards;i++)
-+ {
-+ if(flag & (1 << i)){
-+ if((i%4) == 0){
-+ __a24xx_setcard(wc_dev, i);
-+ __opvx_a24xx_write_8bits(wc_dev->mem32, 0x00);
-+ __opvx_a24xx_write_8bits(wc_dev->mem32, 0x80);
-+ }
-+
-+ /* Sanity check the ProSLIC */
-+ if (!sane && si321x_proslic_insane(wc_dev, i)) {
-+ tmp_flag |= 1<<i;
-+ continue;
-+ }
-+
-+ /* default messages to none and method to FSK */
-+ memset(&wc_dev->mod[i].fxs.vmwisetting, 0, sizeof(wc_dev->mod[i].fxs.vmwisetting));
-+ wc_dev->mod[i].fxs.vmwi_lrev = 0;
-+ wc_dev->mod[i].fxs.vmwi_hvdc = 0;
-+ wc_dev->mod[i].fxs.vmwi_hvac = 0;
-+
-+ /* By default, don't send on hook */
-+ if (reversepolarity) {
-+ wc_dev->mod[i].fxs.idletxhookstate = 5;
-+ } else {
-+ wc_dev->mod[i].fxs.idletxhookstate = 1;
-+ }
-+
-+ if (sane) {
-+ /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */
-+ a24xx_spi_setreg(wc_dev, i, 14, 0x10);
-+ }
-+
-+ if (si321x_proslic_init_indirect_regs(wc_dev, i)) {
-+ printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", i);
-+ tmp_flag |= 1<<i;
-+ continue;
-+ }
-+
-+ /* Clear scratch pad area */
-+ si321x_proslic_setreg_indirect(wc_dev, i, 97,0);
-+
-+ /* Clear digital loopback */
-+ a24xx_spi_setreg(wc_dev, i, 8, 0);
-+
-+ /* Revision C optimization */
-+ a24xx_spi_setreg(wc_dev, i, 108, 0xeb);
-+
-+ /* Disable automatic VBat switching for safety to prevent
-+ Q7 from accidently turning on and burning out. */
-+ a24xx_spi_setreg(wc_dev, i, 67, 0x07); /* Note, if pulse dialing has problems at high REN loads
-+ change this to 0x17 */
-+
-+ /* Turn off Q7 */
-+ a24xx_spi_setreg(wc_dev, i, 66, 1);
-+
-+ /* Flush ProSLIC digital filters by setting to clear, while
-+ saving old values */
-+ for (x=0;x<5;x++) {
-+ tmp[i][x] = si321x_proslic_getreg_indirect(wc_dev, i, x + 35);
-+ si321x_proslic_setreg_indirect(wc_dev, i, x + 35, 0x8000);
-+ }
-+ }
-+ }
-+
-+ /*remove not installed cards*/
-+ flag &= ~(tmp_flag);
-+ if(blk_flag)
-+ *blk_flag = tmp_flag;
-+
-+
-+ touch_softlockup_watchdog();
-+
-+ /* Power up the DC-DC converter */
-+ tmp_flag = si321x_powerup_proslic_all(wc_dev, flag, fast);
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if(tmp_flag & (1 << i))
-+ printk("Unable to do INITIAL ProSLIC powerup on module %d\n",i);
-+ }
-+
-+ /*remove not OK cards flag*/
-+ flag &= ~(tmp_flag);
-+ ret_flag |= tmp_flag;
-+
-+
-+ if (!fast){
-+ /* Check for power leaks */
-+ tmp_flag=si321x_proslic_powerleak_test_all(wc_dev,flag);
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if( (flag & (1 << i)) && !(tmp_flag & (1 << i)) ){
-+ printk("ProSLIC module %d failed leakage test. Check for short circuit\n", i);
-+ }
-+ }
-+
-+ /* Power up again */
-+ tmp_flag = si321x_powerup_proslic_all(wc_dev, flag, fast);
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if(tmp_flag & (1 << i))
-+ printk("Unable to do FINAL ProSLIC powerup on module %d\n",i);
-+ }
-+
-+ /*remove not OK cards flag*/
-+ flag &= ~(tmp_flag);
-+ ret_flag |= tmp_flag;
-+
-+#ifndef NO_CALIBRATION
-+ if(manual) {
-+ tmp_flag = si321x_proslic_manual_calibrate_all(wc_dev,flag);
-+ if(tmp_flag){
-+ tmp_flag = si321x_proslic_manual_calibrate_all(wc_dev,tmp_flag);
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if(flag & (1 << i)){
-+ if(tmp_flag & (1 << i))
-+ printk("Proslic Failed on Second Attempt to Calibrate Manually module %d . (Try -DNO_CALIBRATION in Makefile)\n",i);
-+ else
-+ printk("Proslic Passed Manual Calibration on Second Attempt on module %d \n",i);