[zaptel-commits] trunk r964 - /trunk/wct4xxp.c
zaptel-commits at lists.digium.com
zaptel-commits at lists.digium.com
Mon Feb 20 23:40:49 MST 2006
Author: markster
Date: Tue Feb 21 00:40:48 2006
New Revision: 964
URL: http://svn.digium.com/view/zaptel?rev=964&view=rev
Log:
Add support for timing cable
Modified:
trunk/wct4xxp.c
Modified: trunk/wct4xxp.c
URL: http://svn.digium.com/view/zaptel/trunk/wct4xxp.c?rev=964&r1=963&r2=964&view=diff
==============================================================================
--- trunk/wct4xxp.c (original)
+++ trunk/wct4xxp.c Tue Feb 21 00:40:48 2006
@@ -168,7 +168,7 @@
#endif
static int debug=0;
-static int timingcable;
+static int timingcable = 0;
static int highestorder;
static int t1e1override = -1;
static int j1mode = 0;
@@ -350,7 +350,7 @@
static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data);
static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan);
static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan);
-static void __t4_set_timing_source(struct t4 *wc, int unit);
+static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave);
static void __t4_check_alarms(struct t4 *wc, int span);
static void __t4_check_sigbits(struct t4 *wc, int span);
@@ -1149,7 +1149,7 @@
__t4_pci_out(wc, WC_DMACTRL, 0x00000000);
/* Acknowledge any pending interrupts */
__t4_pci_out(wc, WC_INTR, 0x00000000);
- __t4_set_timing_source(wc,4);
+ __t4_set_timing_source(wc, 4, 0, 0);
} else wc->checktiming = 1;
spin_unlock_irqrestore(&wc->reglock, flags);
if (debug & DEBUG_MAIN)
@@ -1386,7 +1386,16 @@
printk("Successfully initialized serial bus for unit %d\n", unit);
}
-static void __t4_set_timing_source(struct t4 *wc, int unit)
+static int syncsrc = 0;
+static int syncnum = 0 /* -1 */;
+static int syncspan = 0;
+#ifdef DEFINE_SPINLOCK
+static DEFINE_SPINLOCK(synclock);
+#else
+static spinlock_t synclock = SPIN_LOCK_UNLOCKED;
+#endif
+
+static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave)
{
unsigned int timing;
int x;
@@ -1397,20 +1406,30 @@
for (x=0;x<wc->numspans;x++) /* set all 4 receive reference clocks to unit */
__t4_framer_out(wc, x, 0x44, timing);
wc->dmactrl |= (1 << 29);
- __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
} else {
for (x=0;x<wc->numspans;x++) /* set each receive reference clock to itself */
__t4_framer_out(wc, x, 0x44, timing | (x << 6));
wc->dmactrl &= ~(1 << 29);
- __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
- }
- wc->syncsrc = unit;
+ }
+ if (slave)
+ wc->dmactrl |= (1 << 25);
+ else
+ wc->dmactrl &= ~(1 << 25);
+ if (master)
+ wc->dmactrl |= (1 << 24);
+ else
+ wc->dmactrl &= ~(1 << 24);
+ __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
+ if (!master && !slave)
+ wc->syncsrc = unit;
if ((unit < 0) || (unit > 3))
unit = 0;
else
unit++;
- for (x=0;x<wc->numspans;x++)
- wc->tspans[x]->span.syncsrc = unit;
+ if (!master && !slave) {
+ for (x=0;x<wc->numspans;x++)
+ wc->tspans[x]->span.syncsrc = unit;
+ }
} else {
if (debug & DEBUG_MAIN)
printk("TE%dXXP: Timing source already set to %d\n", wc->numspans, unit);
@@ -1420,21 +1439,104 @@
#endif
}
+static inline void __t4_update_timing(struct t4 *wc)
+{
+ int i;
+ /* update sync src info */
+ if (wc->syncsrc != syncsrc) {
+ printk("Swapping card %d from %d to %d\n", wc->num, wc->syncsrc, syncsrc);
+ wc->syncsrc = syncsrc;
+ /* Update sync sources */
+ for (i = 0; i < 4; i++) {
+ wc->tspans[i]->span.syncsrc = wc->syncsrc;
+ }
+ if (syncnum == wc->num) {
+ __t4_set_timing_source(wc, syncspan-1, 1, 0);
+ if (debug) printk("Card %d, using sync span %d, master\n", wc->num, syncspan);
+ } else {
+ __t4_set_timing_source(wc, syncspan-1, 0, 1);
+ if (debug) printk("Card %d, using Timing Bus, NOT master\n", wc->num);
+ }
+ }
+}
+
+static int __t4_findsync(struct t4 *wc)
+{
+ int i;
+ int x;
+ unsigned long flags;
+ int p;
+ int nonzero;
+ int newsyncsrc = 0; /* Zaptel span number */
+ int newsyncnum = 0; /* wct4xxp card number */
+ int newsyncspan = 0; /* span on given wct4xxp card */
+ spin_lock_irqsave(&synclock, flags);
+#if 1
+ if (!wc->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 < 4; i++) {
+ if (cards[x]->tspans[i]->syncpos) {
+ nonzero = 1;
+ if ((cards[x]->tspans[i]->syncpos == p) &&
+ !(cards[x]->tspans[i]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) &&
+ (cards[x]->tspans[i]->span.flags & ZT_FLAG_RUNNING)) {
+ /* This makes a good sync source */
+ newsyncsrc = cards[x]->tspans[i]->span.spanno;
+ newsyncnum = x;
+ newsyncspan = i + 1;
+ /* Jump out */
+ goto found;
+ }
+ }
+ }
+ }
+ if (nonzero)
+ p++;
+ else
+ break;
+ }
+found:
+ if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) {
+ if (debug) printk("New syncnum: %d (was %d), syncsrc: %d (was %d), syncspan: %d (was %d)\n", newsyncnum, syncnum, newsyncsrc, syncsrc, newsyncspan, syncspan);
+ syncnum = newsyncnum;
+ syncsrc = newsyncsrc;
+ syncspan = newsyncspan;
+ for (x=0;cards[x];x++) {
+ __t4_update_timing(cards[x]);
+ }
+ }
+ } else
+ cards[0]->checktiming = 1;
+#endif
+ spin_unlock_irqrestore(&synclock, flags);
+ return 0;
+}
+
static void __t4_set_timing_source_auto(struct t4 *wc)
{
int x;
+ printk("timing source auto card %d!\n", wc->num);
wc->checktiming = 0;
- for (x=0;x<wc->numspans;x++) {
- if (wc->tspans[x]->sync) {
- if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & ZT_FLAG_RUNNING) &&
- !(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE) )) {
- /* Valid timing source */
- __t4_set_timing_source(wc, wc->tspans[x]->psync - 1);
- return;
- }
- }
- }
- __t4_set_timing_source(wc, 4);
+ if (timingcable) {
+ __t4_findsync(wc);
+ } else {
+ for (x=0;x<wc->numspans;x++) {
+ if (wc->tspans[x]->sync) {
+ if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & ZT_FLAG_RUNNING) &&
+ !(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE) )) {
+ /* Valid timing source */
+ __t4_set_timing_source(wc, wc->tspans[x]->psync - 1, 0, 0);
+ return;
+ }
+ }
+ }
+ __t4_set_timing_source(wc, 4, 0, 0);
+ }
}
static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlevel)
@@ -3006,7 +3108,7 @@
}
wc->checktiming = 1;
spin_lock_irqsave(&wc->reglock, flags);
- __t4_set_timing_source(wc,4);
+ __t4_set_timing_source(wc,4, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
#ifdef ENABLE_TASKLETS
tasklet_init(&wc->t4_tlet, t4_tasklet, (unsigned long)wc);
More information about the zaptel-commits
mailing list