From b10b2471d9d8b74474fee28b91c5b6ad1c985b9d Mon Sep 17 00:00:00 2001 From: markster Date: Mon, 28 Nov 2005 23:42:01 +0000 Subject: Add support for next generation VPM400M git-svn-id: http://svn.digium.com/svn/zaptel/trunk@834 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wct4xxp.c | 145 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file 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; } -- cgit v1.2.3