📄 tor2.c
字号:
return -ENOSYS; default: printk("Tor2: Unknown maint command: %d\n", cmd); break; } return 0; } switch(cmd) { case ZT_MAINT_NONE: t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x0a,0); /* no remote loop */ break; case ZT_MAINT_LOCALLOOP: t1out(p->tor,tspan,0x19,0x40 | (japan ? 0x80 : 0x00)); /* local loop */ t1out(p->tor,tspan,0x0a,0); /* no remote loop */ break; case ZT_MAINT_REMOTELOOP: t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x0a,0x40); /* remote loop */ break; case ZT_MAINT_LOOPUP: t1out(p->tor,tspan,0x30,2); /* send loopup code */ t1out(p->tor,tspan,0x12,0x22); /* send loopup code */ t1out(p->tor,tspan,0x13,0x80); /* send loopup code */ break; case ZT_MAINT_LOOPDOWN: t1out(p->tor,tspan,0x30,2); /* send loopdown code */ t1out(p->tor,tspan,0x12,0x62); /* send loopdown code */ t1out(p->tor,tspan,0x13,0x90); /* send loopdown code */ break; case ZT_MAINT_LOOPSTOP: t1out(p->tor,tspan,0x30,0); /* stop sending loopup code */ break; default: printk("Tor2: Unknown maint command: %d\n", cmd); break; } return 0;}static inline void tor2_run(struct tor2 *tor){ int x,y; 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 that the transmit will be in sync with the receive */ for (y=0;y<tor->spans[x].channels;y++) { zt_ec_chunk(&tor->spans[x].chans[y], tor->spans[x].chans[y].readchunk, tor->ec_chunk2[x][y]); memcpy(tor->ec_chunk2[x][y],tor->ec_chunk1[x][y], ZT_CHUNKSIZE); memcpy(tor->ec_chunk1[x][y], tor->spans[x].chans[y].writechunk, ZT_CHUNKSIZE); } zt_receive(&tor->spans[x]); } } for (x = 0; x < SPANS_PER_CARD; x++) { if (tor->spans[x].flags & ZT_FLAG_RUNNING) zt_transmit(&tor->spans[x]); }}#ifdef ENABLE_TASKLETSstatic void tor2_tasklet(unsigned long data){ struct tor2 *tor = (struct tor2 *)data; tor->taskletrun++; if (tor->taskletpending) { tor->taskletexec++; tor2_run(tor); } tor->taskletpending = 0;}#endifstatic int syncsrc = 0;static int syncnum = 0 /* -1 */;static int syncspan = 0;static spinlock_t synclock = SPIN_LOCK_UNLOCKED;static int tor2_findsync(struct tor2 *tor){ int i; int x; unsigned long flags; int p; int nonzero; int newsyncsrc = 0; /* Zaptel span number */ int newsyncnum = 0; /* tor2 card number */ int newsyncspan = 0; /* span on given tor2 card */ spin_lock_irqsave(&synclock, flags);#if 1 if (!tor->num) { /* If we're the first card, go through all the motions, up to 8 levels of sync source */ p = 1; while (p < 8) { nonzero = 0; for (x=0;cards[x];x++) { for (i = 0; i < SPANS_PER_CARD; i++) { if (cards[x]->syncpos[i]) { nonzero = 1; if ((cards[x]->syncpos[i] == p) && !(cards[x]->spans[i].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && (cards[x]->spans[i].flags & ZT_FLAG_RUNNING)) { /* This makes a good sync source */ newsyncsrc = cards[x]->spans[i].spanno; newsyncnum = x; newsyncspan = i + 1; /* Jump out */ goto found; } } } } if (nonzero) p++; else break; }found: if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { syncnum = newsyncnum; syncsrc = newsyncsrc; syncspan = newsyncspan; if (debug) printk("New syncnum: %d, syncsrc: %d, syncspan: %d\n", syncnum, syncsrc, syncspan); } }#endif /* update sync src info */ if (tor->syncsrc != syncsrc) { tor->syncsrc = syncsrc; /* Update sync sources */ for (i = 0; i < SPANS_PER_CARD; i++) { tor->spans[i].syncsrc = tor->syncsrc; } if (syncnum == tor->num) {#if 1 /* actually set the sync register */ tor->mem8[SYNCREG] = syncspan;#endif if (debug) printk("Card %d, using sync span %d, master\n", tor->num, syncspan); tor->master = MASTER; } else {#if 1 /* time from the timing cable */ tor->mem8[SYNCREG] = SYNCEXTERN;#endif tor->master = 0; if (debug) printk("Card %d, using Timing Bus, NOT master\n", tor->num); } } spin_unlock_irqrestore(&synclock, flags); return 0;}#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{ int n, i, j, k, syncsrc; unsigned long rxword,txword; unsigned char c, rxc; unsigned char abits, bbits; struct tor2 *tor = (struct tor2 *) dev_id; /* make sure its a real interrupt for us */ if (!(tor->mem8[STATREG] & INTACTIVE)) /* if not, just return */ {#ifdef LINUX26 return IRQ_NONE;#else return; #endif } if (tor->cardtype == TYPE_E1) /* set outbit, interrupt enable, and ack interrupt */ tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | E1DIV | tor->master; else /* set outbit, interrupt enable, and ack interrupt */ tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | tor->master;#if 0 if (!tor->passno) printk("Interrupt handler\n");#endif /* do the transmit output */ 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 */ txword |= tor->spans[1].chans[n].writechunk[i] << 16; /* span 3 */ txword |= tor->spans[2].chans[n].writechunk[i] << 8; /* span 4 */ txword |= tor->spans[3].chans[n].writechunk[i]; /* write to part */ tor->mem32[tor->datxlt[n] + (32 * i)] = cpu_to_le32(txword); } } /* Do the receive input */ 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 */ tor->spans[0].chans[n].readchunk[i] = rxword >> 24; /* span 2 */ tor->spans[1].chans[n].readchunk[i] = (rxword & 0xff0000) >> 16; /* span 3 */ tor->spans[2].chans[n].readchunk[i] = (rxword & 0xff00) >> 8; /* span 4 */ tor->spans[3].chans[n].readchunk[i] = rxword & 0xff; } } 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 <= SPANS_PER_CARD; k++) { c = t1in(tor,k,0x31 + j); rxc = c & 15; if (rxc != tor->spans[k - 1].chans[j + 16].rxsig) { /* Check for changes in received bits */ if (!(tor->spans[k - 1].chans[j + 16].sig & ZT_SIG_CLEAR)) zt_rbsbits(&tor->spans[k - 1].chans[j + 16], rxc); } rxc = c >> 4; if (rxc != tor->spans[k - 1].chans[j].rxsig) { /* Check for changes in received bits */ if (!(tor->spans[k - 1].chans[j].sig & ZT_SIG_CLEAR)) zt_rbsbits(&tor->spans[k - 1].chans[j], rxc); } } } } /* if a T1, do the signalling */ if ((i < 12) && (tor->cardtype == TYPE_T1)) { k = (i / 3); /* get span */ n = (i % 3); /* get base */ abits = t1in(tor,k + 1, 0x60 + n); bbits = t1in(tor,k + 1, 0x63 + n); for (j=0; j< 8; j++) { /* Get channel number */ i = (n * 8) + j; rxc = 0; if (abits & (1 << j)) rxc |= ZT_ABIT; if (bbits & (1 << j)) rxc |= ZT_BBIT; if (tor->spans[k].chans[i].rxsig != rxc) { /* Check for changes in received bits */ if (!(tor->spans[k].chans[i].sig & ZT_SIG_CLEAR)) { zt_rbsbits(&tor->spans[k].chans[i], rxc); } } } } 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]) { /* clear recover status */ tor->spans[i].alarms &= ~ZT_ALARM_RECOVER; if (tor->cardtype == TYPE_E1) t1out(tor,i + 1,0x21,0x5f); /* turn off yel */ else t1out(tor,i + 1,0x35,0x10); /* turn off yel */ zt_alarm_notify(&tor->spans[i]); /* let them know */ } } } i = tor->passno & 15; if ((i >= 10) && (i <= 13) && !(tor->passno & 0x30)) { j = 0; /* clear this alarm status */ i -= 10; if (tor->cardtype == TYPE_T1) { c = t1in(tor,i + 1,0x31); /* get RIR2 */ tor->spans[i].rxlevel = c >> 6; /* get rx level */ t1out(tor,i + 1,0x20,0xff); c = t1in(tor,i + 1,0x20); /* get the status */ /* detect the code, only if we are not sending one */ if ((!tor->spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ { /* set into remote loop, if not there already */ if ((tor->loopupcnt[i]++ > 80) && (tor->spans[i].maintstat != ZT_MAINT_REMOTELOOP)) { t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(tor,i + 1,0x0a,0x40); /* remote loop */ tor->spans[i].maintstat = ZT_MAINT_REMOTELOOP; } } else tor->loopupcnt[i] = 0; /* detect the code, only if we are not sending one */ if ((!tor->spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ { /* if in remote loop, get out of it */ if ((tor->loopdowncnt[i]++ > 80) && (tor->spans[i].maintstat == ZT_MAINT_REMOTELOOP)) { t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(tor,i + 1,0x0a,0); /* no remote loop */ tor->spans[i].maintstat = ZT_MAINT_NONE; } } else tor->loopdowncnt[i] = 0; if (c & 3) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 8) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } else { /* its an E1 card */ t1out(tor,i + 1,6,0xff); c = t1in(tor,i + 1,6); /* get the status */ if (c & 9) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 2) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } /* only consider previous carrier alarm state */ tor->spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); n = 1; /* set to 1 so will not be in yellow alarm if we dont care about open channels */ /* if to have yellow alarm if nothing open */ 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++) { if (((tor->chans[i] + k)->flags & ZT_FLAG_OPEN) || ((tor->chans[i] + k)->flags & ZT_FLAG_NETDEV)) n++; } /* if none open, set alarm condition */ if (!n) j |= ZT_ALARM_NOTOPEN; } /* if no more alarms, and we had some */ if ((!j) && tor->spans[i].alarms) { tor->alarmtimer[i] = ZT_ALARMSETTLE_TIME; } if (tor->alarmtimer[i]) j |= ZT_ALARM_RECOVER; /* if going into alarm state, set yellow alarm */ if ((j) && (!tor->spans[i].alarms)) { if (tor->cardtype == TYPE_E1) t1out(tor,i + 1,0x21,0x7f); else t1out(tor,i + 1,0x35,0x11); } if (c & 4) /* if yellow alarm */ j |= ZT_ALARM_YELLOW; if (tor->spans[i].maintstat || tor->spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; tor->spans[i].alarms = j; c = (LEDRED | LEDGREEN) << (2 * i); tor->leds &= ~c; /* mask out bits for this span */ /* light LED's if span configured and running */ if (tor->spans[i].flags & ZT_FLAG_RUNNING) { if (j & ZT_ALARM_RED) tor->leds |= LEDRED << (2 * i); else if (j & ZT_ALARM_YELLOW) tor->leds |= (LEDRED | LEDGREEN) << (2 * i); else tor->leds |= LEDGREEN << (2 * i); } tor->mem8[LEDREG] = tor->leds; zt_alarm_notify(&tor->spans[i]); } if (!(tor->passno % 1000)) /* even second boundary */ { /* do all spans */ 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) { /* re-evaluate active sync src (no cable version) */ tor->syncsrc = 0; syncsrc = 0; /* if primary sync specified, see if we can use it */ if (tor->psyncs[0]) { /* if no alarms, use it */ if (!(tor->spans[tor->psyncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) { tor->syncsrc = tor->psyncs[0]; syncsrc = tor->syncs[0]; } } /* if any others specified, see if we can use them */ 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 */ if (!(tor->spans[tor->psyncs[i] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) { tor->syncsrc = tor->psyncs[i]; syncsrc = tor->syncs[i]; } } } /* update sync src info */ for (i = 0; i < SPANS_PER_CARD; i++) tor->spans[i].syncsrc = syncsrc; /* actually set the sync register */ tor->mem8[SYNCREG] = tor->syncsrc; } else /* Timing cable version */ tor2_findsync(tor); tor->passno++;#ifdef ENABLE_TASKLETS if (!tor->taskletpending) { tor->taskletpending = 1; tor->taskletsched++; tasklet_hi_schedule(&tor->tor2_tlet); } else { tor->txerrors++; }#else tor2_run(tor);#endif /* We are not the timing bus master */ if (tor->cardtype == TYPE_E1) /* clear OUTBIT and enable interrupts */ tor->mem8[CTLREG] = INTENA | E1DIV | tor->master; else /* clear OUTBIT and enable interrupts */ tor->mem8[CTLREG] = INTENA | tor->master;#ifdef LINUX26 return IRQ_RETVAL(1);#endif}static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data){ switch(cmd) { default: return -ENOTTY; } return 0;}MODULE_AUTHOR("Mark Spencer");MODULE_DESCRIPTION("Tormenta 2 PCI Quad T1 or E1 Zaptel Driver");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif#ifdef LINUX26module_param(debug, int, 0600);module_param(loopback, int, 0600);module_param(timingcable, int, 0600);module_param(japan, int, 0600);#elseMODULE_PARM(debug, "i");MODULE_PARM(loopback, "i");MODULE_PARM(timingcable, "i");MODULE_PARM(japan, "i");#endifMODULE_DEVICE_TABLE(pci, tor2_pci_ids);module_init(tor2_init);module_exit(tor2_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -