[svn-commits] mattf: branch 1.4 r2946 - in /branches/1.4: ./ wct4xxp/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Aug 24 14:25:20 CDT 2007


Author: mattf
Date: Fri Aug 24 14:25:20 2007
New Revision: 2946

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2946
Log:
Beginning backport of trunk to 1.4

Modified:
    branches/1.4/wct4xxp/base.c
    branches/1.4/wct4xxp/wct4xxp.h
    branches/1.4/zaptel.h

Modified: branches/1.4/wct4xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/wct4xxp/base.c?view=diff&rev=2946&r1=2945&r2=2946
==============================================================================
--- branches/1.4/wct4xxp/base.c (original)
+++ branches/1.4/wct4xxp/base.c Fri Aug 24 14:25:20 2007
@@ -35,6 +35,8 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
+#include <linux/version.h>
+#include <linux/delay.h>
 #ifdef STANDALONE_ZAPATA
 #include "zaptel.h"
 #else
@@ -46,19 +48,6 @@
 
 #include "wct4xxp.h"
 #include "vpm450m.h"
-
-/*
- * Tasklets provide better system interactive response at the cost of the
- * possibility of losing a frame of data at very infrequent intervals.  If
- * you are more concerned with the performance of your machine, enable the
- * tasklets.  If you are strict about absolutely no drops, then do not enable
- * tasklets.
- *
- * XXX THIS IS NOT CURRENTLY IMPLEMENTED FOR THIS MODULE.  FOR NOW, DO NOT USE!
- */
-
-/* #define ENABLE_TASKLETS */
-
 
 /* Work queues are a way to better distribute load on SMP systems */
 #if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
@@ -92,7 +81,7 @@
 #define DEBUG_FRAMER		(1 << 6)
 
 #ifdef ENABLE_WORKQUEUES
-#include <linux/cpumask.h>
+#include <linux/cpu.h>
 
 /* XXX UGLY!!!! XXX  We have to access the direct structures of the workqueue which
   are only defined within workqueue.c because they don't give us a routine to allow us
@@ -131,7 +120,12 @@
  * per-CPU workqueues:
  */
 struct workqueue_struct {
+	/* TODO: Find out exactly where the API changed */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+	struct cpu_workqueue_struct *cpu_wq;
+#else
 	struct cpu_workqueue_struct cpu_wq[NR_CPUS];
+#endif
 	const char *name;
 	struct list_head list; 	/* Empty if single thread */
 };
@@ -160,12 +154,13 @@
 static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu)
 {
 	int ret = 0;
-
+	get_cpu();
 	if (!test_and_set_bit(0, &work->pending)) {
 		BUG_ON(!list_empty(&work->entry));
 		__t4_queue_work(wq->cpu_wq + cpu, work);
 		ret = 1;
 	}
+	put_cpu();
 	return ret;
 }
 
@@ -194,8 +189,6 @@
    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;
 /* For 56kbps links, set this module parameter to 0x7f */
 static int hardhdlcmode = 0xff;
 
@@ -247,8 +240,6 @@
 static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT };
 	
 
-static int inirq = 0;
-
 struct t4;
 
 struct t4_span {
@@ -285,9 +276,9 @@
 	int frames_in;
 
 #ifdef VPM_SUPPORT
-	unsigned int dtmfactive;
-	unsigned int dtmfmask;
-	unsigned int dtmfmutemask;
+	unsigned long dtmfactive;
+	unsigned long dtmfmask;
+	unsigned long dtmfmutemask;
 	short dtmfenergy[31];
 	short dtmfdigit[31];
 #endif
@@ -307,10 +298,6 @@
 	int syncsrc;			/* active sync source */
 	struct t4_span *tspans[4];	/* Individual spans */
 	int numspans;			/* Number of spans on the card */
-#ifdef VPM_SUPPORT
-	int vpm;
-#endif	
-
 	int blinktimer;
 #ifdef FANCY_ALARM
 	int alarmpos;
@@ -323,37 +310,39 @@
 	unsigned int gpio;
 	unsigned int gpioctl;
 	int stopdma;			/* Set to stop DMA */
-	unsigned int dmactrl;
 	int e1recover;			/* E1 recovery timer */
-	dma_addr_t 	readdma;
-	dma_addr_t	writedma;
-	unsigned long memaddr;		/* Base address of card */
-	unsigned long memlen;
-	volatile unsigned int *membase;	/* Base address of card */
+	spinlock_t reglock;		/* lock register access */
 	int spansstarted;		/* number of spans started */
-	/* spinlock_t lock; */		/* lock context */
-	spinlock_t reglock;		/* lock register access */
 	volatile unsigned int *writechunk;					/* Double-word aligned write memory */
 	volatile unsigned int *readchunk;					/* Double-word aligned read memory */
 	unsigned short canary;
 #ifdef ENABLE_WORKQUEUES
 	atomic_t worklist;
 	struct workqueue_struct *workq;
-#else
-#ifdef ENABLE_TASKLETS
-	int taskletrun;
-	int taskletsched;
-	int taskletpending;
-	int taskletexec;
-	int txerrors;
-	struct tasklet_struct t4_tlet;
-#endif
 #endif
 	unsigned int passno;	/* number of interrupt passes */
 	char *variety;
 	int last0;		/* for detecting double-missed IRQ */
 	int checktiming;	/* Set >0 to cause the timing source to be checked */
+
+	/* DMA related fields */
+	unsigned int dmactrl;
+	dma_addr_t 	readdma;
+	dma_addr_t	writedma;
+	unsigned long memaddr;		/* Base address of card */
+	unsigned long memlen;
+	volatile unsigned int *membase;	/* Base address of card */
+
+	/* Flags for our bottom half */
+	unsigned long checkflag;
+	struct tasklet_struct t4_tlet;
+	unsigned int vpm400checkstatus;
+	
+#ifdef VPM_SUPPORT
 	struct vpm450m *vpm450m;
+	int vpm;
+#endif	
+
 };
 
 #define T4_VPM_PRESENT (1 << 28)
@@ -407,9 +396,7 @@
 
 #define MAX_T4_CARDS 64
 
-#ifdef ENABLE_TASKLETS
-static void t4_tasklet(unsigned long data);
-#endif
+static void t4_isr_bh(unsigned long data);
 
 static struct t4 *cards[MAX_T4_CARDS];
 
@@ -547,13 +534,13 @@
 static inline void __t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value)
 {
 	unit &= 0x3;
-	if (debug & DEBUG_REGS)
+	if (unlikely(debug & DEBUG_REGS))
 		printk("Writing %02x to address %02x of unit %d\n", value, addr, unit);
 	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
 	__t4_pci_out(wc, WC_LDATA, value);
 	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LWRITE);
 	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));	
-	if (debug & DEBUG_REGS) printk("Write complete\n");
+	if (unlikely(debug & DEBUG_REGS)) printk("Write complete\n");
 #if 0
 	if ((addr != FRMR_TXFIFO) && (addr != FRMR_CMDR) && (addr != 0xbc))
 	{ unsigned int tmp;
@@ -749,14 +736,14 @@
 			channel -= 5;
 		else
 			channel -= 1;
-		if (debug)
+		if (unlikely(debug))
 			printk("Got tone %s of '%c' on channel %d of span %d\n",
 				(start ? "START" : "STOP"), tone, channel, span + 1);
-		if ((wc->tspans[span]->dtmfmask & (1 << channel)) && (tone != 'u')) {
+		if (test_bit(channel, &wc->tspans[span]->dtmfmask) && (tone != 'u')) {
 			if (start) {
 				/* The octasic is supposed to mute us, but...  Yah, you
 				   guessed it.  */
-				if (wc->tspans[span]->dtmfmutemask & (1 << channel)) {
+				if (test_bit(channel, &wc->tspans[span]->dtmfmutemask)) {
 					unsigned long flags;
 					struct zt_chan *chan = &wc->tspans[span]->span.chans[channel];
 					int y;
@@ -767,10 +754,10 @@
 					}
 					spin_unlock_irqrestore(&chan->lock, flags);
 				}
-				wc->tspans[span]->dtmfactive |= (1 << channel);
+				set_bit(channel, &wc->tspans[span]->dtmfactive);
 				zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFDOWN | tone));
 			} else {
-				wc->tspans[span]->dtmfactive &= ~(1 << channel);
+				clear_bit(channel, &wc->tspans[span]->dtmfactive);
 				zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFUP | tone));
 			}
 		}
@@ -785,24 +772,22 @@
 	short energy=0;
 	static unsigned int lastio = 0;
 	struct t4_span *ts;
-	unsigned long flags;
 
 	if (debug && (newio != lastio)) 
 		printk("Last was %08x, new is %08x\n", lastio, newio);
 
 	lastio = newio;
  
-	spin_lock_irqsave(&wc->reglock, flags);
 	for(x = 0; x < 8; x++) {
 		if (newio & (1 << (7 - x)))
 			continue;
 		ts = wc->tspans[x%4];
 		/* Start of DTMF detection process */	
-		regbyte = __t4_vpm_in(wc, x, 0xb8);
-		__t4_vpm_out(wc, x, 0xb8, regbyte); /* Write 1 to clear */
+		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);
+		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++) {
@@ -812,42 +797,32 @@
 
 				if (!wc->t1e1)
 					base -= 4;
-				regbyte = __t4_vpm_in(wc, x, 0xa8 + i);
+				regbyte = t4_vpm_in(wc, x, 0xa8 + i);
 				digit = vpm_digits[regbyte];
 				if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) {
-					energy = __t4_vpm_in(wc, x, 0x58 + channel);
+					energy = t4_vpm_in(wc, x, 0x58 + channel);
 					energy = ZT_XLAW(energy, ts->chans);
 					ts->dtmfenergy[base] = energy;
 				}
-				ts->dtmfactive |= (1 << base);
+				set_bit(base, &ts->dtmfactive);
 				if (ts->dtmfdigit[base]) {
-					if (ts->dtmfmask & (1 << base)) {
-						spin_unlock_irqrestore(&wc->reglock, flags);
+					if (ts->dtmfmask & (1 << base))
 						zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
-						spin_lock_irqsave(&wc->reglock, flags);
-					}
 				}
 				ts->dtmfdigit[base] = digit;
-				if (ts->dtmfmask & (1 << base)) {
-					spin_unlock_irqrestore(&wc->reglock, flags);
+				if (test_bit(base, &ts->dtmfmask))
 					zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFDOWN | digit));
-					spin_lock_irqsave(&wc->reglock, flags);
-				}
-				if (ts->dtmfmutemask & (1 << base)) {
+				if (test_bit(base, &ts->dtmfmutemask)) {
 					/* Mute active receive buffer*/
-					unsigned long flags2;
+					unsigned long flags;
 					struct zt_chan *chan = &ts->span.chans[base];
 					int y;
-					/* We can't hold the reglock and the channel lock at the same time.  If we do so,
-					 * we can cause a deadlock scenario */
-					spin_unlock_irqrestore(&wc->reglock, flags);
-					spin_lock_irqsave(&chan->lock, flags2);
+					spin_lock_irqsave(&chan->lock, flags);
 					for (y=0;y<chan->numbufs;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, flags2);
-					spin_lock_irqsave(&wc->reglock, flags);
+					spin_unlock_irqrestore(&chan->lock, flags);
 				}
 				if (debug)
 					printk("Digit Seen: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x);
@@ -859,11 +834,11 @@
 			continue;
 
 		/* Start of DTMF off detection process */	
-		regbyte = __t4_vpm_in(wc, x, 0xbc);
-		__t4_vpm_out(wc, x, 0xbc, regbyte); /* Write 1 to clear */
+		regbyte = t4_vpm_in(wc, x, 0xbc);
+		t4_vpm_out(wc, x, 0xbc, regbyte); /* Write 1 to clear */
 		regval = regbyte << 8;
-		regbyte = __t4_vpm_in(wc, x, 0xbd);
-		__t4_vpm_out(wc, x, 0xbd, regbyte);
+		regbyte = t4_vpm_in(wc, x, 0xbd);
+		t4_vpm_out(wc, x, 0xbd, regbyte);
 		regval |= regbyte;
 
 		for(i = 0; (i < MAX_DTMF_DET) && regval; i++) {
@@ -873,13 +848,10 @@
 
 				if (!wc->t1e1)
 					base -= 4;
-				ts->dtmfactive &= ~(1 << base);
+				clear_bit(base, &ts->dtmfactive);
 				if (ts->dtmfdigit[base]) {
-					if (ts->dtmfmask & (1 << base)) {
-						spin_unlock_irqrestore(&wc->reglock, flags);
+					if (test_bit(base, &ts->dtmfmask))
 						zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
-						spin_lock_irqsave(&wc->reglock, flags);
-					}
 				}
 				digit = ts->dtmfdigit[base];
 				ts->dtmfdigit[base] = 0;
@@ -891,11 +863,10 @@
 		}
 
 	}
-	spin_unlock_irqrestore(&wc->reglock, flags);
-}
-#endif
-
-static void __hdlc_stop(struct t4 *wc, unsigned int span)
+}
+#endif
+
+static void hdlc_stop(struct t4 *wc, unsigned int span)
 {
 	struct t4_span *t = wc->tspans[span];
 	unsigned char imr0, imr1, mode;
@@ -905,23 +876,23 @@
 	
 	/* Clear receive and transmit timeslots */
 	for (i = 0; i < 4; i++) {
-		__t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00);
-		__t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00);
-	}
-
-	imr0 = __t4_framer_in(wc, span, FRMR_IMR0);
-	imr1 = __t4_framer_in(wc, span, FRMR_IMR1);
+		t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00);
+		t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00);
+	}
+
+	imr0 = t4_framer_in(wc, span, FRMR_IMR0);
+	imr1 = t4_framer_in(wc, span, FRMR_IMR1);
 
 	/* Disable HDLC interrupts */
 	imr0 |= HDLC_IMR0_MASK;
-	__t4_framer_out(wc, span, FRMR_IMR0, imr0);
+	t4_framer_out(wc, span, FRMR_IMR0, imr0);
 
 	imr1 |= HDLC_IMR1_MASK;
-	__t4_framer_out(wc, span, FRMR_IMR1, imr1);
-
-	mode = __t4_framer_in(wc, span, FRMR_MODE);
+	t4_framer_out(wc, span, FRMR_IMR1, imr1);
+
+	mode = t4_framer_in(wc, span, FRMR_MODE);
 	mode &= ~FRMR_MODE_HRAC;
-	__t4_framer_out(wc, span, FRMR_MODE, mode);
+	t4_framer_out(wc, span, FRMR_MODE, mode);
 
 	t->sigactive = 0;
 }
@@ -931,31 +902,32 @@
 	__t4_framer_out(wc, span, FRMR_CMDR, cmd);
 }
 
-static inline void __t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd)
+static inline void t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd)
 {
 	int sis;
 	int loops = 0;
 
 	/* XXX could be time consuming XXX */
 	for (;;) {
-		sis = __t4_framer_in(wc, span, FRMR_SIS);
+		sis = t4_framer_in(wc, span, FRMR_SIS);
 		if (!(sis & 0x04))
 			break;
-		if (!loops++) {
+		if (!loops++ && (debug & DEBUG_FRAMER)) {
 			printk("!!!SIS Waiting before cmd %02x\n", cmd);
 		}
 	}
-	if (loops)
+	if (loops && (debug & DEBUG_FRAMER))
 		printk("!!!SIS waited %d loops\n", loops);
 
-	__t4_framer_out(wc, span, FRMR_CMDR, cmd);
-}
-
-static int __hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan, unsigned char mode)
+	t4_framer_out(wc, span, FRMR_CMDR, cmd);
+}
+
+static int hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan, unsigned char mode)
 {
 	struct t4_span *t = wc->tspans[span];
 	unsigned char imr0, imr1;
 	int offset = chan->chanpos;
+	unsigned long flags;
 
 	if (debug & DEBUG_FRAMER) printk("Starting HDLC controller for channel %d span %d\n", offset, span+1);
 
@@ -965,33 +937,36 @@
 	mode |= FRMR_MODE_HRAC;
 
 	/* Make sure we're in the right mode */
-	__t4_framer_out(wc, span, FRMR_MODE, mode);
-	__t4_framer_out(wc, span, FRMR_TSEO, 0x00);
-	__t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode);
+	t4_framer_out(wc, span, FRMR_MODE, mode);
+	t4_framer_out(wc, span, FRMR_TSEO, 0x00);
+	t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode);
 
 	/* Set the interframe gaps, etc */
-	__t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
-
-	__t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
+	t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
+
+	t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
 	
 	/* Set up the time slot that we want to tx/rx on */
-	__t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
-	__t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
-
-	imr0 = __t4_framer_in(wc, span, FRMR_IMR0);
-	imr1 = __t4_framer_in(wc, span, FRMR_IMR1);
+	t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
+	t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
+
+	imr0 = t4_framer_in(wc, span, FRMR_IMR0);
+	imr1 = t4_framer_in(wc, span, FRMR_IMR1);
 
 	/* Enable our interrupts again */
 	imr0 &= ~HDLC_IMR0_MASK;
-	__t4_framer_out(wc, span, FRMR_IMR0, imr0);
+	t4_framer_out(wc, span, FRMR_IMR0, imr0);
 
 	imr1 &= ~HDLC_IMR1_MASK;
-	__t4_framer_out(wc, span, FRMR_IMR1, imr1);
+	t4_framer_out(wc, span, FRMR_IMR1, imr1);
 
 	/* Reset the signaling controller */
-	__t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
-
+	t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
+
+	spin_lock_irqsave(&wc->reglock, flags);
 	t->sigchan = chan;
+	spin_unlock_irqrestore(&wc->reglock, flags);
+
 	t->sigactive = 0;
 
 	return 0;
@@ -1192,13 +1167,13 @@
 		if (j && (vpmdtmfsupport == 0))
 			return -ENOSYS;
 		if (j & ZT_TONEDETECT_ON)
-			ts->dtmfmask |= (1 << (chan->chanpos - 1));
+			set_bit(chan->chanpos - 1, &ts->dtmfmask);
 		else
-			ts->dtmfmask &= ~(1 << (chan->chanpos - 1));
+			clear_bit(chan->chanpos - 1, &ts->dtmfmask);
 		if (j & ZT_TONEDETECT_MUTE)
-			ts->dtmfmutemask |= (1 << (chan->chanpos - 1));
+			set_bit(chan->chanpos - 1, &ts->dtmfmutemask);
 		else
-			ts->dtmfmutemask &= ~(1 << (chan->chanpos - 1));
+			clear_bit(chan->chanpos - 1, &ts->dtmfmutemask);
 		if (wc->vpm450m) {
 			channel = (chan->chanpos) << 2;
 			if (!wc->t1e1)
@@ -1218,12 +1193,8 @@
 {
 	int res, i, size = 32;
 	unsigned char buf[32];
-	unsigned long flags;
 
 	res = zt_hdlc_getbuf(ts->sigchan, buf, &size);
-
-	spin_lock_irqsave(&wc->reglock, flags);
-
 	if (debug & DEBUG_FRAMER) printk("Got buffer sized %d and res %d for %d\n", size, res, span);
 	if (size > 0) {
 		ts->sigactive = 1;
@@ -1236,11 +1207,11 @@
 		}
 
 		for (i = 0; i < size; i++)
-			__t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]);
+			t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]);
 
 		if (res) /* End of message */ {
 			if (debug & DEBUG_FRAMER) printk("transmiting XHF|XME\n");
-			__t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME);
+			t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME);
 #if 0
 			ts->sigactive = (__t4_framer_in(wc, span, FRMR_SIS) & FRMR_SIS_XFW) ? 0 : 1;
 #endif
@@ -1249,13 +1220,11 @@
 				printk("Transmitted %d frames on span %d\n", ts->frames_out, span);
 		} else { /* Still more to transmit */
 			if (debug & DEBUG_FRAMER) printk("transmiting XHF\n");
-			__t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF);
+			t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF);
 		}
 	}
 	else if (res < 0)
 		ts->sigactive = 0;
-
-	spin_unlock_irqrestore(&wc->reglock, flags);
 }
 
 static void t4_hdlc_hard_xmit(struct zt_chan *chan)
@@ -1271,12 +1240,12 @@
 		spin_unlock_irqrestore(&wc->reglock, flags);
 		return;
 	}
+	spin_unlock_irqrestore(&wc->reglock, flags);
+
 	if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit on channel %s (sigchan %s), sigactive=%d\n", chan->name, ts->sigchan->name, ts->sigactive);
-	if ((ts->sigchan == chan) && !ts->sigactive) {
-		spin_unlock_irqrestore(&wc->reglock, flags);
+
+	if ((ts->sigchan == chan) && !ts->sigactive)
 		t4_hdlc_xmit_fifo(wc, span, ts);
-	} else
-		spin_unlock_irqrestore(&wc->reglock, flags);
 }
 
 static int t4_maint(struct zt_span *span, int cmd)
@@ -1405,18 +1374,15 @@
 	}
 
 	if (debug & DEBUG_MAIN) printk("Shutting down span %d (%s)\n", span->spanno, span->name);
+
+	/* Stop HDLC controller if runned */
+	if (ts->sigchan)
+		hdlc_stop(wc, span->offset);
 	
 	spin_lock_irqsave(&wc->reglock, flags);
 	wasrunning = span->flags & ZT_FLAG_RUNNING;
 
 	span->flags &= ~ZT_FLAG_RUNNING;
-	if (wasrunning)
-		wc->spansstarted--;
-
-	/* Stop HDLC controller if runned */
-	if (ts->sigchan)
-		__hdlc_stop(wc, span->offset);
-
 	__t4_set_led(wc, span->offset, WC_OFF);
 	if (((wc->numspans == 4) && 
 	    (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) &&
@@ -1432,6 +1398,12 @@
 		wc->stopdma = 1;
 	} else wc->checktiming = 1;
 	spin_unlock_irqrestore(&wc->reglock, flags);
+
+	/* Wait for interrupt routine to shut itself down */
+	msleep(10);
+	if (wasrunning)
+		wc->spansstarted--;
+
 	if (debug & DEBUG_MAIN)
 		printk("Span %d (%s) shutdown\n", span->spanno, span->name);
 	return 0;
@@ -1497,30 +1469,34 @@
 	if (alreadyrunning)
 		__set_clear(wc, chan->span->offset);
 
+	spin_unlock_irqrestore(&wc->reglock, flags);	
+
 	/* (re)configure signalling channel */
 	if ((sigtype == ZT_SIG_HARDHDLC) || (ts->sigchan == chan)) {
 		if (debug & DEBUG_FRAMER)
 				printk("%sonfiguring hardware HDLC on %s\n", ((sigtype == ZT_SIG_HARDHDLC) ? "C" : "Unc"), chan->name);
 		if (alreadyrunning) {
 			if (ts->sigchan)
-				__hdlc_stop(wc, ts->sigchan->span->offset);
+				hdlc_stop(wc, ts->sigchan->span->offset);
 			if (sigtype == ZT_SIG_HARDHDLC) {
-				if (__hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) {
+				if (hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) {
 					printk("Error initializing signalling controller\n");
-					spin_unlock_irqrestore(&wc->reglock, flags);
 					return -1;
 				}
-			}
-			else
+			} else {
+				spin_lock_irqsave(&wc->reglock, flags);
 				ts->sigchan = NULL;
+				spin_unlock_irqrestore(&wc->reglock, flags);
+			}
 		
 		}
 		else {
+			spin_lock_irqsave(&wc->reglock, flags);
 			ts->sigchan = (sigtype == ZT_SIG_HARDHDLC) ? chan : NULL;
+			spin_unlock_irqrestore(&wc->reglock, flags);
 			ts->sigactive = 0;
 		}
 	}
-	spin_unlock_irqrestore(&wc->reglock, flags);	
 	return 0;
 }
 
@@ -1547,7 +1523,7 @@
 
 static void init_spans(struct t4 *wc)
 {
-	int x,y,c;
+	int x,y;
 	int gen2;
 	int offset = 1;
 	struct t4_span *ts;
@@ -1603,7 +1579,6 @@
 			sprintf(mychans->name, "TE%d/%d/%d/%d", wc->numspans, wc->num, x + 1, y + 1);
 			mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_HARDHDLC |
 									 ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_EM_E1 | ZT_SIG_DACS_RBS;
-			c = (x * ts->span.channels) + y;
 			mychans->pvt = wc;
 			mychans->chanpos = y + 1;
 			if (gen2) {
@@ -1896,13 +1871,8 @@
 	__t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0));	/* IMR0: We care about CAS changes, etc */
 	__t4_framer_out(wc, unit, FRMR_IMR1, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0));	/* IMR1: We care about nothing */
 	__t4_framer_out(wc, unit, 0x16, 0x00);	/* IMR2: We care about all the alarm stuff! */
-	if (debugslips) {
-		__t4_framer_out(wc, unit, 0x17, 0xf4);	/* IMR3: We care about AIS and friends */
-		__t4_framer_out(wc, unit, 0x18, 0x3f);  /* IMR4: We care about slips on transmit */
-	} else {
-		__t4_framer_out(wc, unit, 0x17, 0xf7);	/* IMR3: We care about AIS and friends */
-		__t4_framer_out(wc, unit, 0x18, 0xff);  /* IMR4: We don't care about slips on transmit */
-	}
+	__t4_framer_out(wc, unit, 0x17, 0xf4);	/* IMR3: We care about AIS and friends */
+	__t4_framer_out(wc, unit, 0x18, 0x3f);  /* IMR4: We care about slips on transmit */
 
 	printk("TE%dXXP: Span %d configured for %s/%s\n", wc->numspans, unit + 1, framing, line);
 }
@@ -1980,13 +1950,9 @@
 	__t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0));	/* IMR0: We care about CRC errors, CAS changes, etc */
 	__t4_framer_out(wc, unit, FRMR_IMR1, 0x3f & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0));	/* IMR1: We care about loopup / loopdown */
 	__t4_framer_out(wc, unit, 0x16, 0x00);	/* IMR2: We care about all the alarm stuff! */
-	if (debugslips) {
-		__t4_framer_out(wc, unit, 0x17, 0xc4 | imr3extra);	/* IMR3: We care about AIS and friends */
-		__t4_framer_out(wc, unit, 0x18, 0x3f);  /* IMR4: We care about slips on transmit */
-	} else {
-		__t4_framer_out(wc, unit, 0x17, 0xc7 | imr3extra);	/* IMR3: We care about AIS and friends */
-		__t4_framer_out(wc, unit, 0x18, 0xff);  /* IMR4: We don't care about slips on transmit */
-	}
+	__t4_framer_out(wc, unit, 0x17, 0xc4 | imr3extra);	/* IMR3: We care about AIS and friends */
+	__t4_framer_out(wc, unit, 0x18, 0x3f);  /* IMR4: We care about slips on transmit */
+
 	printk("TE%dXXP: Span %d configured for %s/%s%s\n", wc->numspans, unit + 1, framing, line, crc4);
 }
 
@@ -2042,6 +2008,8 @@
 		/* enable interrupts */
 		/* Start DMA, enabling DMA interrupts on read only */
 		wc->dmactrl = 1 << 29;
+		/* Enable framer only interrupts */
+		wc->dmactrl |= 1 << 27;
 		wc->dmactrl |= (ts->spanflags & FLAG_2NDGEN) ? 0xc0000000 : 0xc0000003;
 #ifdef VPM_SUPPORT
 		wc->dmactrl |= wc->vpm;
@@ -2051,15 +2019,19 @@
 		if (noburst && !(ts->spanflags & FLAG_BURST))
 			wc->dmactrl |= (1 << 26);
 		__t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
+
 		/* Startup HDLC controller too */
-		if (ts->sigchan) {
-			if (__hdlc_start(wc, span->offset, ts->sigchan, ts->sigmode)) {
-				printk("Error initializing signalling controller\n");
-				/* XXX Should de-initialize span XXX */
-				spin_unlock_irqrestore(&wc->reglock, flags);
-				return -1;
-			}
-		}
+	}
+
+	if (ts->sigchan) {
+		struct zt_chan *sigchan = ts->sigchan;
+
+		spin_unlock_irqrestore(&wc->reglock, flags);
+		if (hdlc_start(wc, span->offset, sigchan, ts->sigmode)) {
+			printk("Error initializing signalling controller\n");
+			return -1;
+		}
+		spin_lock_irqsave(&wc->reglock, flags);
 	}
 
 	spin_unlock_irqrestore(&wc->reglock, flags);
@@ -2205,12 +2177,12 @@
 {
 #ifdef VPM_SUPPORT
 	int y;
-	unsigned int merged;
+	unsigned long merged;
 	merged = ts->dtmfactive & ts->dtmfmutemask;
 	if (merged) {
 		for (y=0;y<ts->span.channels;y++) {
 			/* Mute any DTMFs which are supposed to be muted */
-			if (merged & (1 << y))  {
+			if (test_bit(y, &merged)) {
 				memset(ts->span.chans[y].readchunk, ZT_XLAW(0, (ts->span.chans + y)), ZT_CHUNKSIZE);
 			}
 		}
@@ -2334,7 +2306,6 @@
 
 	if (!(ts->span.flags & ZT_FLAG_RUNNING))
 		return;
-
 	if (ts->spantype == TYPE_E1) {
 		for (i = 0; i < 15; i++) {
 			a = t4_framer_in(wc, span, 0x71 + i);
@@ -2519,21 +2490,18 @@
 	if (ts->span.mainttimer || ts->span.maintstat) 
 		alarms |= ZT_ALARM_LOOPBACK;
 	ts->span.alarms = alarms;
-
 	spin_unlock_irqrestore(&wc->reglock, flags);
-
 	zt_alarm_notify(&ts->span);
 }
 
 static void t4_do_counters(struct t4 *wc)
 {
 	int span;
-	unsigned long flags;
-
 	for (span=0;span<wc->numspans;span++) {
 		struct t4_span *ts = wc->tspans[span];
 		int docheck=0;
-		spin_lock_irqsave(&wc->reglock, flags);
+
+		spin_lock(&wc->reglock);
 		if (ts->loopupcnt || ts->loopdowncnt)
 			docheck++;
 		if (ts->alarmtimer) {
@@ -2542,10 +2510,9 @@
 				ts->span.alarms &= ~(ZT_ALARM_RECOVER);
 			}
 		}
-		spin_unlock_irqrestore(&wc->reglock, flags);
+		spin_unlock(&wc->reglock);
 		if (docheck) {
-			if (!polling)
-				t4_check_alarms(wc, span);
+			t4_check_alarms(wc, span);
 			zt_alarm_notify(&ts->span);
 		}
 	}
@@ -2619,6 +2586,7 @@
 	unsigned char gis, isr0, isr1, isr2, isr3, isr4;
 	int readsize = -1;
 	struct t4_span *ts = wc->tspans[span];
+	struct zt_chan *sigchan;
 	unsigned long flags;
 
 	if (debug & DEBUG_FRAMER)	
@@ -2647,16 +2615,20 @@
 		if (isr2 || (isr3 & 0x08)) 
 			t4_check_alarms(wc, span);		
 	}
-	if (debugslips && !ts->span.alarms) {
-		if (isr3 & 0x02)
-			printk("TE%d10P: RECEIVE slip NEGATIVE on span %d\n", wc->numspans, span + 1);
-		if (isr3 & 0x01)
-			printk("TE%d10P: RECEIVE slip POSITIVE on span %d\n", wc->numspans, span + 1);
-		if (isr4 & 0x80)
-			printk("TE%dXXP: TRANSMIT slip POSITIVE on span %d\n", wc->numspans, span + 1);
-		if (isr4 & 0x40)
-			printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1);
-	}
+	if (!ts->span.alarms) {
+		ts->span.timingslips++;
+		if (debug & DEBUG_MAIN) {
+			if (isr3 & 0x02)
+				printk("TE%d10P: RECEIVE slip NEGATIVE on span %d\n", wc->numspans, span + 1);
+			if (isr3 & 0x01)
+				printk("TE%d10P: RECEIVE slip POSITIVE on span %d\n", wc->numspans, span + 1);
+			if (isr4 & 0x80)
+				printk("TE%dXXP: TRANSMIT slip POSITIVE on span %d\n", wc->numspans, span + 1);
+			if (isr4 & 0x40)
+				printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1);
+		}
+	} else
+		ts->span.timingslips = 0;
 
 	spin_lock_irqsave(&wc->reglock, flags);
 	/* HDLC controller checks - receive side */
@@ -2665,8 +2637,11 @@
 		return;
 	}
 
+	sigchan = ts->sigchan;
+	spin_unlock_irqrestore(&wc->reglock, flags);
+
 	if (isr0 & FRMR_ISR0_RME) {
-		readsize = (__t4_framer_in(wc, span, FRMR_RBCH) << 8) | __t4_framer_in(wc, span, FRMR_RBCL);
+		readsize = (t4_framer_in(wc, span, FRMR_RBCH) << 8) | t4_framer_in(wc, span, FRMR_RBCL);
 		if (debug & DEBUG_FRAMER) printk("Received data length is %d (%d)\n", readsize, readsize & FRMR_RBCL_MAX_SIZE);
 		/* RPF isn't set on last part of frame */
 		if ((readsize > 0) && ((readsize &= FRMR_RBCL_MAX_SIZE) == 0))
@@ -2675,17 +2650,16 @@
 		readsize = 32;
 
 	if (readsize > 0) {
-		struct zt_chan *sigchan = ts->sigchan;
 		int i;
 		unsigned char readbuf[readsize];
 
 		if (debug & DEBUG_FRAMER) printk("Framer %d: Got RPF/RME! readsize is %d\n", sigchan->span->offset, readsize);
 
 		for (i = 0; i < readsize; i++)
-			readbuf[i] = __t4_framer_in(wc, span, FRMR_RXFIFO);
+			readbuf[i] = t4_framer_in(wc, span, FRMR_RXFIFO);
 
 		/* Tell the framer to clear the RFIFO */
-		__t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC);
+		t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC);
 
 		if (debug & DEBUG_FRAMER) {
 			printk("RX(");
@@ -2697,8 +2671,10 @@
 		if (isr0 & FRMR_ISR0_RME) {
 			/* Do checks for HDLC problems */
 			unsigned char rsis = readbuf[readsize-1];
+#if 0
 			unsigned int olddebug = debug;
-			unsigned char rsis_reg = __t4_framer_in(wc, span, FRMR_RSIS);
+#endif
+			unsigned char rsis_reg = t4_framer_in(wc, span, FRMR_RSIS);
 
 #if 0
 			if ((rsis != 0xA2) || (rsis != rsis_reg))
@@ -2706,7 +2682,6 @@
 #endif
 
 			++ts->frames_in;
-			spin_unlock_irqrestore(&wc->reglock, flags);
 			if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f))
 				printk("Received %d frames on span %d\n", ts->frames_in, span);
 			if (debug & DEBUG_FRAMER) printk("Received HDLC frame %d.  RSIS = 0x%x (%x)\n", ts->frames_in, rsis, rsis_reg);
@@ -2727,36 +2702,28 @@
 				zt_hdlc_finish(sigchan);
 				if (debug & DEBUG_FRAMER) printk("Received valid HDLC frame on span %d\n", span);
 			}
-			spin_lock_irqsave(&wc->reglock, flags);
+#if 0
 			debug = olddebug;
-		} else if (isr0 & FRMR_ISR0_RPF) {
-			spin_unlock_irqrestore(&wc->reglock, flags);
+#endif
+		} else if (isr0 & FRMR_ISR0_RPF)
 			zt_hdlc_putbuf(sigchan, readbuf, readsize);
-			spin_lock_irqsave(&wc->reglock, flags);
-		}
 	}
 
 	/* Transmit side */
 	if (isr1 & FRMR_ISR1_XDU) {
 		if (debug & DEBUG_FRAMER) printk("XDU: Resetting signal controler!\n");
-		__t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
+		t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
 	} else if (isr1 & FRMR_ISR1_XPR) {
-		struct zt_chan *sigchan = ts->sigchan;
-
 		if (debug & DEBUG_FRAMER)
 			printk("Sigchan %d is %p\n", sigchan->chanpos, sigchan);
 
 		if (debug & DEBUG_FRAMER) printk("Framer %d: Got XPR!\n", sigchan->span->offset);
-		spin_unlock_irqrestore(&wc->reglock, flags);
 		t4_hdlc_xmit_fifo(wc, span, ts);
-		spin_lock_irqsave(&wc->reglock, flags);
 	}
 
 	if (isr1 & FRMR_ISR1_ALLS) {
 		if (debug & DEBUG_FRAMER) printk("ALLS received\n");
 	}
-
-	spin_unlock_irqrestore(&wc->reglock, flags);
 
 }
 
@@ -2775,9 +2742,9 @@
 		printk("Pre-interrupt\n");
 #endif
 	
-	inirq = 1;
 	/* Make sure it's really for us */
-	status = t4_pci_in(wc, WC_INTR);
+	status = __t4_pci_in(wc, WC_INTR);
+
 	/* Process framer interrupts */
 	status2 = t4_framer_in(wc, 0, FRMR_CIS);
 	if (status2 & 0x0f) {
@@ -2795,7 +2762,7 @@
 		return;
 #endif		
 
-	t4_pci_out(wc, WC_INTR, 0);
+	__t4_pci_out(wc, WC_INTR, 0);
 
 	if (!wc->spansstarted) {
 		printk("Not prepped yet!\n");
@@ -2859,42 +2826,32 @@
 }
 #endif
 
+static void t4_isr_bh(unsigned long data)
+{
+	struct t4 *wc = (struct t4 *)data;
+
+#ifdef VPM_SUPPORT
+	if (wc->vpm) {
+		if (test_and_clear_bit(T4_CHECK_VPM, &wc->checkflag)) {
+			if (wc->vpm450m) {
+				/* How stupid is it that the octasic can't generate an
+				   interrupt when there's a tone, in spite of what their
+				   documentation says? */
+				t4_check_vpm450(wc);
+			} else
+				t4_check_vpm400(wc, wc->vpm400checkstatus);
+		}
+	}
+#endif
+}
+
 ZAP_IRQ_HANDLER(t4_interrupt_gen2)
 {
 	struct t4 *wc = dev_id;
-	unsigned long flags;
-	unsigned char cis;
-	int x;
-	int needcheckvpm450=0;
+	unsigned int status;
 	
-	unsigned int status;
-#if 0
-	unsigned int status2;
-#endif
-
-#if 0
-	if (wc->intcount < 20)
-		printk("2G: Pre-interrupt\n");
-#endif
-
-	spin_lock_irqsave(&wc->reglock, flags);
-
-	if (wc->stopdma) {
-		/* Stop DMA cleanly if requested */
-		wc->dmactrl = 0x0;
-		__t4_pci_out(wc, WC_DMACTRL, 0x00000000);
-		/* Acknowledge any pending interrupts */
-		__t4_pci_out(wc, WC_INTR, 0x00000000);
-		__t4_set_timing_source(wc, 4, 0, 0);
-		wc->stopdma = 0x0;
-	}
-
-	spin_unlock_irqrestore(&wc->reglock, flags);
-
-	
-	inirq = 1;
 	/* Make sure it's really for us */
-	status = t4_pci_in(wc, WC_INTR);
+	status = __t4_pci_in(wc, WC_INTR);
 
 	/* Ignore if it's not for us */
 	if (!(status & 0x7)) {
@@ -2906,9 +2863,10 @@
 	}
 
 #ifdef ENABLE_WORKQUEUES
-	t4_pci_out(wc, WC_INTR, status & 0x00000008);
-#endif
-	if (!wc->spansstarted) {
+	__t4_pci_out(wc, WC_INTR, status & 0x00000008);
+#endif
+
+	if (unlikely(!wc->spansstarted)) {
 		printk("Not prepped yet!\n");
 #ifdef LINUX26
 		return IRQ_NONE;
@@ -2918,13 +2876,12 @@
 	}
 
 	wc->intcount++;
-#if 1
-	if ((wc->intcount < 20) && debug)
+
+	if (unlikely((wc->intcount < 20) && debug))
 
 		printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, t4_framer_in(wc, 0, FRMR_CIS));
-#endif		
-
-	if (status & 0x2) {
+
+	if (likely(status & 0x2)) {
 #ifdef ENABLE_WORKQUEUES
 		int cpus = num_online_cpus();
 		atomic_set(&wc->worklist, wc->numspans);
@@ -2949,28 +2906,16 @@
 #else
 		t4_prep_gen2(wc);
 #endif
-	}
-
-	if (status & 0x2)
 		t4_do_counters(wc);
-
-	if (polling && (status & 0x2)) {
-		x = wc->intcount & 15 /* 63 */;
-		switch(x) {
-		case 0:
-		case 1:
-		case 2:
-		case 3:
-			t4_check_sigbits(wc, x);
-			break;
-		case 4:
-		case 5:
-		case 6:
-		case 7:
-			t4_check_alarms(wc, x - 4);
-			break;
-		}
-	} else if (status & 0x1) {
+		spin_lock(&wc->reglock);
+		__handle_leds(wc);
+		spin_unlock(&wc->reglock);
+
+	}
+
+	if (unlikely(status & 0x1)) {
+		unsigned char cis;
+
 		cis = t4_framer_in(wc, 0, FRMR_CIS);
 		if (cis & FRMR_CIS_GIS1)
 			t4_framer_interrupt(wc, 0);
@@ -2982,81 +2927,43 @@
 			t4_framer_interrupt(wc, 3);
 	}
 
-	spin_lock_irqsave(&wc->reglock, flags);
-
-#ifdef VPM_SUPPORT
 	if (wc->vpm) {
-		if (!wc->vpm450m && !(wc->intcount % 16) && !(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) {
-			/* Check DTMF events */
-			int span = (wc->intcount >> 4) & 0x3;
-			int y;
-			short energy;
-			int offset = 1;
-			int chip;
-			int channel;
-			struct t4_span *ts = wc->tspans[span];
-			if (!wc->t1e1)
-				offset = 5;
-			if (ts->dtmfactive) {
-				for (y = 0; y < ts->span.channels; y++) {
-					if (ts->dtmfactive & (1 << y)) {
-						channel = y + offset;
-						chip = span + ((channel & 0x1) << 2);
-						/* Have an active channel, check its energy! */
-						energy = __t4_vpm_in(wc, chip, 0x58 + channel);
-						energy = ZT_XLAW(energy, ts->span.chans);
-						if (energy < (ts->dtmfenergy[y])) {
-							if (debug & DEBUG_DTMF)
-								printk("Finished digit on span %d, channel %d (energy = %02x < %02x) 'channel' %d, chip %d!\n", span, y + 1, energy, ts->dtmfenergy[y], channel, chip);
-							if (debug & DEBUG_DTMF)	
-								printk("Finished digit '%c' on channel %d of span %d\n", ts->dtmfdigit[y], y + 1, span);
-							if (ts->dtmfmask & (1 << y)) {
-								spin_unlock_irqrestore(&wc->reglock, flags);
-								zt_qevent_lock(&ts->span.chans[y], (ZT_EVENT_DTMFUP | ts->dtmfdigit[y]));
-								spin_lock_irqsave(&wc->reglock, flags);
-							}
-							ts->dtmfenergy[y] = 0;
-							ts->dtmfdigit[y] = 0;
-							ts->dtmfactive &= ~(1 << y);
-						} else if (energy > (ts->dtmfenergy[y])) {
-							if (debug & DEBUG_DTMF)
-								printk("Increasing digit energy on span %d, channel %d (energy = %02x > %02x)!\n", span, y + 1, energy, ts->dtmfenergy[y]);
-							ts->dtmfenergy[y] = energy;
-						}
-					}
-				}
-			}
-		} 
 		if (wc->vpm450m) {
 			/* How stupid is it that the octasic can't generate an
 			   interrupt when there's a tone, in spite of what their
 			   documentation says? */
 			if (!(wc->intcount & 0xf)) {
-				needcheckvpm450 = 1;
+				set_bit(T4_CHECK_VPM, &wc->checkflag);
 			}
 		} else if ((status & 0xff00) != 0xff00) {
-			spin_unlock_irqrestore(&wc->reglock, flags);
-			t4_check_vpm400(wc, (status & 0xff00) >> 8);
-			spin_lock_irqsave(&wc->reglock, flags);
-		}
-	}
-#endif
-
-#if 1 
-	__handle_leds(wc);
-#endif
-
-	if (wc->checktiming > 0)
+			wc->vpm400checkstatus = (status & 0xff00) >> 8;
+			set_bit(T4_CHECK_VPM, &wc->checkflag);
+		}
+	}
+
+	spin_lock(&wc->reglock);
+
+	if (unlikely(wc->checktiming > 0)) {
 		__t4_set_timing_source_auto(wc);
-	spin_unlock_irqrestore(&wc->reglock, flags);
-
-	if (needcheckvpm450 && (vpmdtmfsupport == 1)) {
-		t4_check_vpm450(wc);
-		needcheckvpm450 = 0;
-	}
+	}
+
+	if (unlikely(wc->stopdma)) {
+		/* Stop DMA cleanly if requested */
+		wc->dmactrl = 0x0;
+		__t4_pci_out(wc, WC_DMACTRL, 0x00000000);
+		/* Acknowledge any pending interrupts */
+		__t4_pci_out(wc, WC_INTR, 0x00000000);
+		__t4_set_timing_source(wc, 4, 0, 0);
+		wc->stopdma = 0x0;
+	}
+
+	spin_unlock(&wc->reglock);
+
+	if (unlikely(test_bit(T4_CHECK_VPM, &wc->checkflag)))
+		tasklet_schedule(&wc->t4_tlet);
 
 #ifndef ENABLE_WORKQUEUES
-	t4_pci_out(wc, WC_INTR, 0);
+	__t4_pci_out(wc, WC_INTR, 0);
 #endif	
 #ifdef LINUX26
 	return IRQ_RETVAL(1);
@@ -3243,8 +3150,8 @@
 #endif
 
 	if (vpmdtmfsupport == -1) {
-		printk("VPM450: hardware DTMF disabled.\n");
-		vpmdtmfsupport = 0;
+		printk("VPM450: hardware DTMF enabled.\n");
+		vpmdtmfsupport = 1;
 	}
 
 	wc->vpm = T4_VPM_PRESENT;
@@ -3453,7 +3360,7 @@
 	unsigned int version;
 
 	version = t4_pci_in(wc, WC_VERSION);
- 	printk("TE%dXXP version %08x, burst %s, slip debug: %s\n", wc->numspans, version, (!(cardflags & FLAG_BURST) && noburst) ? "OFF" : "ON", debugslips ? "ON" : "OFF");
+  	printk("TE%dXXP version %08x, burst %s\n", wc->numspans, version, (!(cardflags & FLAG_BURST) && noburst) ? "OFF" : "ON");
 #ifdef ENABLE_WORKQUEUES
 	printk("TE%dXXP running with work queues.\n", wc->numspans);
 #endif
@@ -3550,9 +3457,7 @@
 	spin_lock_irqsave(&wc->reglock, flags);
 	__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);
-#endif
+	tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
 	return 0;
 }
 
@@ -3691,14 +3596,14 @@
 
 
 #ifdef SUPPORT_GEN1
-			if (request_irq(pdev->irq, (dt->flags & FLAG_2NDGEN) ? t4_interrupt_gen2 :t4_interrupt, ZAP_IRQ_SHARED_DISABLED, (wc->numspans == 2) ? "wct2xxp" : "wct4xxp", wc)) 
+			if (request_irq(pdev->irq, (dt->flags & FLAG_2NDGEN) ? t4_interrupt_gen2 :t4_interrupt, SA_INTERRUPT | SA_SHIRQ, (wc->numspans == 2) ? "wct2xxp" : "wct4xxp", wc)) 
 #else
 			if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) {
 				printk("This driver does not support 1st gen modules\n");
 				kfree(wc);
 				return -ENODEV;
 			}	
-			if (request_irq(pdev->irq, t4_interrupt_gen2, ZAP_IRQ_SHARED_DISABLED, "t4xxp", wc)) 
+			if (request_irq(pdev->irq, t4_interrupt_gen2, SA_INTERRUPT | SA_SHIRQ, "t4xxp", wc)) 
 #endif
 			{
 				printk("t4xxp: Unable to request IRQ %d\n", pdev->irq);
@@ -3902,8 +3807,6 @@
 module_param(debug, int, 0600);
 module_param(loopback, int, 0600);
 module_param(noburst, int, 0600);
-module_param(debugslips, int, 0600);
-module_param(polling, int, 0600);
 module_param(timingcable, int, 0600);
 module_param(t1e1override, int, 0600);
 module_param(alarmdebounce, int, 0600);
@@ -3920,8 +3823,6 @@
 MODULE_PARM(debug, "i");
 MODULE_PARM(loopback, "i");
 MODULE_PARM(noburst, "i");
-MODULE_PARM(debugslips, "i");
-MODULE_PARM(polling, "i");
 MODULE_PARM(hardhdlcmode, "i");
 MODULE_PARM(timingcable, "i");
 MODULE_PARM(t1e1override, "i");

Modified: branches/1.4/wct4xxp/wct4xxp.h
URL: http://svn.digium.com/view/zaptel/branches/1.4/wct4xxp/wct4xxp.h?view=diff&rev=2946&r1=2945&r2=2946
==============================================================================
--- branches/1.4/wct4xxp/wct4xxp.h (original)
+++ branches/1.4/wct4xxp/wct4xxp.h Fri Aug 24 14:25:20 2007
@@ -105,5 +105,7 @@
 	unsigned char regs[NUM_REGS];
 };
 
+#define T4_CHECK_VPM		0
+
 #define WCT4_GET_REGS	_IOW (ZT_CODE, 60, struct t4_regs)
 

Modified: branches/1.4/zaptel.h
URL: http://svn.digium.com/view/zaptel/branches/1.4/zaptel.h?view=diff&rev=2946&r1=2945&r2=2946
==============================================================================
--- branches/1.4/zaptel.h (original)
+++ branches/1.4/zaptel.h Fri Aug 24 14:25:20 2007
@@ -669,6 +669,12 @@
  */
 #define ZT_TRANSCODE_OP		_IOWR(ZT_CODE, 93, int)
 
+/*
+ * VoiceMail Waiting Indication (WMWI) -- implemented by low-level driver.

[... 29 lines stripped ...]



More information about the svn-commits mailing list