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

📄 tor2.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Tormenta 2  Quad-T1 PCI Driver * * Written by Mark Spencer <markster@linux-support.net> * Based on previous works, designs, and archetectures conceived and * written by Jim Dixon <jim@lambdatel.com>. * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001, Linux Support Services, Inc. * * 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.  * * $Id: tor2.c,v 1.19.2.3 2005/01/17 01:58:09 russell Exp $ */#include <linux/kernel.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/interrupt.h>#ifdef STANDALONE_ZAPATA#include "zaptel.h"#else#include <linux/zaptel.h>#endif#ifdef LINUX26#include <linux/moduleparam.h>#endif#define NEED_PCI_IDS#include "tor2-hw.h"#include "tor2fw.h"/* * Tasklets provide better system interactive response at the cost of the * possibility of losing a frame of data at very infrequent intervals.  If * you are more concerned with the performance of your machine, enable the * tasklets.  If you are strict about absolutely no drops, then do not enable * tasklets. *//* #define ENABLE_TASKLETS */#define SPANS_PER_CARD  4#define MAX_SPANS       16#define FLAG_STARTED (1 << 0)#define	TYPE_T1	1		/* is a T1 card */#define	TYPE_E1	2		/* is an E1 card */struct tor2_chan {	/* Private pointer for channel.  We want to know our	   channel and span */	struct tor2 *tor;	int span;	/* Index from 0 */};struct tor2_span {	/* Private pointer for span.  We want to know our	   span number and pointer to the tor device */	struct tor2 *tor;	int span;	/* Index from 0 */};struct tor2 {	/* This structure exists one per card */	struct pci_dev *pci;		/* Pointer to PCI device */	int num;			/* Which card we are */	int syncsrc;			/* active sync source */	int syncs[SPANS_PER_CARD];	/* sync sources */	int psyncs[SPANS_PER_CARD];	/* span-relative sync sources */	int alarmtimer[SPANS_PER_CARD];	/* Alarm timer */	char *type;			/* Type of tormenta 2 card */	int irq;			/* IRQ used by device */	int order;			/* Order */	int flags;			/* Device flags */	int syncpos[SPANS_PER_CARD];	/* span-relative sync sources */	int master;			/* Are we master */	unsigned long plx_region;	/* phy addr of PCI9030 registers */	unsigned long plx_len;		/* length of PLX window */	volatile unsigned short *plx;	/* Virtual representation of local space */	unsigned long xilinx32_region;	/* 32 bit Region allocated to Xilinx */	unsigned long xilinx32_len;	/* Length of 32 bit Xilinx region */	volatile unsigned long *mem32;	/* Virtual representation of 32 bit Xilinx memory area */	unsigned long xilinx8_region;	/* 8 bit Region allocated to Xilinx */	unsigned long xilinx8_len;	/* Length of 8 bit Xilinx region */	volatile unsigned char *mem8;	/* Virtual representation of 8 bit Xilinx memory area */	struct zt_span spans[SPANS_PER_CARD];		/* Spans */	struct tor2_span tspans[SPANS_PER_CARD];	/* Span data */	struct zt_chan *chans[SPANS_PER_CARD];		/* Pointers to blocks of 24(30/31) contiguous zt_chans for each span */	struct tor2_chan tchans[32 * SPANS_PER_CARD];	/* Channel user data */	unsigned char txsigs[SPANS_PER_CARD][16];	/* Copy of tx sig registers */	int loopupcnt[SPANS_PER_CARD];	/* loop up code counter */	int loopdowncnt[SPANS_PER_CARD];/* loop down code counter */	int spansstarted;		/* number of spans started */	spinlock_t lock;		/* lock context */	unsigned char leds;		/* copy of LED register */	unsigned char ec_chunk1[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* first EC chunk buffer */	unsigned char ec_chunk2[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* second EC chunk buffer */#ifdef ENABLE_TASKLETS	int taskletrun;	int taskletsched;	int taskletpending;	int taskletexec;	int txerrors;	struct tasklet_struct tor2_tlet;#endif	int cardtype;		/* card type, T1 or E1 */	unsigned int *datxlt;	/* pointer to datxlt structure */	unsigned int passno;	/* number of interrupt passes */};#define t1out(tor,span,reg,val) tor->mem8[((span - 1) * 0x100) + reg] = val#define t1in(tor,span,reg) tor->mem8[((span - 1) * 0x100) + reg]#ifdef ENABLE_TASKLETSstatic void tor2_tasklet(unsigned long data);#endif#define	GPIOC (PLX_LOC_GPIOC >> 1) /* word-oriented address for PLX GPIOC reg. (32 bit reg.) */#define	INTCSR (0x4c >> 1)  /* word-oriented address for PLX INTCSR reg. */#define	PLX_INTENA 0x43 /* enable, hi-going, level trigger */#define	SYNCREG	0x400#define	CTLREG	0x401#define	LEDREG	0x402#define	STATREG	0x400#define SWREG	0x401#define	CTLREG1	0x404#define	INTENA	(1 + ((loopback & 3) << 5))#define	OUTBIT	(2 + ((loopback & 3) << 5))#define	E1DIV	0x10#define	INTACK	(0x80 + ((loopback & 3) << 5))#define	INTACTIVE 2#define MASTER (1 << 3)/* un-define this if you dont want NON-REV A hardware support *//* #define	NONREVA 1 */#define	SYNCSELF 0#define	SYNC1	1#define	SYNC2	2#define	SYNC3	3#define	SYNC4	4#define SYNCEXTERN 5#define	LEDRED	2#define	LEDGREEN 1#define MAX_TOR_CARDS 64struct tor2 *cards[MAX_TOR_CARDS];/* signalling bits */#define	TOR_ABIT 8#define	TOR_BBIT 4static int debug;static int japan;static int loopback;static int highestorder;static int timingcable;static void set_clear(struct tor2 *tor);static int tor2_startup(struct zt_span *span);static int tor2_shutdown(struct zt_span *span);static int tor2_rbsbits(struct zt_chan *chan, int bits);static int tor2_maint(struct zt_span *span, int cmd);static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data);#ifdef LINUX26static irqreturn_t tor2_intr(int irq, void *dev_id, struct pt_regs *regs);#elsestatic void tor2_intr(int irq, void *dev_id, struct pt_regs *regs);#endif/* translations of data channels for 24 channels in a 32 bit PCM highway */unsigned datxlt_t1[] = {     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[] = {     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 };static int tor2_spanconfig(struct zt_span *span, struct zt_lineconfig *lc){	int i;	struct tor2_span *p = span->pvt;	if (debug)		printk("Tor2: Configuring span %d\n", span->spanno);	/* XXX We assume lineconfig is okay and shouldn't XXX */		span->lineconfig = lc->lineconfig;	span->txlevel = lc->lbo;	span->rxlevel = 0;	span->syncsrc = p->tor->syncsrc;		/* remove this span number from the current sync sources, if there */	for (i = 0; i < SPANS_PER_CARD; i++) {		if (p->tor->syncs[i] == span->spanno) {			p->tor->syncs[i] = 0;			p->tor->psyncs[i] = 0;		}	}	p->tor->syncpos[p->span] = lc->sync;	/* if a sync src, put it in the proper place */	if (lc->sync) {		p->tor->syncs[lc->sync - 1] = span->spanno;		p->tor->psyncs[lc->sync - 1] = p->span + 1;	}	/* If we're already running, then go ahead and apply the changes */	if (span->flags & ZT_FLAG_RUNNING)		return tor2_startup(span);	return 0;}static int tor2_chanconfig(struct zt_chan *chan, int sigtype){	int alreadyrunning;	unsigned long flags;	struct tor2_chan *p = chan->pvt;	alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING;	if (debug) {		if (alreadyrunning)			printk("Tor2: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype);		else			printk("Tor2: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype);	}			/* nothing more to do if an E1 */	if (p->tor->cardtype == TYPE_E1) return 0;	spin_lock_irqsave(&p->tor->lock, flags);		if (alreadyrunning)		set_clear(p->tor);	spin_unlock_irqrestore(&p->tor->lock, flags);		return 0;}static int tor2_open(struct zt_chan *chan){#ifndef LINUX26	MOD_INC_USE_COUNT;#endif	return 0;}static int tor2_close(struct zt_chan *chan){#ifndef LINUX26	MOD_DEC_USE_COUNT;#endif		return 0;}static void init_spans(struct tor2 *tor){	int x, y, c;	for (x = 0; x < SPANS_PER_CARD; x++) {		sprintf(tor->spans[x].name,                	"Tor2/%d/%d", 		        tor->num,                        x + 1);		sprintf(tor->spans[x].desc,                	"Tormenta 2 (PCI) Quad %s Card %d Span %d",                        (tor->cardtype == TYPE_T1)  ?  "T1"  :  "E1",                	tor->num,                        x + 1);		tor->spans[x].spanconfig = tor2_spanconfig;		tor->spans[x].chanconfig = tor2_chanconfig;		tor->spans[x].startup = tor2_startup;		tor->spans[x].shutdown = tor2_shutdown;		tor->spans[x].rbsbits = tor2_rbsbits;		tor->spans[x].maint = tor2_maint;		tor->spans[x].open = tor2_open;		tor->spans[x].close  = tor2_close;		if (tor->cardtype == TYPE_T1) {			tor->spans[x].channels = 24;			tor->spans[x].deflaw = ZT_LAW_MULAW;		} else {			tor->spans[x].channels = 31;			tor->spans[x].deflaw = ZT_LAW_ALAW;		}		tor->spans[x].chans = tor->chans[x];		tor->spans[x].flags = ZT_FLAG_RBS;		tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;		tor->spans[x].ioctl = tor2_ioctl;		tor->spans[x].pvt = &tor->tspans[x];		tor->tspans[x].tor = tor;		tor->tspans[x].span = x;		init_waitqueue_head(&tor->spans[x].maintq);		for (y=0;y<tor->spans[x].channels;y++) {			struct zt_chan *mychans = tor->chans[x] + y;			sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1);			mychans->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 | ZT_SIG_EM_E1;			c = (x * tor->spans[x].channels) + y;			mychans->pvt = &tor->tchans[c];			mychans->chanpos = y + 1;			tor->tchans[c].span = x;			tor->tchans[c].tor = tor;		}	}}static int __devinit tor2_launch(struct tor2 *tor){	if (tor->spans[0].flags & ZT_FLAG_REGISTERED)		return 0;	printk("Tor2: Launching card: %d\n", tor->order);	if (zt_register(&tor->spans[0], 0)) {		printk(KERN_ERR "Unable to register span %s\n", tor->spans[0].name);		return -1;	}	if (zt_register(&tor->spans[1], 0)) {		printk(KERN_ERR "Unable to register span %s\n", tor->spans[1].name);		zt_unregister(&tor->spans[0]);		return -1;	}	if (zt_register(&tor->spans[2], 0)) {		printk(KERN_ERR "Unable to register span %s\n", tor->spans[2].name);		zt_unregister(&tor->spans[0]);		zt_unregister(&tor->spans[1]);		return -1;	}	if (zt_register(&tor->spans[3], 0)) {		printk(KERN_ERR "Unable to register span %s\n", tor->spans[3].name);		zt_unregister(&tor->spans[0]);		zt_unregister(&tor->spans[1]);		zt_unregister(&tor->spans[2]);		return -1;	}	tor->plx[INTCSR] = cpu_to_le16(PLX_INTENA); /* enable PLX interrupt */#ifdef ENABLE_TASKLETS	tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor);#endif	return 0;}static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id *ent){	int res,x,f;	struct tor2 *tor;	unsigned long endjif;	volatile unsigned long *gpdata_io;	unsigned long gpdata;	res = pci_enable_device(pdev);	if (res)		return res;	tor = kmalloc(sizeof(struct tor2), GFP_KERNEL);	if (!tor)		return -ENOMEM;	memset(tor,0,sizeof(struct tor2));	spin_lock_init(&tor->lock);	for (x = 0; x < SPANS_PER_CARD; x++) {		tor->chans[x] = kmalloc(sizeof(struct zt_chan) * 31,GFP_KERNEL);		if (!tor->chans[x])			return -ENOMEM;		memset(tor->chans[x],0,sizeof(struct zt_chan) * 31);	}	/* Load the resources */	tor->irq = pdev->irq;	if (tor->irq < 1) {		printk(KERN_ERR "No IRQ allocated for device\n");		goto err_out_free_tor;	}	tor->plx_region = pci_resource_start(pdev, 0);	tor->plx_len = pci_resource_len(pdev, 0);	tor->plx = ioremap(tor->plx_region, tor->plx_len);	/* We don't use the I/O space, so we dont do anything with section 1 */	tor->xilinx32_region = pci_resource_start(pdev, 2);	tor->xilinx32_len = pci_resource_len(pdev, 2);	tor->mem32 = ioremap(tor->xilinx32_region, tor->xilinx32_len);	tor->xilinx8_region = pci_resource_start(pdev, 3);	tor->xilinx8_len = pci_resource_len(pdev, 3);	tor->mem8 = ioremap(tor->xilinx8_region, tor->xilinx8_len);	/* Record what type */	tor->type = (char *)ent->driver_data;	/* Verify existence and accuracy of resources */	if (!tor->plx_region || !tor->plx ||	    (pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {		printk(KERN_ERR "Invalid PLX 9030 Base resource\n");		goto err_out_free_tor;	}	if (!tor->xilinx32_region || !tor->mem32 ||	    (pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {		printk(KERN_ERR "Invalid Xilinx 32 bit Base resource\n");		goto err_out_free_tor;	}	if (!tor->xilinx8_region || !tor->mem8 ||	    (pci_resource_flags(pdev, 3) & IORESOURCE_IO)) {		printk(KERN_ERR "Invalid Xilinx 8 bit Base resource\n");		goto err_out_free_tor;	}	/* Request regions */	if (!request_mem_region(tor->plx_region, tor->plx_len, tor->type)) {		printk(KERN_ERR "Unable to reserve PLX memory %08lx window at %08lx\n",		       tor->plx_len, tor->plx_region);		goto err_out_free_tor;	}	if (!request_mem_region(tor->xilinx32_region, tor->xilinx32_len, tor->type)) {		printk(KERN_ERR "Unable to reserve Xilinx 32 bit memory %08lx window at %08lx\n",		       tor->xilinx32_len, tor->xilinx32_region);		goto err_out_release_plx_region;	}	if (!request_mem_region(tor->xilinx8_region, tor->xilinx8_len, tor->type)) {		printk(KERN_ERR "Unable to reserve Xilinx memory %08lx window at %08lx\n",		       tor->xilinx8_len, tor->xilinx8_region);		goto err_out_release_plx_region;	}	pci_set_drvdata(pdev, tor);	printk("Detected %s at 0x%lx/0x%lx irq %d\n", tor->type, 		tor->xilinx32_region, tor->xilinx8_region,tor->irq);	for (x = 0; x < MAX_TOR_CARDS; x++) {		if (!cards[x]) break;	}	if (x >= MAX_TOR_CARDS) {		printk("No cards[] slot available!!\n");		goto err_out_release_all;	}	tor->num = x;	cards[x] = tor;	/* start programming mode */	gpdata_io = (unsigned long *)&tor->plx[GPIOC];	gpdata = le32_to_cpu(*gpdata_io);	gpdata |= GPIO_WRITE; /* make sure WRITE is not asserted */	*gpdata_io = cpu_to_le32(gpdata);	gpdata &= ~GPIO_PROGRAM;  /* activate the PROGRAM signal */	*gpdata_io = cpu_to_le32(gpdata);	/* wait for INIT and DONE to go low */	endjif = jiffies + 10;	while (le32_to_cpu(*gpdata_io) & (GPIO_INIT | GPIO_DONE) && (jiffies <= endjif));	if (endjif < jiffies) {		printk("Timeout waiting for INIT and DONE to go low\n");		goto err_out_release_all;	}	if (debug) printk("fwload: Init and done gone to low\n");	gpdata |= GPIO_PROGRAM;	*gpdata_io = cpu_to_le32(gpdata);  /* de-activate the PROGRAM signal */	/* wait for INIT to go high (clearing done */	endjif = jiffies + 10;	while (!(le32_to_cpu(*gpdata_io) & GPIO_INIT) && (jiffies <= endjif));	if (endjif < jiffies) {		printk("Timeout waiting for INIT to go high\n");		goto err_out_release_all;	}	if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n");	/* assert WRITE signal */	gpdata &= ~GPIO_WRITE;	*gpdata_io = cpu_to_le32(gpdata);	for (x = 0; x < sizeof(tor2fw); x++)	   {		  /* write the byte */		*tor->mem8 = tor2fw[x];		  /* if DONE signal, we're done, exit */		if (le32_to_cpu(*gpdata_io) & GPIO_DONE) break;		  /* if INIT drops, we're screwed, exit */		if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) break;	   }	if (debug) printk("fwload: Transferred %d bytes into chip\n",x);	/* Wait for FIFO to clear */	endjif = jiffies + 2;	while (jiffies < endjif); /* wait */	  /* de-assert write signal */	gpdata |= GPIO_WRITE;	*gpdata_io = cpu_to_le32(gpdata);	if (debug) printk("fwload: Loading done!\n");		/* Wait for FIFO to clear */	endjif = jiffies + 2;	while (jiffies < endjif); /* wait */	if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT))	   {		printk("Drove Init low!! CRC Error!!!\n");		goto err_out_release_all;	   }	if (!(le32_to_cpu(*gpdata_io) & GPIO_DONE))	   {

⌨️ 快捷键说明

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