📄 wcfxs.c
字号:
/* * Wildcard TDM400P TDM FXS/FXO Interface Driver for Zapata Telephony interface * * Written by Mark Spencer <markster@linux-support.net> * Matthew Fredrickson <creslin@linux-support.net> * * Copyright (C) 2001, Linux Support Services, Inc. * * All rights reserved. * * Adapted to the Blackfin by David Rowe 2005. * * 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/delay.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/proc_fs.h>#include "proslic.h"#include "wcfxs.h"#include "bfsi.h"#include "sport_interface.h" //Added by Alex Tao/* * Define for audio vs. register based ring detection * *//* #define AUDIO_RINGCHECK *//* Experimental max loop current limit for the proslic Loop current limit is from 20 mA to 41 mA in steps of 3 (according to datasheet) So set the value below to: 0x00 : 20mA (default) 0x01 : 23mA 0x02 : 26mA 0x03 : 29mA 0x04 : 32mA 0x05 : 35mA 0x06 : 37mA 0x07 : 41mA*/static int loopcurrent = 20;static alpha indirect_regs[] ={{0,255,"DTMF_ROW_0_PEAK",0x55C2},{1,255,"DTMF_ROW_1_PEAK",0x51E6},{2,255,"DTMF_ROW2_PEAK",0x4B85},{3,255,"DTMF_ROW3_PEAK",0x4937},{4,255,"DTMF_COL1_PEAK",0x3333},{5,255,"DTMF_FWD_TWIST",0x0202},{6,255,"DTMF_RVS_TWIST",0x0202},{7,255,"DTMF_ROW_RATIO_TRES",0x0198},{8,255,"DTMF_COL_RATIO_TRES",0x0198},{9,255,"DTMF_ROW_2ND_ARM",0x0611},{10,255,"DTMF_COL_2ND_ARM",0x0202},{11,255,"DTMF_PWR_MIN_TRES",0x00E5},{12,255,"DTMF_OT_LIM_TRES",0x0A1C},{13,0,"OSC1_COEF",0x7B30},{14,1,"OSC1X",0x0063},{15,2,"OSC1Y",0x0000},{16,3,"OSC2_COEF",0x7870},{17,4,"OSC2X",0x007D},{18,5,"OSC2Y",0x0000},{19,6,"RING_V_OFF",0x0000},{20,7,"RING_OSC",0x7EF0},{21,8,"RING_X",0x0160},{22,9,"RING_Y",0x0000},{23,255,"PULSE_ENVEL",0x2000},{24,255,"PULSE_X",0x2000},{25,255,"PULSE_Y",0x0000},//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower{27,14,"XMIT_DIGITAL_GAIN",0x4000},//{27,14,"XMIT_DIGITAL_GAIN",0x2000},{28,15,"LOOP_CLOSE_TRES",0x1000},{29,16,"RING_TRIP_TRES",0x3600},{30,17,"COMMON_MIN_TRES",0x1000},{31,18,"COMMON_MAX_TRES",0x0200},{32,19,"PWR_ALARM_Q1Q2",0x07C0},{33,20,"PWR_ALARM_Q3Q4",0x2600},{34,21,"PWR_ALARM_Q5Q6",0x1B80},{35,22,"LOOP_CLOSURE_FILTER",0x8000},{36,23,"RING_TRIP_FILTER",0x0320},{37,24,"TERM_LP_POLE_Q1Q2",0x008C},{38,25,"TERM_LP_POLE_Q3Q4",0x0100},{39,26,"TERM_LP_POLE_Q5Q6",0x0010},{40,27,"CM_BIAS_RINGING",0x0C00},{41,64,"DCDC_MIN_V",0x0C00},{42,255,"DCDC_XTRA",0x1000},{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},};static struct fxo_mode { char *name; /* FXO */ int ohs; int ohs2; int rz; int rt; int ilim; int dcv; int mini; int acim; int ring_osc; int ring_x;} fxo_modes[] ={ { "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0 }, /* US, Canada */ { "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a }, /* Austria, Belgium, Denmark, Finland, France, Germany, Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, Norway, Portugal, Spain, Sweden, Switzerland, and UK */ { "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3 }, { "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3 }, { "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3 }, { "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf }, { "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3 }, { "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4 }, { "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0 }, { "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0 }, /* Current loop >= 20ma */ { "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2 }, { "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4 }, { "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2 }, { "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0 }, { "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0 }, { "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3 }, { "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2 }, { "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3 }, { "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2 }, { "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0 }, { "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5 }, { "USA", 0, 0, 0, 0, 0, 0x3, 0, 0 }, { "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0 },};#ifdef STANDALONE_ZAPATA#include "zaptel.h"#else#include "zaptel.h"#endif#ifdef LINUX26#include <linux/moduleparam.h>#endif#define NUM_FXO_REGS 60#define WC_MAX_IFACES 128#define WC_CNTL 0x00#define WC_OPER 0x01#define WC_AUXC 0x02#define WC_AUXD 0x03#define WC_MASK0 0x04#define WC_MASK1 0x05#define WC_INTSTAT 0x06#define WC_AUXR 0x07#define WC_DMAWS 0x08#define WC_DMAWI 0x0c#define WC_DMAWE 0x10#define WC_DMARS 0x18#define WC_DMARI 0x1c#define WC_DMARE 0x20#define WC_AUXFUNC 0x2b#define WC_SERCTL 0x2d#define WC_FSCDELAY 0x2f#define WC_REGBASE 0xc0#define WC_SYNC 0x0#define WC_TEST 0x1#define WC_CS 0x2#define WC_VER 0x3/* ------------------------ Blackfin -------------------------*//* Modified by Alex Tao */#ifdef CONFIG_4FX_SPI_INTERFACE#define SPI_BAUDS 5 /* 12.5 MHz for 100MHz system clock */#define SPI_NCSA 3 /* nCS bit for SPI data */#define SPI_NCSB 12 /* nCS bit for SPI mux */#else#ifdef CONFIG_4FX_SPORT_INTERFACE#define SPI_BAUDS 4 /* 13.4 MHz for 133MHz system clock *//* Use other PF signals */#define SPI_NCSA 8 /* Simulate SPORT interface as SPI */#define SPI_NCSB 9#endif#endif#define RESET_BIT 4 /* GPIO bit tied to nRESET on Si chips */#include "fx.c"#ifdef CONFIG_4FX_SPI_INTERFACE#define __write_8bits(X, Y) bfsi_spi_write_8_bits(SPI_NCSA, Y)#define __read_8bits(X) bfsi_spi_read_8_bits(SPI_NCSA)#else#define __write_8bits(X, Y) sport_tx_byte(SPI_NCSA, Y)#define __read_8bits(X) sport_rx_byte(SPI_NCSA)#endif#define __reset_spi(X) do {} while(0)/* ------------------------ Blackfin -------------------------*/#define FLAG_EMPTY 0#define FLAG_WRITE 1#define FLAG_READ 2#define RING_DEBOUNCE 64 /* Ringer Debounce (in ms) */#define BATT_DEBOUNCE 64 /* Battery debounce (in ms) */#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */#define BATT_THRESH 3 /* Anything under this is "no battery" */#define OHT_TIMER 6000 /* How long after RING to retain OHT */#define FLAG_3215 (1 << 0)#define NUM_CARDS 8#define MAX_ALARMS 10#define MOD_TYPE_FXS 0#define MOD_TYPE_FXO 1#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */#define PEGCOUNT 5 /* 5 cycles of pegging means RING */#define NUM_CAL_REGS 12struct calregs { unsigned char vals[NUM_CAL_REGS];};struct wcfxs { int irq; char *variety; struct zt_span span; unsigned char ios; int usecount; unsigned int intcount; int dead; int pos; int flags[NUM_CARDS]; int freeregion; int alt; int curcard; int cards; int cardflag; /* Bit-map of present cards */ spinlock_t lock; /* FXO Stuff */ union { struct {#ifdef AUDIO_RINGCHECK unsigned int pegtimer[NUM_CARDS]; int pegcount[NUM_CARDS]; int peg[NUM_CARDS]; int ring[NUM_CARDS];#else int wasringing[NUM_CARDS];#endif int ringdebounce[NUM_CARDS]; int offhook[NUM_CARDS]; int battdebounce[NUM_CARDS]; int nobatttimer[NUM_CARDS]; int battery[NUM_CARDS]; int lastpol[NUM_CARDS]; int polarity[NUM_CARDS]; int polaritydebounce[NUM_CARDS]; } fxo; struct { int oldrxhook[NUM_CARDS]; int debouncehook[NUM_CARDS]; int lastrxhook[NUM_CARDS]; int debounce[NUM_CARDS]; int ohttimer[NUM_CARDS]; int idletxhookstate[NUM_CARDS]; /* IDLE changing hook state */ int lasttxhook[NUM_CARDS]; int palarms[NUM_CARDS]; struct calregs calregs[NUM_CARDS]; } fxs; } mod; /* Receive hook state and debouncing */ int modtype[NUM_CARDS]; unsigned long ioaddr; dma_addr_t readdma; dma_addr_t writedma; volatile int *writechunk; /* Double-word aligned write memory */ volatile int *readchunk; /* Double-word aligned read memory */ struct zt_chan chans[NUM_CARDS];};struct wcfxs_desc { char *name; int flags;};static struct wcfxs_desc wcfxs_bf = { "Blackfin STAMP", 0 };static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 };static struct wcfxs *ifaces[WC_MAX_IFACES];static void wcfxs_release(struct wcfxs *wc);#ifdef OLD_DRstatic void init_sport0(void);static void init_dma_wc(void);static int init_sport_interrupts(void);static void enable_dma_sport0(void);static void disable_sport0(void);int wcfxs_proc_read(char *buf, char **start, off_t offset, int count, int *eof, void *data);#endifstatic int debug = 0;static int robust = 0;static int timingonly = 0;static int lowpower = 0;static int boostringer = 0;static int _opermode = 0;static char *opermode = "FCC";static int fxshonormode = 0;static struct wcfxs *devs;/* added for uCasterisk/Blackfin */static int loopback = 0;static int reg5, reg12, loop_i, line_v;static int wcfxs_init_ok = 0;#ifdef TMP_DRstatic int internalclock = 0;static int readchunk_first = 0;static int readchunk_second = 0;static int readchunk_didntswap = 0;static unsigned char* lastreadchunk;static int writechunk_first = 0;static int writechunk_second = 0;static int writechunk_didntswap = 0;static unsigned char* lastwritechunk;static int rx1;static int rx2;static int tx1;static int tx2;#ifdef TMP_DR/* SPORT0 DMA transmit buffer */volatile char iTxBuffer1[8*ZT_CHUNKSIZE*2];/* SPORT0 DMA receive buffer */volatile char iRxBuffer1[8*ZT_CHUNKSIZE*2];#elsevolatile char *iTxBuffer1;volatile char *iRxBuffer1;#endif#endif#ifdef TMP_DR#if L1_DATA_A_LENGTH != 0extern unsigned long l1_data_A_sram_alloc(unsigned long size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -