summarylogtreecommitdiffstats
path: root/dahdi-linux-2.10.1-openvox-2.patch
diff options
context:
space:
mode:
authorMaik Broemme2015-10-04 21:51:11 +0200
committerMaik Broemme2015-10-04 21:51:11 +0200
commit205e1524de216b894a99a525a9cd45f49a6d2119 (patch)
treed6683bbd43e65fe52c986a349662aff443c5c60b /dahdi-linux-2.10.1-openvox-2.patch
parent126ae972e89a76accea7bcc79972ae8f72c17ab3 (diff)
downloadaur-205e1524de216b894a99a525a9cd45f49a6d2119.tar.gz
Removed no longer needed patches
Diffstat (limited to 'dahdi-linux-2.10.1-openvox-2.patch')
-rw-r--r--dahdi-linux-2.10.1-openvox-2.patch5851
1 files changed, 0 insertions, 5851 deletions
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 3be86e27c9a4..000000000000
--- 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);
-+ }
-+ }
-+ }
-+ }else{
-+ tmp_flag = si321x_proslic_calibrate_all(wc_dev,flag);
-+ if(tmp_flag){
-+ tmp_flag = si321x_proslic_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 Auto Calibrate module %d . (Try -DNO_CALIBRATION in Makefile)\n",i);
-+ else
-+ printk("Proslic Passed Auto Calibration on Second Attempt on module %d \n",i);
-+ }
-+ }
-+ }
-+ }
-+
-+ /*remove not OK cards flag*/
-+ flag &= ~(tmp_flag);
-+ ret_flag |= tmp_flag;
-+
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if(flag & (1 << i)){
-+ /* Perform DC-DC calibration */
-+ a24xx_spi_setreg(wc_dev, i, 93, 0x99);
-+ r19 = a24xx_spi_getreg(wc_dev, i, 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, i, 107, 0x8);
-+ }
-+ /* Save calibration vectors */
-+ for (x=0;x<NUM_CAL_REGS;x++) {
-+ wc_dev->mod[i].fxs.calregs.vals[x] = a24xx_spi_getreg(wc_dev, i, 96 + x);
-+ }
-+ }
-+ }
-+#endif
-+ }else{
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if(flag & (1 << i)){
-+ /* Restore calibration registers */
-+ for (x=0;x<NUM_CAL_REGS;x++) {
-+ a24xx_spi_setreg(wc_dev, i, 96 + x, wc_dev->mod[i].fxs.calregs.vals[x]);
-+ }
-+ }
-+ }
-+ }
-+
-+ tmp_flag = 0;
-+ for(i=0;i<wc_dev->max_cards;i++){
-+ if(flag & (1 << i)){
-+ /* Calibration complete, restore original values */
-+ for (x=0;x<5;x++) {
-+ si321x_proslic_setreg_indirect(wc_dev, i, x + 35, tmp[i][x]);
-+ }
-+
-+ if (si321x_proslic_verify_indirect_regs(wc_dev, i)) {
-+ printk(KERN_INFO "Indirect Registers failed verification on module %d.\n",i);
-+ tmp_flag |=(1<<i);
-+ continue;
-+ }
-+
-+
-+ if (alawoverride) {
-+ a24xx_spi_setreg(wc_dev, i, 1, 0x20);
-+ } else {
-+ a24xx_spi_setreg(wc_dev, i, 1, 0x28);
-+ }
-+ // U-Law 8-bit interface
-+ a24xx_spi_setreg(wc_dev, i, 2, (i%4) * 8 + (i/4) * 32); // Tx Start count low byte 0
-+ a24xx_spi_setreg(wc_dev, i, 3, 0); // Tx Start count high byte 0
-+ a24xx_spi_setreg(wc_dev, i, 4, (i%4) * 8 + (i/4) * 32); // Rx Start count low byte 0
-+ a24xx_spi_setreg(wc_dev, i, 5, 0); // Rx Start count high byte 0
-+ a24xx_spi_setreg(wc_dev, i, 18, 0xff); // clear all interrupt
-+ a24xx_spi_setreg(wc_dev, i, 19, 0xff);
-+ a24xx_spi_setreg(wc_dev, i, 20, 0xff);
-+ a24xx_spi_setreg(wc_dev, i, 73, 0x04);
-+ if (fxshonormode) {
-+ fxsmode = acim2tiss[fxo_modes[_opermode].acim];
-+ a24xx_spi_setreg(wc_dev, i, 10, 0x08 | fxsmode);
-+ if (fxo_modes[_opermode].ring_osc) {
-+ si321x_proslic_setreg_indirect(wc_dev, i, 20, fxo_modes[_opermode].ring_osc);
-+ }
-+ if (fxo_modes[_opermode].ring_x) {
-+ si321x_proslic_setreg_indirect(wc_dev, i, 21, fxo_modes[_opermode].ring_x);
-+ }
-+ }
-+ if (lowpower) {
-+ a24xx_spi_setreg(wc_dev, i, 72, 0x10);
-+ }
-+
-+ if (fastringer) {
-+ /* Speed up Ringer */
-+ si321x_proslic_setreg_indirect(wc_dev, i, 20, 0x7e6d);
-+ si321x_proslic_setreg_indirect(wc_dev, i, 21, 0x01b9);
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ a24xx_spi_setreg(wc_dev, i, 74, 0x3f);
-+ if (si321x_proslic_setreg_indirect(wc_dev, i, 21, 0x247)) {
-+ tmp_flag |=(1<<i);
-+ continue;
-+ }
-+ printk("Boosting fast ringer on slot %d (89V peak)\n", i + 1);
-+ } else if (lowpower) {
-+ if (si321x_proslic_setreg_indirect(wc_dev, i, 21, 0x14b)) {
-+ tmp_flag |=(1<<i);
-+ continue;
-+ }
-+ printk("Reducing fast ring power on slot %d (50V peak)\n", i + 1);
-+ } else {
-+ printk("Speeding up ringer on slot %d (25Hz)\n", i + 1);
-+ }
-+ } else {
-+ /* Beef up Ringing voltage to 89V */
-+ if (boostringer) {
-+ a24xx_spi_setreg(wc_dev, i, 74, 0x3f);
-+ if (si321x_proslic_setreg_indirect(wc_dev, i, 21, 0x1d1)) {
-+ tmp_flag |=(1<<i);
-+ continue;
-+ }
-+ printk("Boosting ringer on slot %d (89V peak)\n", i + 1);
-+ } else if (lowpower) {
-+ if (si321x_proslic_setreg_indirect(wc_dev, i, 21, 0x108)) {
-+ tmp_flag |=(1<<i);
-+ continue;
-+ }
-+ printk("Reducing ring power on slot %d (50V peak)\n", i + 1);
-+ }
-+ }
-+
-+ if (si321x_init_ring_generator_mode(wc_dev, i)) {
-+ tmp_flag |=(1<<i);
-+ continue;
-+ }
-+
-+ if(fxstxgain || fxsrxgain) {
-+ r9 = a24xx_spi_getreg(wc_dev, i, 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,i,9,r9);
-+ }
-+
-+ if(debug) {
-+ printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",
-+ ((a24xx_spi_getreg(wc_dev, i, 9)/8) == 1) ? "3.5":
-+ (((a24xx_spi_getreg(wc_dev, i, 9)/4) == 1) ? "-3.5":"0.0"),
-+ ((a24xx_spi_getreg(wc_dev, i, 9)/2) == 1) ?"3.5":((a24xx_spi_getreg(wc_dev,i,9)%2) ? "-3.5":"0.0")
-+ );
-+ }
-+
-+ a24xx_spi_setreg(wc_dev, i, 64, 0x01);
-+ }
-+ }
-+ ret_flag |= tmp_flag;
-+
-+ return ret_flag;
-+}
-+
-+int si321x_proslic_setreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address, unsigned short data)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ ret = __a24xx_proslic_setreg_indirect(wc_dev, card, address, data);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+
-+ return ret;
-+}
-+
-+int si321x_proslic_getreg_indirect(struct a24xx_dev *wc_dev, int card, unsigned char address)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ spin_lock_irqsave(&wc_dev->lock, flags);
-+ ret = __a24xx_proslic_getreg_indirect(wc_dev, card, address);
-+ spin_unlock_irqrestore(&wc_dev->lock, flags);
-+
-+ return ret;
-+}
-+
-+void si321x_proslic_recheck_sanity(struct a24xx_dev *wc_dev, int card)
-+{
-+ int res;
-+
-+ /* Check loopback */
-+ res = wc_dev->reg1shadow[card];
-+ if (!res && (res != wc_dev->mod[card].fxs.lasttxhook)) // read real state from register By wx
-+ res=a24xx_spi_getreg(wc_dev, card, 64);
-+ if (!res && (res != wc_dev->mod[card].fxs.lasttxhook)) {
-+ res = a24xx_spi_getreg(wc_dev, card, 8);
-+ if (res) {
-+ printk("Ouch, part reset, quickly restoring reality (%d)\n", card);
-+ si321x_init_proslic(wc_dev, card, 1, 0, 1);
-+ } else {
-+ if (wc_dev->mod[card].fxs.palarms++ < MAX_ALARMS) {
-+ printk("Power alarm on module %d, resetting!\n", card + 1);
-+ if (wc_dev->mod[card].fxs.lasttxhook == 4)
-+ wc_dev->mod[card].fxs.lasttxhook = 1;
-+ a24xx_spi_setreg(wc_dev, card, 64, wc_dev->mod[card].fxs.lasttxhook);
-+ } else {
-+ if (wc_dev->mod[card].fxs.palarms == MAX_ALARMS)
-+ printk("Too many power alarms on card %d, NOT resetting!\n", card + 1);
-+ }
-+ }
-+ }
-+}
---- dahdi-linux-2.10.0.1/drivers/dahdi/opvxd115/Kbuild 1970-01-01 01:00:00.000000000 +0100
-+++ dahdi-linux-2.10.0.1-openvox/drivers/dahdi/opvxd115/Kbuild 2015-02-10 14:19:03.000000000 +0100
-@@ -0,0 +1,33 @@
-+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXD115) += opvxd115.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
-+
-+opvxd115-objs := base.o vpm450m.o
-+
-+ifneq ($(HOTPLUG_FIRMWARE),yes)
-+opvxd115-objs += $(FIRM_DIR)/dahdi-fw-oct6114-032.o $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o
-+$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
-+endif
-+$(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
-+
-+$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o
-+ $(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o