summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xwct4xxp.c145
1 files changed, 103 insertions, 42 deletions
diff --git a/wct4xxp.c b/wct4xxp.c
index 1bc11b6..7ce1e19 100755
--- a/wct4xxp.c
+++ b/wct4xxp.c
@@ -207,6 +207,7 @@ static int altab[] = {
#define FLAG_2NDGEN (1 << 3)
#define FLAG_2PORT (1 << 4)
+#define FLAG_VPM2GEN (1 << 5)
#define CANARY 0xc0de
@@ -545,7 +546,7 @@ static void __t4_check_vpm(struct t4 *wc, unsigned int newio)
unsigned int digit, regval = 0;
unsigned int regbyte;
int x, i;
- short energy;
+ short energy=0;
static unsigned int lastio = 0;
struct t4_span *ts;
@@ -575,10 +576,12 @@ static void __t4_check_vpm(struct t4 *wc, unsigned int newio)
base -= 4;
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);
+ if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) {
+ energy = __t4_vpm_in(wc, x, 0x58 + channel);
+ energy = ZT_XLAW(energy, ts->chans);
+ ts->dtmfenergy[base] = energy;
+ }
ts->dtmfactive |= (1 << base);
- ts->dtmfenergy[base] = energy;
if (ts->dtmfdigit[base]) {
if (ts->dtmfmask & (1 << base))
zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
@@ -604,6 +607,38 @@ static void __t4_check_vpm(struct t4 *wc, unsigned int newio)
}
regval = regval >> 1;
}
+ if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN))
+ 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 */
+ regval = regbyte << 8;
+ 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++) {
+ if(regval & 0x0001) {
+ int channel = (i << 1) + (x >> 2);
+ int base = channel - 1;
+
+ if (!wc->t1e1)
+ base -= 4;
+ ts->dtmfactive &= ~(1 << base);
+ if (ts->dtmfdigit[base]) {
+ if (ts->dtmfmask & (1 << base))
+ zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
+ }
+ digit = ts->dtmfdigit[base];
+ ts->dtmfdigit[base] = 0;
+ if (debug)
+ printk("Digit Gone: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x);
+
+ }
+ regval = regval >> 1;
+ }
+
}
}
#endif
@@ -2231,41 +2266,39 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs)
}
#ifdef VPM_SUPPORT
if (wc->vpm) {
- if (!(wc->intcount % 16)) {
+ if (!(wc->intcount % 16) && !(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) {
/* Check DTMF events */
- if (wc->vpm) {
- 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))
- zt_qevent_lock(&ts->span.chans[y], (ZT_EVENT_DTMFUP | ts->dtmfdigit[y]));
- 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;
- }
+ 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))
+ zt_qevent_lock(&ts->span.chans[y], (ZT_EVENT_DTMFUP | ts->dtmfdigit[y]));
+ 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;
}
}
}
@@ -2382,7 +2415,7 @@ static void t4_vpm_init(struct t4 *wc)
unsigned char reg;
unsigned int mask;
unsigned int ver;
- unsigned int i, x, y;
+ unsigned int i, x, y, gen2vpm=0;
if (!vpmsupport) {
printk("VPM: Support Disabled\n");
@@ -2405,10 +2438,22 @@ static void t4_vpm_init(struct t4 *wc)
int echotail = t4_vpm_echotail();
ver = t4_vpm_in(wc, x, 0x1a0); /* revision */
- if (ver != 0x26) {
+ if ((ver != 0x26) && (ver != 0x33)) {
printk("VPM: %s\n", x ? "Inoperable" : "Not Present");
return;
- }
+ }
+ if (ver == 0x33) {
+ if (x && !gen2vpm) {
+ printk("VPM: Inconsistent\n");
+ return;
+ }
+ ts->spanflags |= FLAG_VPM2GEN;
+ gen2vpm++;
+ } else if (gen2vpm) {
+ printk("VPM: Inconsistent\n");
+ return;
+ }
+
/* Setup GPIO's */
for (y=0;y<4;y++) {
@@ -2475,13 +2520,29 @@ static void t4_vpm_init(struct t4 *wc)
for (i = 0; i < MAX_DTMF_DET; i++) {
t4_vpm_out(wc, x, 0x98 + i, 0x40 | (i * 2) | ((x < 4) ? 0 : 1));
}
+ for (i = 0x34; i < 0x38; i++)
+ t4_vpm_out(wc, x, i, 0x00);
+ for (i = 0x3C; i < 0x40; i++)
+ t4_vpm_out(wc, x, i, 0x00);
+
+ for (i = 0x48; i < 0x4B; i++)
+ t4_vpm_out(wc, x, i, 0x00);
+ for (i = 0x50; i < 0x53; i++)
+ t4_vpm_out(wc, x, i, 0x00);
for (i = 0xB8; i < 0xBE; i++)
t4_vpm_out(wc, x, i, 0xFF);
+ if (gen2vpm) {
+ for (i = 0xBE; i < 0xC0; i++)
+ t4_vpm_out(wc, x, i, 0xFF);
+ } else {
+ for (i = 0xBE; i < 0xC0; i++)
+ t4_vpm_out(wc, x, i, 0x00);
+ }
for (i = 0xC0; i < 0xC4; i++)
t4_vpm_out(wc, x, i, (x < 4) ? 0x55 : 0xAA);
}
- printk("VPM: Present and operational servicing %d span(s)\n", vpmspans);
+ printk("VPM%s: Present and operational servicing %d span(s)\n", (gen2vpm ? "(2nd Gen)" : ""), vpmspans);
wc->vpm = T4_VPM_PRESENT;
}