diff options
Diffstat (limited to 'tor2.c')
-rwxr-xr-x | tor2.c | 166 |
1 files changed, 97 insertions, 69 deletions
@@ -1,5 +1,5 @@ /* - * Tormenta 2 Quad-T1 PCI Driver version 0.2, 12/11/01 + * Tormenta 2 Quad-T1 PCI Driver * * Written by Mark Spencer <markster@linux-support.net> * Based on previous works, designs, and archetectures conceived and @@ -24,6 +24,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * $Id$ */ #include <linux/kernel.h> @@ -52,7 +53,8 @@ /* #define ENABLE_TASKLETS */ -#define MAX_SPANS 16 +#define SPANS_PER_CARD 4 +#define MAX_SPANS 16 #define FLAG_STARTED (1 << 0) @@ -78,15 +80,15 @@ struct tor2 { struct pci_dev *pci; /* Pointer to PCI device */ int num; /* Which card we are */ int syncsrc; /* active sync source */ - int syncs[4]; /* sync sources */ - int psyncs[4]; /* span-relative sync sources */ - int alarmtimer[4]; /* Alarm timer */ + 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[4]; /* span-relative sync sources */ - int master; /* Are we master */ + 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 */ @@ -96,18 +98,18 @@ struct tor2 { 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[4]; /* Spans */ - struct tor2_span tspans[4]; /* Span data */ - struct zt_chan *chans[4]; /* Pointers to blocks of 24(30/31) contiguous zt_chans for each span */ - struct tor2_chan tchans[32 * 4];/* Channel user data */ - unsigned char txsigs[4][16]; /* Copy of tx sig registers */ - int loopupcnt[4]; /* loop up code counter */ - int loopdowncnt[4]; /* loop down code counter */ + 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[4][32][ZT_CHUNKSIZE]; /* first EC chunk buffer */ - unsigned char ec_chunk2[4][32][ZT_CHUNKSIZE]; /* second EC chunk buffer */ + 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; @@ -205,14 +207,14 @@ static int tor2_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) span->syncsrc = p->tor->syncsrc; /* remove this span number from the current sync sources, if there */ - for(i = 0; i < 3; i++) { + 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 proper place */ + /* 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; @@ -259,11 +261,17 @@ static int tor2_close(struct zt_chan *chan) static void init_spans(struct tor2 *tor) { - int x,y,c; - for (x=0;x<4;x++) { - sprintf(tor->spans[x].name, "Tor2/%d/%d", - tor->num, x + 1); - sprintf(tor->spans[x].desc, "Tormenta 2 (PCI) Card %d Span %d", tor->num, x+1); + 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; @@ -305,7 +313,7 @@ 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); + 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; @@ -351,7 +359,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id return -ENOMEM; memset(tor,0,sizeof(struct tor2)); spin_lock_init(&tor->lock); - for(x = 0; x < 4; x++) { + 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; @@ -411,7 +419,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id 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++) { + for (x = 0; x < MAX_TOR_CARDS; x++) { if (!cards[x]) break; } if (x >= MAX_TOR_CARDS) { @@ -454,7 +462,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id /* assert WRITE signal */ gpdata &= ~GPIO_WRITE; *gpdata_io = cpu_to_le32(gpdata); - for(x = 0; x < sizeof(tor2fw); x++) + for (x = 0; x < sizeof(tor2fw); x++) { /* write the byte */ *tor->mem8 = tor2fw[x]; @@ -466,7 +474,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id if (debug) printk("fwload: Transferred %d bytes into chip\n",x); /* Wait for FIFO to clear */ endjif = jiffies + 2; - while(jiffies < endjif); /* wait */ + while (jiffies < endjif); /* wait */ /* de-assert write signal */ gpdata |= GPIO_WRITE; *gpdata_io = cpu_to_le32(gpdata); @@ -474,7 +482,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id /* Wait for FIFO to clear */ endjif = jiffies + 2; - while(jiffies < endjif); /* wait */ + while (jiffies < endjif); /* wait */ if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) { printk("Drove Init low!! CRC Error!!!\n"); @@ -500,7 +508,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id tor->mem8[CTLREG1] = NONREVA; } #endif - for(x = 0; x < 256; x++) tor->mem32[x] = 0x7f7f7f7f; + for (x = 0; x < 256; x++) tor->mem32[x] = 0x7f7f7f7f; if (request_irq(tor->irq, tor2_intr, SA_INTERRUPT | SA_SHIRQ, "tor2", tor)) { @@ -524,7 +532,7 @@ static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id /* Launch cards as appropriate */ x = 0; - for(;;) { + for (;;) { /* Find a card to activate */ f = 0; for (x=0;cards[x];x++) { @@ -553,7 +561,7 @@ err_out_free_tor: if (tor->mem8) iounmap((void *)tor->mem8); if (tor->mem32) iounmap((void *)tor->mem32); if (tor) { - for(x = 0; x < 3; x++) kfree(tor->chans[x]); + for (x = 0; x < 3; x++) kfree(tor->chans[x]); kfree(tor); } return -NODEV; @@ -590,7 +598,7 @@ static void __devexit tor2_remove(struct pci_dev *pdev) cards[tor->num] = 0; pci_set_drvdata(pdev, NULL); - for(x = 0; x < 3; x++) + for (x = 0; x < 3; x++) if (tor->chans[x]) kfree(tor->chans[x]); kfree(tor); @@ -619,8 +627,8 @@ static void set_clear(struct tor2 *tor) { int i,j,s; unsigned short val=0; - for (s=0;s<4;s++) { - for (i=0;i<24;i++) { + for (s = 0; s < SPANS_PER_CARD; s++) { + for (i = 0; i < 24; i++) { j = (i/8); if (tor->spans[s].chans[i].flags & ZT_FLAG_CLEAR) val |= 1 << (i % 8); @@ -737,10 +745,10 @@ static int tor2_shutdown(struct zt_span *span) if (wasrunning) p->tor->spansstarted--; spin_unlock_irqrestore(&p->tor->lock, flags); - if ((!p->tor->spans[0].flags & ZT_FLAG_RUNNING) && - (!p->tor->spans[1].flags & ZT_FLAG_RUNNING) && - (!p->tor->spans[2].flags & ZT_FLAG_RUNNING) && - (!p->tor->spans[3].flags & ZT_FLAG_RUNNING)) + if (!(p->tor->spans[0].flags & ZT_FLAG_RUNNING) && + !(p->tor->spans[1].flags & ZT_FLAG_RUNNING) && + !(p->tor->spans[2].flags & ZT_FLAG_RUNNING) && + !(p->tor->spans[3].flags & ZT_FLAG_RUNNING)) /* No longer in use, disable interrupts */ p->tor->mem8[CTLREG] = 0; if (debug) @@ -772,14 +780,14 @@ static int tor2_startup(struct zt_span *span) alreadyrunning = span->flags & ZT_FLAG_RUNNING; /* initialize the start value for the entire chunk of last ec buffer */ - for(i = 0; i < span->channels; i++) + for (i = 0; i < span->channels; i++) { memset(p->tor->ec_chunk1[p->span][i], ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); memset(p->tor->ec_chunk2[p->span][i], ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); } - /* Force re-evaluation fo timing source */ + /* Force re-evaluation of the timing source */ if (timingcable) p->tor->syncsrc = -1; @@ -795,11 +803,17 @@ static int tor2_startup(struct zt_span *span) t1out(p->tor,tspan, i, 0); /* Set up for Interleaved Serial Bus operation in byte mode */ - if (tspan == 1) t1out(p->tor,tspan,0xb5,9); - else t1out(p->tor,tspan,0xb5,8); + /* Set up all the spans every time, so we are sure they are + in a consistent state. If we don't, a card without all + its spans configured misbehaves in strange ways. */ + t1out(p->tor,1,0xb5,9); + t1out(p->tor,2,0xb5,8); + t1out(p->tor,3,0xb5,8); + t1out(p->tor,4,0xb5,8); + t1out(p->tor,tspan,0x1a,4); /* CCR2: set LOTCMC */ - for(i = 0; i <= 8; i++) t1out(p->tor,tspan,i,0); - for(i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(p->tor,tspan,i,0); + for (i = 0; i <= 8; i++) t1out(p->tor,tspan,i,0); + for (i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(p->tor,tspan,i,0); t1out(p->tor,tspan,0x10,0x20); /* RCR1: Rsync as input */ t1out(p->tor,tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ t1out(p->tor,tspan,0x12,9); /* TCR1: TSiS mode */ @@ -831,12 +845,12 @@ static int tor2_startup(struct zt_span *span) t1out(p->tor,tspan,0x20,0x1b); /* TAFR */ t1out(p->tor,tspan,0x21,0x5f); /* TNAFR */ t1out(p->tor,tspan,0x40,0xb); /* TSR1 */ - for(i = 0x41; i <= 0x4f; i++) t1out(p->tor,tspan,i,0x55); - for(i = 0x22; i <= 0x25; i++) t1out(p->tor,tspan,i,0xff); + for (i = 0x41; i <= 0x4f; i++) t1out(p->tor,tspan,i,0x55); + for (i = 0x22; i <= 0x25; i++) t1out(p->tor,tspan,i,0xff); /* Wait 100 ms */ endjif = jiffies + 10; spin_unlock_irqrestore(&p->tor->lock, flags); - while(jiffies < endjif); /* wait 100 ms */ + while (jiffies < endjif); /* wait 100 ms */ spin_lock_irqsave(&p->tor->lock, flags); t1out(p->tor,tspan,0x1b,0x9a); /* CCR3: set also ESR */ t1out(p->tor,tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ @@ -867,8 +881,13 @@ static int tor2_startup(struct zt_span *span) t1out(p->tor,tspan, i, 0); /* Set up for Interleaved Serial Bus operation in byte mode */ - if (tspan == 1) t1out(p->tor,tspan,0x94,9); - else t1out(p->tor,tspan,0x94,8); + /* Set up all the spans every time, so we are sure they are + in a consistent state. If we don't, a card without all + its spans configured misbehaves in strange ways. */ + t1out(p->tor,1,0x94,9); + t1out(p->tor,2,0x94,8); + t1out(p->tor,3,0x94,8); + t1out(p->tor,4,0x94,8); /* Full-on Sync required (RCR1) */ t1out(p->tor,tspan, 0x2b, 8); /* RSYNC is an input (RCR2) */ @@ -915,7 +934,7 @@ static int tor2_startup(struct zt_span *span) spin_unlock_irqrestore(&p->tor->lock, flags); - while(jiffies < endjif); /* wait 100 ms */ + while (jiffies < endjif); /* wait 100 ms */ spin_lock_irqsave(&p->tor->lock, flags); @@ -1010,7 +1029,7 @@ static int tor2_maint(struct zt_span *span, int cmd) static inline void tor2_run(struct tor2 *tor) { int x,y; - for (x=0;x<4;x++) { + for (x = 0; x < SPANS_PER_CARD; x++) { if (tor->spans[x].flags & ZT_FLAG_RUNNING) { /* since the Tormenta 2 PCI is double-buffered, you need to delay the transmit data 2 entire chunks so @@ -1028,7 +1047,7 @@ static inline void tor2_run(struct tor2 *tor) zt_receive(&tor->spans[x]); } } - for (x=0;x<4;x++) { + for (x = 0; x < SPANS_PER_CARD; x++) { if (tor->spans[x].flags & ZT_FLAG_RUNNING) zt_transmit(&tor->spans[x]); } @@ -1068,10 +1087,10 @@ static int tor2_findsync(struct tor2 *tor) /* If we're the first card, go through all the motions, up to 8 levels of sync source */ p = 1; - while(p < 8) { + while (p < 8) { nonzero = 0; for (x=0;cards[x];x++) { - for (i=0;i<4;i++) { + for (i = 0; i < SPANS_PER_CARD; i++) { if (cards[x]->syncpos[i]) { nonzero = 1; if ((cards[x]->syncpos[i] == p) && @@ -1105,7 +1124,7 @@ found: if (tor->syncsrc != syncsrc) { tor->syncsrc = syncsrc; /* Update sync sources */ - for(i = 0; i < 4; i++) { + for (i = 0; i < SPANS_PER_CARD; i++) { tor->spans[i].syncsrc = tor->syncsrc; } if (syncnum == tor->num) { @@ -1156,8 +1175,8 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) #endif /* do the transmit output */ - for(n = 0; n < tor->spans[0].channels; n++) { - for(i = 0; i < ZT_CHUNKSIZE; i++) { + for (n = 0; n < tor->spans[0].channels; n++) { + for (i = 0; i < ZT_CHUNKSIZE; i++) { /* span 1 */ txword = tor->spans[0].chans[n].writechunk[i] << 24; /* span 2 */ @@ -1172,8 +1191,8 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) } /* Do the receive input */ - for(n = 0; n < tor->spans[0].channels; n++) { - for(i = 0; i < ZT_CHUNKSIZE; i++) { + for (n = 0; n < tor->spans[0].channels; n++) { + for (i = 0; i < ZT_CHUNKSIZE; i++) { /* read from */ rxword = le32_to_cpu(tor->mem32[tor->datxlt[n] + (32 * i)]); /* span 1 */ @@ -1190,9 +1209,8 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) i = tor->passno & 15; /* if an E1 card, do rx signalling for it */ if ((i < 3) && (tor->cardtype == TYPE_E1)) { /* if an E1 card */ - for(j = (i * 5); j < (i * 5) + 5; j++) - { - for(k = 1; k <= 4; k++) { + for (j = (i * 5); j < (i * 5) + 5; j++) { + for (k = 1; k <= SPANS_PER_CARD; k++) { c = t1in(tor,k,0x31 + j); rxc = c & 15; if (rxc != tor->spans[k - 1].chans[j + 16].rxsig) { @@ -1231,7 +1249,7 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) } } - for(i = 0; i < 4; i++) { /* Go thru all 4 spans */ + for (i = 0; i < SPANS_PER_CARD; i++) { /* Go thru all the spans */ /* if alarm timer, and it's timed out */ if (tor->alarmtimer[i]) { if (!--tor->alarmtimer[i]) { @@ -1308,7 +1326,7 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) if (tor->spans[i].lineconfig & ZT_CONFIG_NOTOPEN) { /* go thru all chans, and count # open */ - for(n = 0,k = 0; k < tor->spans[i].channels; k++) + for (n = 0,k = 0; k < tor->spans[i].channels; k++) { if (((tor->chans[i] + k)->flags & ZT_FLAG_OPEN) || ((tor->chans[i] + k)->flags & ZT_FLAG_NETDEV)) n++; @@ -1347,14 +1365,24 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) if (!(tor->passno % 1000)) /* even second boundary */ { /* do all spans */ - for(i = 1; i <= 4; i++) + for (i = 1; i <= SPANS_PER_CARD; i++) { if (tor->cardtype == TYPE_E1) + { /* add this second's BPV count to total one */ tor->spans[i - 1].bpvcount += t1in(tor,i,1) + (t1in(tor,i,0) << 8); + if (tor->spans[i - 1].lineconfig & ZT_CONFIG_CRC4) + { + tor->spans[i - 1].crc4count += t1in(tor,i,3) + ((t1in(tor,i,2) & 3) << 8); + tor->spans[i - 1].ebitcount += t1in(tor,i,5) + ((t1in(tor,i,4) & 3) << 8); + } + tor->spans[i - 1].fascount += (t1in(tor,i,4) >> 2) + ((t1in(tor,i,2) & 0x3F) << 6); + } else + { /* add this second's BPV count to total one */ tor->spans[i - 1].bpvcount += t1in(tor,i,0x24) + (t1in(tor,i,0x23) << 8); + } } } if (!timingcable) { @@ -1372,7 +1400,7 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) } } /* if any others specified, see if we can use them */ - for(i = 1; i < 4; i++) { + for (i = 1; i < SPANS_PER_CARD; i++) { /* if we dont have one yet, and there is one specified at this level, see if we can use it */ if ((!tor->syncsrc) && (tor->psyncs[i])) { /* if no alarms, use it */ @@ -1384,7 +1412,7 @@ static void tor2_intr(int irq, void *dev_id, struct pt_regs *regs) } } /* update sync src info */ - for(i = 0; i < 4; i++) tor->spans[i].syncsrc = syncsrc; + for (i = 0; i < SPANS_PER_CARD; i++) tor->spans[i].syncsrc = syncsrc; /* actually set the sync register */ tor->mem8[SYNCREG] = tor->syncsrc; @@ -1424,7 +1452,7 @@ static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data } MODULE_AUTHOR("Mark Spencer"); -MODULE_DESCRIPTION("Tormenta 2 PCI Driver"); +MODULE_DESCRIPTION("Tormenta 2 PCI Quad T1 or E1 Zaptel Driver"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif |