[Asterisk-cvs] zaptel wct4xxp.c,1.13,1.14

markster at lists.digium.com markster at lists.digium.com
Thu Nov 20 18:40:41 CST 2003


Update of /usr/cvsroot/zaptel
In directory mongoose.digium.com:/tmp/cvs-serv12541

Modified Files:
	wct4xxp.c 
Log Message:
Detect E1 alignment errors and fix alignment


Index: wct4xxp.c
===================================================================
RCS file: /usr/cvsroot/zaptel/wct4xxp.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- wct4xxp.c	13 Nov 2003 17:55:25 -0000	1.13
+++ wct4xxp.c	21 Nov 2003 01:07:00 -0000	1.14
@@ -100,7 +100,9 @@
 	int syncpos[4];			/* span-relative sync sources */
 	int master;				/* Are we master */
 	int ledreg;				/* LED Register */
+	int e1check[4];			/* E1 check */
 	unsigned int dmactrl;
+	int e1recover;			/* E1 recovery timer */
 	dma_addr_t 	readdma;
 	dma_addr_t	writedma;
 	unsigned long memaddr;		/* Base address of card */
@@ -138,6 +140,7 @@
 static int t4_shutdown(struct zt_span *span);
 static int t4_rbsbits(struct zt_chan *chan, int bits);
 static int t4_maint(struct zt_span *span, int cmd);
+static int t4_reset_dma(struct t4 *wc);
 static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data);
 
 #define WC_RDADDR	0
@@ -905,6 +908,27 @@
 	return 0;
 }
 
+static inline void e1_check(struct t4 *wc, int span, int val)
+{
+	if ((wc->spans[span].channels > 24) &&
+	    (wc->spans[span].flags & ZT_FLAG_RUNNING) &&
+	    !(wc->spans[span].alarms) &&
+	    (!wc->e1recover))   {
+		if (val != 0x1b) {
+			wc->e1check[span]++;
+		} else
+			wc->e1check[span] = 0;
+		if (wc->e1check[span] > 100) {
+			/* Wait 1000 ms */
+			wc->e1recover = 1000 * 8;
+			memset(wc->e1check, 0, sizeof(wc->e1check));
+			if (debug)
+				printk("Detected loss of E1 alignment on span %d!\n", span);
+			t4_reset_dma(wc);
+		}
+	}
+}
+
 static void t4_receiveprep(struct t4 *wc, int irq)
 {
 	volatile unsigned int *readchunk;
@@ -913,12 +937,12 @@
 	unsigned int tmp;
 	if (irq & 1) {
 		/* First part */
-		readchunk = wc->readchunk + 1;
+		readchunk = wc->readchunk;
 		if (!wc->last0) 
 			dbl = 1;
 		wc->last0 = 0;
 	} else {
-		readchunk = wc->readchunk + ZT_CHUNKSIZE * 32 + 1;
+		readchunk = wc->readchunk + ZT_CHUNKSIZE * 32;
 		if (wc->last0) 
 			dbl = 1;
 		wc->last0 = 1;
@@ -930,19 +954,25 @@
 			printk("TE410P: Double/missed interrupt detected\n");
 	}
 	for (x=0;x<ZT_CHUNKSIZE;x++) {
-		/* Once per chunk */
 		for (z=0;z<24;z++) {
 			/* All T1/E1 channels */
-			tmp = readchunk[z];
+			tmp = readchunk[z+1];
 			wc->spans[3].chans[z].readchunk[x] = tmp & 0xff;
 			wc->spans[2].chans[z].readchunk[x] = (tmp & 0xff00) >> 8;
 			wc->spans[1].chans[z].readchunk[x] = (tmp & 0xff0000) >> 16;
 			wc->spans[0].chans[z].readchunk[x] = tmp >> 24;
 		}
 		if (wc->t1e1) {
+			if (wc->e1recover > 0)
+				wc->e1recover--;
+			tmp = readchunk[0];
+			e1_check(wc, 3, (tmp & 0x7f));
+			e1_check(wc, 2, (tmp & 0x7f00) >> 8);
+			e1_check(wc, 1, (tmp & 0x7f0000) >> 16);
+			e1_check(wc, 0, (tmp & 0x7f000000) >> 24);
 			for (z=24;z<31;z++) {
 				/* Only E1 channels now */
-				tmp = readchunk[z];
+				tmp = readchunk[z+1];
 				if (wc->spans[3].channels > 24)
 					wc->spans[3].chans[z].readchunk[x] = tmp & 0xff;
 				if (wc->spans[2].channels > 24)
@@ -1353,6 +1383,25 @@
 
 	spin_unlock_irqrestore(&wc->reglock, flags);
 
+}
+
+static int t4_reset_dma(struct t4 *wc)
+{
+	/* Turn off DMA and such */
+	wc->dmactrl = 0x0;
+	t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
+	t4_pci_out(wc, WC_COUNT, 0);
+	t4_pci_out(wc, WC_RDADDR, 0);
+	t4_pci_out(wc, WC_WRADDR, 0);
+	t4_pci_out(wc, WC_INTR, 0);
+	/* Turn it all back on */
+	t4_pci_out(wc, WC_RDADDR, wc->readdma);
+	t4_pci_out(wc, WC_WRADDR, wc->writedma);
+	t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2));
+	t4_pci_out(wc, WC_INTR, 0);
+	wc->dmactrl = 0xc0000003 | (1 << 29);
+	t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
+	return 0;
 }
 
 static int t4_hardware_init(struct t4 *wc)




More information about the svn-commits mailing list