📄 tor2.c
字号:
/* * 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 + -