summaryrefslogtreecommitdiff
path: root/wct4xxp/base.c
diff options
context:
space:
mode:
authormattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-08-24 19:25:20 +0000
committermattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-08-24 19:25:20 +0000
commitec3da485f11dc83627691b49323ed6bf94ac7c5d (patch)
treef7ce6737b41926ec802c13ae826b7299c1fdd2ef /wct4xxp/base.c
parente437fabe6982221fa2f339c823fa9927bb0f2832 (diff)
Beginning backport of trunk to 1.4
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@2946 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct4xxp/base.c')
-rw-r--r--wct4xxp/base.c571
1 files changed, 236 insertions, 335 deletions
diff --git a/wct4xxp/base.c b/wct4xxp/base.c
index 4aebb70..012a8b6 100644
--- a/wct4xxp/base.c
+++ b/wct4xxp/base.c
@@ -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
@@ -47,19 +49,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 @@ struct cpu_workqueue_struct {
* 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 void __t4_queue_work(struct cpu_workqueue_struct *cwq,
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 @@ static int lastdtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
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 wct205 = { "Wildcard TE205P ", FLAG_2NDGEN | FLAG_2PORT };
static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT };
-static int inirq = 0;
-
struct t4;
struct t4_span {
@@ -285,9 +276,9 @@ struct t4_span {
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 @@ struct t4 {
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 @@ struct t4 {
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 */
- int spansstarted; /* number of spans started */
- /* spinlock_t lock; */ /* lock context */
spinlock_t reglock; /* lock register access */
+ int spansstarted; /* number of spans started */
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 @@ static void t4_check_sigbits(struct t4 *wc, int span);
#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 unsigned int t4_framer_in(struct t4 *wc, int unit, const unsigned
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 @@ static void t4_check_vpm450(struct t4 *wc)
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 @@ static void t4_check_vpm450(struct t4 *wc)
}
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 @@ static void t4_check_vpm400(struct t4 *wc, unsigned int newio)
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 @@ static void t4_check_vpm400(struct t4 *wc, unsigned int newio)
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 @@ static void t4_check_vpm400(struct t4 *wc, unsigned int newio)
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 @@ static void t4_check_vpm400(struct t4 *wc, unsigned int newio)
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 @@ static void t4_check_vpm400(struct t4 *wc, unsigned int newio)
}
}
- spin_unlock_irqrestore(&wc->reglock, flags);
}
#endif
-static void __hdlc_stop(struct t4 *wc, unsigned int span)
+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 @@ static void __hdlc_stop(struct t4 *wc, unsigned int span)
/* 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);
+ 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);
+ 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);
+ t4_framer_out(wc, span, FRMR_IMR1, imr1);
- mode = __t4_framer_in(wc, span, FRMR_MODE);
+ 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 @@ static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd)
__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);
+ 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)
+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 @@ static int __hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan,
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_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
- __t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
+ 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)));
+ 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);
+ 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 @@ static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
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 @@ static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4
{
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 @@ static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4
}
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 @@ static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4
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 @@ static void t4_hdlc_hard_xmit(struct zt_chan *chan)
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 @@ static int t4_shutdown(struct zt_span *span)
}
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 @@ static int t4_shutdown(struct zt_span *span)
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 @@ static int t4_chanconfig(struct zt_chan *chan, int sigtype)
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 int t4_close(struct zt_chan *chan)
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 @@ static void init_spans(struct t4 *wc)
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 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev
__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 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
__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 @@ static int t4_startup(struct zt_span *span)
/* 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 @@ static int t4_startup(struct zt_span *span)
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 @@ static inline void __receive_span(struct t4_span *ts)
{
#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 @@ static void t4_check_sigbits(struct t4 *wc, int span)
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 @@ static void t4_check_alarms(struct t4 *wc, int span)
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 @@ static void t4_do_counters(struct t4 *wc)
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 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
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 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
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 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
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 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
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 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
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 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
#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,37 +2702,29 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
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);
-
}
#ifdef SUPPORT_GEN1
@@ -2775,9 +2742,9 @@ ZAP_IRQ_HANDLER(t4_interrupt)
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 @@ ZAP_IRQ_HANDLER(t4_interrupt)
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 @@ ZAP_IRQ_HANDLER(t4_interrupt)
}
#endif
-ZAP_IRQ_HANDLER(t4_interrupt_gen2)
+static void t4_isr_bh(unsigned long data)
{
- struct t4 *wc = dev_id;
- unsigned long flags;
- unsigned char cis;
- int x;
- int needcheckvpm450=0;
-
- unsigned int status;
-#if 0
- unsigned int status2;
-#endif
+ struct t4 *wc = (struct t4 *)data;
-#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;
+#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
+}
- spin_unlock_irqrestore(&wc->reglock, flags);
-
+ZAP_IRQ_HANDLER(t4_interrupt_gen2)
+{
+ struct t4 *wc = dev_id;
+ unsigned int status;
- 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 @@ ZAP_IRQ_HANDLER(t4_interrupt_gen2)
}
#ifdef ENABLE_WORKQUEUES
- t4_pci_out(wc, WC_INTR, status & 0x00000008);
+ __t4_pci_out(wc, WC_INTR, status & 0x00000008);
#endif
- if (!wc->spansstarted) {
+
+ if (unlikely(!wc->spansstarted)) {
printk("Not prepped yet!\n");
#ifdef LINUX26
return IRQ_NONE;
@@ -2918,13 +2876,12 @@ ZAP_IRQ_HANDLER(t4_interrupt_gen2)
}
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 @@ ZAP_IRQ_HANDLER(t4_interrupt_gen2)
#else
t4_prep_gen2(wc);
#endif
+ t4_do_counters(wc);
+ spin_lock(&wc->reglock);
+ __handle_leds(wc);
+ spin_unlock(&wc->reglock);
+
}
- if (status & 0x2)
- t4_do_counters(wc);
+ if (unlikely(status & 0x1)) {
+ unsigned char cis;
- 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) {
cis = t4_framer_in(wc, 0, FRMR_CIS);
if (cis & FRMR_CIS_GIS1)
t4_framer_interrupt(wc, 0);
@@ -2982,81 +2927,43 @@ ZAP_IRQ_HANDLER(t4_interrupt_gen2)
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);
+ wc->vpm400checkstatus = (status & 0xff00) >> 8;
+ set_bit(T4_CHECK_VPM, &wc->checkflag);
}
}
-#endif
-#if 1
- __handle_leds(wc);
-#endif
+ spin_lock(&wc->reglock);
- if (wc->checktiming > 0)
+ 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 @@ static void t4_vpm450_init(struct t4 *wc)
#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 @@ static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
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 @@ static int __devinit t4_launch(struct t4 *wc)
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 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i
#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(pedanticpci, int, 0600);
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(pedanticpci, "i");
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");