⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 torisa.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Zapata Telephony "Tormenta" ISA card LINUX driver, version 2.2 11/29/01 *  * 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.  * * Modified from original tor.c by Mark Spencer <markster@linux-support.net> *                     original by Jim Dixon <jim@lambdatel.com> */#include <linux/config.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/module.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <asm/io.h>#ifdef STANDALONE_ZAPATA#include "zaptel.h"#include "torisa.h"#else#include <linux/zaptel.h>#include <linux/torisa.h>#endif#ifdef LINUX26#include <linux/moduleparam.h>#endif/* Board address offsets (specified in word (not byte) offsets) */#define	DDATA 0			/* Data I/O Register */#define	DADDR 0x100		/* Dallas Card Address Reg., 0x200 in byte offset higher */#define	CTLREG 0x100		/* Control/Status Reg., 0x200 in byte offset *//* Control register bits */#define	OUTBIT 8		/* Status output bit (for external measurements) */#define	INTENA 4		/* Interrupt enable bit */#define	MASTERVAL 0x41		/* Enable E1 master clock on Rev. B board */#define	ENA16 0x80		/* 16 bit bus cycle enable bit */#define	TYPE_T1	1		/* is a T1 card */#define	TYPE_E1	2		/* is an E1 card */#define	E1SYNCSTABLETHRESH 15000 /* amount of samples needed for E1 Sync stability */static int syncsrc;static int syncs[2];static int debug;#define	MASTERCLOCK (*clockvals)  /* value for master clock *//* clock values */static u_char clockvals_t1[] = {MASTERVAL,0x12,0x22,MASTERVAL};static u_char clockvals_e1[] = {MASTERVAL,0x13,0x23,MASTERVAL};static u_char *clockvals;/* translations of data channels for 24 channels in a 32 bit PCM highway */unsigned datxlt_t1[] = { 0,    1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 };/* translations of data channels for 30/31 channels in a 32 bit PCM highway */unsigned datxlt_e1[] = { 0,    1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,	25,26,27,28,29,30,31 };unsigned int *datxlt;/* This is the order that the data (audio) channels getscanned in. This was done in this rather poopy manner because when outputting(and inputting) a sine wave, such as in the case of TDD, any repeated samples(because of PCM bus contention) will result in nasty-sounding distortion. The Mitel STPA chips (MT8920) have a contention mechanism, which results in asituation where, if the processor accesses a timeslot that is currentlybeing transmitted or received, it will HOLD the bus until it is done withthe timeslot. This means that there can be cases where we are tryingto write to a timeslot, and its already outputting the same valueas the last one (since we didnt get there in time), and in a sine-waveoutput, distortion will occur. In any other output, it will be utterlyun-noticeable. So, what we do is use a pattern that gives us the mostflexibility in how long our interrupt latency is (note: Even with this,our interrupt latency must be between 4 and 28 microseconds!!!)  Essentiallywe receive the interrupt just after the 24th channel is read.  It willtake us AT LEAST 30 microseconds to read it, but could take as much as35 microseconds to read all the channels.  In any case it's the veryfirst thing we do in the interrupt handler.  Worst case (30 microseconds)is that the MT8920 has only moved 7 channels.  That's where the 6 comes from.*/static int chseq_t1[] = 	{ 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,1,2,3,4,5 } ;static int chseq_e1[] = 	{ 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,2,3,4,5 } ;static int *chseq;struct torisa_pvt {	int span;};static struct zt_span spans[2];static struct zt_chan chans[64];static struct torisa_pvt pvts[64];static u_char txsigs[2][16];static int loopupcnt[2];static int loopdowncnt[2];static int alarmtimer[2];static int channels_per_span = 24; static int card_type = TYPE_T1; static int prefmaster = 0;static int spansstarted = 0;static rwlock_t torisa = RW_LOCK_UNLOCKED;static u_char readdata[2][64][ZT_MAX_CHUNKSIZE];static u_char writedata[2][64][ZT_MAX_CHUNKSIZE];static u_char last_ecwrite[2][32];static int curread;static unsigned long base;volatile static unsigned short *maddr;static int irq;static unsigned int irqcount = 0;static unsigned int taskletsched = 0;static unsigned int taskletrun = 0;static unsigned int taskletexec = 0;/* set the control register */static void setctlreg(unsigned char val){volatile register char *cp;	cp = (char *) &maddr[CTLREG];	*cp = val;}/* output a byte to one of the registers in one of the Dallas T-1 chips */static void t1out(int spanno, int loc, unsigned char val){register int n;volatile register char *cp;	  /* get the memory offset */	n = spanno << 9;	  /* point a char * at the address location */	cp = (char *) &maddr[DADDR + n];	*cp = loc;  /* set address in T1 chip */	  /* point a char * at the data location */	cp = (char *) &maddr[DDATA + n];	*cp = val;  /* out the value */}/* get a byte from one of the registers in one of the Dallas T-1 chips */static unsigned char t1in(int spanno, int loc){register int n;volatile register char *cp;	  /* get the memory offset */	n = spanno << 9;	  /* point a char * at the address location */	cp = (char *) &maddr[DADDR + n];	*cp = loc;  /* set address in T1 chip */	cp = (char *) &maddr[DDATA + n];	  /* point a char * at the data location */	return(*cp);}/* get input from the status register */static unsigned char getctlreg(void){register char *cp;	cp = (char *) &maddr[CTLREG];	return(*cp);}static void set_clear(void){	int i,j,s;	unsigned short val=0;	for (s=0;s<2;s++) {		for (i=0;i<channels_per_span;i++) {			j = (i/8);			if (spans[s].chans[i].flags & ZT_FLAG_CLEAR) 				val |= 1 << (i % 8);			if ((i % 8)==7) {#if 0				printk("Putting %d in register %02x on span %d\n",				       val, 0x39 + j, 1 + s);#endif				t1out(1 + s, 0x39 + j, val);				val = 0;			}		}	}		}/* device probe routine .. determines if the Tormenta device is present in   the system */static inttor_probe(void){	int			i,status;	u_char			c1,c2;	maddr = phys_to_virt(base);	status = -1; /* default status return is 'not present' */	clockvals = clockvals_t1;	datxlt = datxlt_t1;	chseq = chseq_t1;	  /* initialize control register */	setctlreg(MASTERCLOCK);	   /* init all the registers in first T-1 chip to 0 */	for(i = 0; i <= 0xff; i++) t1out(1,i,0); /* set register to 0 */	/* simple test that will fail if tried in an array of standard memory */	  /* put an 0x55 here */	t1out(1,0x2b,0x55);	  /* put an 0xaa here */	t1out(1,0x2c,0xaa);	  /* get input from first location */	c1 = t1in(1,0x2b);	  /* get input from second location */	c2 = t1in(1,0x2c);	  /* see if we read back what we put in */	if ((c1 == 0x55) && (c2 == 0xaa)) {		/* We now need to determine card type */		/* This test is documented in Dallas app note 341 */		t1out(1, 0x7D, 0);		t1out(1, 0x36, 0);		t1out(1, 0x15, 0);		t1out(1, 0x19, 0);		t1out(1, 0x23, 0x55);		c1 = t1in(1, 0x23);  		if (c1 == 0x55) { /* if this is an E-1 card */				clockvals = clockvals_e1;			chseq = chseq_e1;			channels_per_span = 31;			datxlt = datxlt_e1;			card_type = TYPE_E1;			  /* initialize control register */			setctlreg(MASTERCLOCK);		}		/* Try to get the irq if the user didn't specify one */		if (irq < 1) {#ifdef LINUX26			unsigned long irqs;			unsigned long delay = jiffies + 5;			irqs = probe_irq_on();			setctlreg(MASTERCLOCK|INTENA);			while((long)(jiffies - delay) < 0);			irq = probe_irq_off(irqs);#else						autoirq_setup(0);			setctlreg(MASTERCLOCK|INTENA);			/* Wait a jiffie -- that's plenty of time */			irq = autoirq_report(5);#endif					}		/* disable interrupts having gotten one */		setctlreg(MASTERCLOCK);		if (irq == 2)			irq = 9;		if (irq) {	  		/* init both STPA's to all silence */			for(i = 0; i < 32; i++) maddr[i] = 0x7f7f;			status = 0;	/* found */			if (debug)				printk("ISA Tormenta %s Card found at base addr 0x%lx, irq %d\n",					((card_type == TYPE_E1) ? "E1" : "T1"),						base,irq);		} else			printk("ISA Tormenta %s Card found at base addr 0x%lx, but unable to determine IRQ.  Try using irq= option\n", 				((card_type == TYPE_E1) ? "E1" : "T1"), base );	   }	return status;}static void make_chans(void){	int x,y;	int c;	for (x=0;x<2;x++)		for (y=0;y<channels_per_span;y++) {			c = x * channels_per_span + y;			sprintf(chans[c].name, "TorISA/%d/%d", x + 1, y + 1);			chans[c].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS |									 ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF;			chans[c].pvt = &pvts[c];			pvts[c].span = x;			chans[c].chanpos = y + 1;		}			}static int torisa_rbsbits(struct zt_chan *chan, int bits){	u_char m,c;	int k,n,b;	struct torisa_pvt *p = chan->pvt;	unsigned long flags;#if	0	printk("Setting bits to %x hex on channel %s\n", bits, chan->name);#endif	if (card_type == TYPE_E1) { /* do it E1 way */		if (chan->chanpos > 30) return 0;  /* cant do this for chan 31 */		n = chan->chanpos - 1;		k = p->span;		b = (n % 15) + 1;		c = txsigs[k][b];		m = (n / 15) * 4; /* nibble selector */		c &= (15 << m); /* keep the other nibble */		c |= (bits & 15) << (4 - m); /* put our new nibble here */		txsigs[k][b] = c;		  /* output them into the chip */		t1out(k + 1,0x40 + b,c); 		return 0;	}							n = chan->chanpos - 1;	k = p->span;	b = (n / 8); /* get byte number */	m = 1 << (n & 7); /* get mask */	c = txsigs[k][b];	c &= ~m;  /* clear mask bit */	  /* set mask bit, if bit is to be set */	if (bits & ZT_ABIT) c |= m;	txsigs[k][b] = c;	write_lock_irqsave(&torisa, flags);		t1out(k + 1,0x70 + b,c);	b += 3; /* now points to b bit stuff */	  /* get current signalling values */	c = txsigs[k][b];	c &= ~m;  /* clear mask bit */	  /* set mask bit, if bit is to be set */	if (bits & ZT_BBIT) c |= m;	  /* save new signalling values */	txsigs[k][b] = c;	  /* output them into the chip */	t1out(k + 1,0x70 + b,c);	b += 3; /* now points to c bit stuff */	  /* get current signalling values */	c = txsigs[k][b];	c &= ~m;  /* clear mask bit */	  /* set mask bit, if bit is to be set */	if (bits & ZT_CBIT) c |= m;	  /* save new signalling values */	txsigs[k][b] = c;	  /* output them into the chip */	t1out(k + 1,0x70 + b,c);	b += 3; /* now points to d bit stuff */	  /* get current signalling values */	c = txsigs[k][b];	c &= ~m;  /* clear mask bit */	  /* set mask bit, if bit is to be set */	if (bits & ZT_DBIT) c |= m;	  /* save new signalling values */	txsigs[k][b] = c;	  /* output them into the chip */	t1out(k + 1,0x70 + b,c);	write_unlock_irqrestore(&torisa, flags);	return 0;}static inline int getspan(struct zt_span *span){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -