[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