[Asterisk-cvs] zaptel wct4xxp.c,1.51.2.14,1.51.2.15

kpfleming kpfleming
Mon Aug 22 11:30:48 CDT 2005


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

Modified Files:
      Tag: v1-0
	wct4xxp.c 
Log Message:
backport all fixes from HEAD


Index: wct4xxp.c
===================================================================
RCS file: /usr/cvsroot/zaptel/wct4xxp.c,v
retrieving revision 1.51.2.14
retrieving revision 1.51.2.15
diff -u -d -r1.51.2.14 -r1.51.2.15
--- wct4xxp.c	18 Aug 2005 00:15:59 -0000	1.51.2.14
+++ wct4xxp.c	22 Aug 2005 15:32:55 -0000	1.51.2.15
@@ -56,7 +56,12 @@
 
 /* Work queues are a way to better distribute load on SMP systems */
 #ifdef LINUX26
-#define ENABLE_WORKQUEUES
+/*
+ * Work queues can significantly improve performance and scalability
+ * on multi-processor machines, but requires bypassing some kernel
+ * API's, so it's not guaranteed to be compatible with all kernels.
+ */
+/* #define ENABLE_WORKQUEUES */
 #endif
 
 /* Enable prefetching may help performance */
@@ -169,8 +174,15 @@
 static int alarmdebounce = 0;
 #ifdef VPM_SUPPORT
 static int vpmsupport = 1;
+#define VPM_DEFAULT_DTMFTHRESHOLD 1000
+static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
+static int lastdtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
 #endif
-static int noburst = 0;
+/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but
+   can also cause PCI bus starvation, especially in combination with other
+   aggressive cards.  Please note that burst mode has no effect on CPU
+   utilization / max number of calls / etc. */
+static int noburst = 1;
 static int debugslips = 0;
 static int polling = 0;
 
@@ -310,6 +322,7 @@
 
 #ifdef VPM_SUPPORT
 static void t4_vpm_init(struct t4 *wc);
+static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold);
 #endif
 static void __set_clear(struct t4 *wc, int span);
 static int t4_startup(struct zt_span *span);
@@ -523,9 +536,12 @@
 	spin_unlock_irqrestore(&wc->reglock, flags);
 }
 
+static const char vpm_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', '*', '#'};
+
 static void __t4_check_vpm(struct t4 *wc, unsigned int newio)
 {
 	unsigned int digit, regval = 0;
+	unsigned int regbyte;
 	int x, i;
 	short energy;
 	static unsigned int lastio = 0;
@@ -541,27 +557,22 @@
 			continue;
 		ts = wc->tspans[x%4];
 		/* Start of DTMF detection process */	
-		regval = __t4_vpm_in(wc, x, 0xb8);
-		__t4_vpm_out(wc, x, 0xb8, regval); /* Write 1 to clear */
-		regval = regval << 8;
-		regval |= __t4_vpm_in(wc, x, 0xb9);
-		__t4_vpm_out(wc, x, 0xb9, regval & 0xff);
+		regbyte = __t4_vpm_in(wc, x, 0xb8);
+		__t4_vpm_out(wc, x, 0xb8, regbyte); /* Write 1 to clear */
+		regval = regbyte << 8;
+		regbyte = __t4_vpm_in(wc, x, 0xb9);
+		__t4_vpm_out(wc, x, 0xb9, regbyte);
+		regval |= regbyte;
 
 		for(i = 0; (i < MAX_DTMF_DET) && regval; i++) {
 			if(regval & 0x0001) {
 				int channel = (i << 1) + (x >> 2);
 				int base = channel - 1;
+
 				if (!wc->t1e1)
 					base -= 4;
-				digit = __t4_vpm_in(wc, x, 0xa8 + i);
-				if (digit < 10) 
-					digit += '0'; 
-				else if (digit < 0xe) 
-					digit += 'A' - 0xe; 
-				else if (digit == 0xe) 
-					digit = '*';
-				else if (digit == 0xf) 
-					digit = '#';
+				regbyte = __t4_vpm_in(wc, x, 0xa8 + i);
+				digit = vpm_digits[regbyte];
 				energy = __t4_vpm_in(wc, x, 0x58 + channel);
 				energy = ZT_XLAW(energy, ts->chans);
 				ts->dtmfactive |= (1 << base);
@@ -571,10 +582,6 @@
 						zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
 				}
 				ts->dtmfdigit[base] = digit;
-				if (ts->dtmfdigit[base]) {
-					if (ts->dtmfmask & (1 << base))
-						zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
-				}
 				if (ts->dtmfmask & (1 << base))
 					zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFDOWN | digit));
 				if (ts->dtmfmutemask & (1 << base)) {
@@ -584,7 +591,7 @@
 					int y;
 					spin_lock_irqsave(&chan->lock, flags);
 					for (y=0;y<chan->numbufs;y++) {
-						if (chan->readidx[y]) 
+						if ((chan->inreadbuf > -1) && (chan->readidx[y]))
 							memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]);
 					}
 					spin_unlock_irqrestore(&chan->lock, flags);
@@ -719,9 +726,17 @@
 	struct t4_span *ts = wc->tspans[chan->span->offset];
 #endif
 
+#ifdef VPM_SUPPORT
+	if (dtmfthreshold == 0)
+		dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
+	if (lastdtmfthreshold != dtmfthreshold) {
+		lastdtmfthreshold = dtmfthreshold;
+		t4_vpm_set_dtmf_threshold(wc, dtmfthreshold);
+	}
+#endif
+
 	switch(cmd) {
 	case WCT4_GET_REGS:
-		wc = chan->pvt;
 		for (x=0;x<NUM_PCI;x++)
 			regs.pci[x] = t4_pci_in(wc, x);
 		for (x=0;x<NUM_REGS;x++)
@@ -737,7 +752,6 @@
 	case ZT_TONEDETECT:
 		if (get_user(j, (int *)data))
 			return -EFAULT;
-		wc = chan->pvt;
 		if (!wc->vpm)
 			return -ENOSYS;
 		if (j & ZT_TONEDETECT_ON)
@@ -2283,25 +2297,36 @@
 #endif
 
 #ifdef VPM_SUPPORT
+static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold)
+{
+	unsigned int x;
+
+	for (x = 0; x < 8; x++) {
+		t4_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF);
+		t4_vpm_out(wc, x, 0xC5, (threshold & 0xFF));
+	}
+	printk("VPM: DTMF threshold set to %d\n", threshold);
+}
+
 static void t4_vpm_init(struct t4 *wc)
 {
 	unsigned char reg;
 	unsigned int mask;
 	unsigned int ver;
-	int i,x,y;
+	unsigned int i, x, y;
+
 	if (!vpmsupport) {
 		printk("VPM: Support Disabled\n");
 		return;
 	}
 
 	for (x=0;x<8;x++) {
-		struct t4_span *ts = wc->tspans[x & 0x3];
+		int spanno = x & 0x3;
+		struct t4_span *ts = wc->tspans[spanno];
+
 		ver = t4_vpm_in(wc, x, 0x1a0); /* revision */
 		if (ver != 0x26) {
-			if (x)
-				printk("VPM: Inopperable\n");
-			else
-				printk("VPM: Not Present\n");
+			printk("VPM: %s\n", x ? "Inoperable" : "Not Present");
 			return;
 		}	
 
@@ -2317,36 +2342,33 @@
 		t4_vpm_out(wc, x, 0x1a3, reg & ~2);
 
 		/* Setup timeslots */
-		t4_vpm_out(wc, x, 0x02f, 0x20 | ((x%4) << 3)); 
-		if (x < 4)
-			mask = 0x55555555;
-		else
-			mask = 0xaaaaaaaa;
+		t4_vpm_out(wc, x, 0x02f, 0x20 | (spanno << 3)); 
 
 		/* Setup Echo length (128 taps) */
 		t4_vpm_out(wc, x, 0x022, 0x00);
 		t4_vpm_out(wc, x, 0x023, 0x7f);
 		
-		/* Setup the tdm channel masks for all LV's*/
-		for (i=0;i<4;i++)
-			t4_vpm_out(wc, x, 0x30+i, (mask >> (i << 3)) & 0xff);
+		/* Setup the tdm channel masks for all chips*/
+		mask = (x < 4) ? 0x55555555 : 0xaaaaaaaa;
+		for (i = 0; i < 4; i++)
+			t4_vpm_out(wc, x, 0x30 + i, (mask >> (i << 3)) & 0xff);
 
 		/* Setup convergence rate */
 		reg = t4_vpm_in(wc,x,0x20);
 		reg &= 0xE0;
 		if (ts->spantype == TYPE_E1) {
 			if (x < 4)
-				printk("VPM: Span %d A-law mode\n", x & 0x3);
+				printk("VPM: Span %d A-law mode\n", spanno);
 			reg |= 0x01;
 		} else {
 			if (x < 4)
-				printk("VPM: Span %d U-law mode\n", x & 0x3);
+				printk("VPM: Span %d U-law mode\n", spanno);
 			reg &= ~0x01;
 		}
 		t4_vpm_out(wc,x,0x20,(reg | 0x20));
 		
 		/* Initialize echo cans */
-		for (i = 0 ; i < MAX_TDM_CHAN ; i++) {
+		for (i = 0 ; i < MAX_TDM_CHAN; i++) {
 			if (mask & (0x00000001 << i))
 				t4_vpm_out(wc,x,i,0x00);
 		}
@@ -2366,25 +2388,21 @@
 				t4_vpm_out(wc,x,0x78 + i,0x01);
 		}
       
-        /* Enable DTMF detectors */
-		for (i=0;i<MAX_DTMF_DET;i++) {
-			if(x < 4)
-				t4_vpm_out(wc, x, 0x98+i,(i*2)|0x40);
-			else
-				t4_vpm_out(wc, x, 0x98+i, ((i*2)+1)|0x40);
-        }
-		for (i=0xb8;i<0xbe;i++)
-			t4_vpm_out(wc, x, i, 0xff);
-		if(x < 4) {
-			for(i=0;i<4;i++)
-				t4_vpm_out(wc, x, 0xc0+i, 0x55);
-		} else {
-			for(i = 0; i < 4; i++)
-				t4_vpm_out(wc, x, 0xc0+i, 0xaa);
+		/* set DTMF detection threshold */
+		t4_vpm_set_dtmf_threshold(wc, dtmfthreshold);
+
+		/* Enable DTMF detectors */
+		for (i = 0; i < MAX_DTMF_DET; i++) {
+			t4_vpm_out(wc, x, 0x98 + i, 0x40 | (i * 2) | ((x < 4) ? 0 : 1));
 		}
-   } 
-   printk("VPM: Present and operational\n");
-   wc->vpm = T4_VPM_PRESENT;
+		for (i = 0xB8; i < 0xBE; i++)
+			t4_vpm_out(wc, x, i, 0xFF);
+		for (i = 0xC0; i < 0xC4; i++)
+			t4_vpm_out(wc, x, i, (x < 4) ? 0x55 : 0xAA);
+
+	} 
+	printk("VPM: Present and operational\n");
+	wc->vpm = T4_VPM_PRESENT;
 }
 
 #endif
@@ -2851,7 +2869,7 @@
 
 
 MODULE_AUTHOR("Mark Spencer");
-MODULE_DESCRIPTION("Unified TE4XXP/TE2XXP PCI Driver");
+MODULE_DESCRIPTION("Unified TE4XXP-TE2XXP PCI Driver");
 #ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
 #endif
@@ -2867,6 +2885,7 @@
 module_param(j1mode, int, 0600);
 #ifdef VPM_SUPPORT
 module_param(vpmsupport, int, 0600);
+module_param(dtmfthreshold, int, 0600);
 #endif
 #else
 MODULE_PARM(debug, "i");
@@ -2880,6 +2899,7 @@
 MODULE_PARM(j1mode, "i");
 #ifdef VPM_SUPPORT
 MODULE_PARM(vpmsupport, "i");
+MODULE_PARM(dtmfthreshold, "i");
 #endif
 #endif
 
@@ -2887,4 +2907,3 @@
 
 module_init(t4_init);
 module_exit(t4_cleanup);
-




More information about the svn-commits mailing list