diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-06-19 14:34:05 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2006-06-19 14:34:05 +0000 |
commit | 6446efb93dc10bb2d42fd664480fc1c8b8b0e456 (patch) | |
tree | 422ddc80377b61d6b7e3107c376d5d7e82b3de01 /wct4xxp_base.c | |
parent | 790db3fbe391a9147a1de81e9877c8a8640bd4f6 (diff) |
Merge the giant mess that is the Octasic API
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1117 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct4xxp_base.c')
-rw-r--r-- | wct4xxp_base.c | 380 |
1 files changed, 347 insertions, 33 deletions
diff --git a/wct4xxp_base.c b/wct4xxp_base.c index 31de0ca..17f76be 100644 --- a/wct4xxp_base.c +++ b/wct4xxp_base.c @@ -44,6 +44,7 @@ #include <linux/moduleparam.h> #endif #include "wct4xxp.h" +#include "vpm450m.h" /* * Tasklets provide better system interactive response at the cost of the @@ -170,14 +171,14 @@ static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct static int debug=0; static int timingcable = 0; static int highestorder; -static int t1e1override = -1; +static int t1e1override = 0x00; //0xFF; // -1 = jumper; 0xFF = E1 static int j1mode = 0; static int sigmode = FRMR_MODE_NO_ADDR_CMP; static int loopback = 0; static int alarmdebounce = 0; #ifdef VPM_SUPPORT static int vpmsupport = 1; -static int vpmdtmfsupport = 1; +static int vpmdtmfsupport = 0; static int vpmspans = 4; #define VPM_DEFAULT_DTMFTHRESHOLD 1000 static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; @@ -211,6 +212,8 @@ static int altab[] = { #define FLAG_2NDGEN (1 << 3) #define FLAG_2PORT (1 << 4) #define FLAG_VPM2GEN (1 << 5) +#define FLAG_OCTOPT (1 << 6) +#define FLAG_3RDGEN (1 << 7) #define CANARY 0xc0de @@ -220,8 +223,12 @@ struct devtype { }; static struct devtype wct4xxp = { "Wildcard TE410P/TE405P (1st Gen)", 0 }; +static struct devtype wct410p3 = { "Wildcard TE410P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct405p3 = { "Wildcard TE405P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; static struct devtype wct410p2 = { "Wildcard TE410P (2nd Gen)", FLAG_2NDGEN }; static struct devtype wct405p2 = { "Wildcard TE405P (2nd Gen)", FLAG_2NDGEN }; +static struct devtype wct205p3 = { "Wildcard TE205P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; +static struct devtype wct210p3 = { "Wildcard TE210P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; static struct devtype wct205 = { "Wildcard TE205P ", FLAG_2NDGEN | FLAG_2PORT }; static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT }; @@ -299,6 +306,8 @@ struct t4 { int flags; /* Device flags */ int master; /* Are we master */ int ledreg; /* LED Register */ + unsigned int gpio; + unsigned int gpioctl; int stopdma; /* Set to stop DMA */ unsigned int dmactrl; int e1recover; /* E1 recovery timer */ @@ -330,13 +339,15 @@ struct t4 { char *variety; int last0; /* for detecting double-missed IRQ */ int checktiming; /* Set >0 to cause the timing source to be checked */ + struct vpm450m *vpm450m; }; #define T4_VPM_PRESENT (1 << 28) #ifdef VPM_SUPPORT -static void t4_vpm_init(struct t4 *wc); +static void t4_vpm400_init(struct t4 *wc); +static void t4_vpm450_init(struct t4 *wc); static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold); #endif static void __set_clear(struct t4 *wc, int span); @@ -367,6 +378,9 @@ static void __t4_check_sigbits(struct t4 *wc, int span); #define WC_GPIO 9 #define WC_LADDR 10 #define WC_LDATA 11 +#define WC_LCS (1 << 11) +#define WC_LCS2 (1 << 12) +#define WC_LALE (1 << 13) #define WC_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ #define WC_ACTIVATE (1 << 12) #define WC_LREAD (1 << 15) @@ -417,6 +431,44 @@ static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const un #endif } +static inline void __t4_gpio_set(struct t4 *wc, unsigned bits, unsigned int val) +{ + unsigned int newgpio; + newgpio = wc->gpio & (~bits); + newgpio |= val; + if (newgpio != wc->gpio) { + wc->gpio = newgpio; + __t4_pci_out(wc, WC_GPIO, wc->gpio); + } +} + +static inline void __t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) +{ + unsigned int newgpioctl; + newgpioctl = wc->gpioctl & (~bits); + newgpioctl |= val; + if (newgpioctl != wc->gpioctl) { + wc->gpioctl = newgpioctl; + __t4_pci_out(wc, WC_GPIOCTL, wc->gpioctl); + } +} + +static inline void t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_gpio_setdir(wc, bits, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void t4_gpio_set(struct t4 *wc, unsigned int bits, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_gpio_set(wc, bits, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) { unsigned long flags; @@ -521,6 +573,80 @@ static inline unsigned int __t4_vpm_in(struct t4 *wc, int unit, const unsigned i return ret & 0xff; } +static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) +{ + int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; + if (!octopt) + __t4_gpio_set(wc, 0xff, (addr >> 8)); + __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); + if (!octopt) + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); + if (!octopt) + __t4_gpio_set(wc, 0xff, (value >> 8)); + __t4_pci_out(wc, WC_LDATA, (value & 0xffff)); + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE | WC_LCS)); + __t4_pci_out(wc, WC_LADDR, (0)); +} + +static inline unsigned int __t4_raw_oct_in(struct t4 *wc, const unsigned int addr) +{ + unsigned int ret; + int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; + if (!octopt) + __t4_gpio_set(wc, 0xff, (addr >> 8)); + __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); + if (!octopt) + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); +#ifdef PEDANTIC_OCTASIC_CHECKING + __t4_pci_out(wc, WC_LADDR, (WC_LALE)); +#endif + if (!octopt) { + __t4_gpio_setdir(wc, 0xff, 0x00); + __t4_gpio_set(wc, 0xff, 0x00); + } + __t4_pci_out(wc, WC_LADDR, (WC_LREAD | WC_LALE | WC_LCS)); + if (octopt) { + ret = __t4_pci_in(wc, WC_LDATA) & 0xffff; + } else { + ret = __t4_pci_in(wc, WC_LDATA) & 0xff; + ret |= (__t4_pci_in(wc, WC_GPIO) & 0xff) << 8; + } + __t4_pci_out(wc, WC_LADDR, (0)); + if (!octopt) + __t4_gpio_setdir(wc, 0xff, 0xff); + return ret & 0xffff; +} + +static inline unsigned int __t4_oct_in(struct t4 *wc, unsigned int addr) +{ +#ifdef PEDANTIC_OCTASIC_CHECKING + int count = 1000; +#endif + __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); + __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); + __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1)); +#ifdef PEDANTIC_OCTASIC_CHECKING + while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); + if (count != 1000) + printk("Yah, read can be slow...\n"); + if (!count) + printk("Read timed out!\n"); +#endif + return __t4_raw_oct_in(wc, 0x0004); +} + +static inline unsigned int t4_oct_in(struct t4 *wc, const unsigned int addr) +{ + unsigned long flags; + unsigned int ret; + spin_lock_irqsave(&wc->reglock, flags); + ret = __t4_oct_in(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + static inline unsigned int t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr) { unsigned long flags; @@ -555,6 +681,32 @@ static inline void __t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr #endif } +static inline void __t4_oct_out(struct t4 *wc, unsigned int addr, unsigned int value) +{ +#ifdef PEDANTIC_OCTASIC_CHECKING + int count = 1000; +#endif + __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); + __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); + __t4_raw_oct_out(wc, 0x0004, value); + __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1); +#ifdef PEDANTIC_OCTASIC_CHECKING + while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); + if (count != 1000) + printk("Yah, write can be slow\n"); + if (!count) + printk("Write timed out!\n"); +#endif +} + +static inline void t4_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_oct_out(wc, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + static inline void t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) { unsigned long flags; @@ -565,7 +717,49 @@ static inline void t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, static const char vpm_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', '*', '#'}; -static void __t4_check_vpm(struct t4 *wc, unsigned int newio) +static void t4_check_vpm450(struct t4 *wc) +{ + int channel, tone, start, span; +#if 0 + /* There's no point checking the interrupt, it's pointless. */ + vpm450m_checkirq(wc->vpm450m); +#endif + while(vpm450m_getdtmf(wc->vpm450m, &channel, &tone, &start)) { + span = channel & 0x3; + channel >>= 2; + if (!wc->t1e1) + channel -= 5; + else + channel -= 1; + if (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 (start) { + /* The octasic is supposed to mute us, but... Yah, you + guessed it. */ + if (wc->tspans[span]->dtmfmutemask & (1 << channel)) { + unsigned long flags; + struct zt_chan *chan = &wc->tspans[span]->span.chans[channel]; + int y; + 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, flags); + } + wc->tspans[span]->dtmfactive |= (1 << channel); + zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFDOWN | tone)); + } else { + wc->tspans[span]->dtmfactive &= ~(1 << channel); + zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFUP | tone)); + } + } + } +} + +static void __t4_check_vpm400(struct t4 *wc, unsigned int newio) { unsigned int digit, regval = 0; unsigned int regbyte; @@ -674,7 +868,7 @@ static void __hdlc_stop(struct t4 *wc, unsigned int span) int i = 0; if (debug & DEBUG_FRAMER) printk("Stopping HDLC controller on span %d\n", span+1); - + /* Clear receive and transmit timeslots */ for (i = 0; i < 4; i++) { __t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00); @@ -854,6 +1048,20 @@ static int t4_dacs(struct zt_chan *dst, struct zt_chan *src) #ifdef VPM_SUPPORT +void oct_set_reg(void *data, unsigned int reg, unsigned int val) +{ + struct t4 *wc = data; + t4_oct_out(wc, reg, val); +} + +unsigned int oct_get_reg(void *data, unsigned int reg) +{ + struct t4 *wc = data; + unsigned int ret; + ret = t4_oct_in(wc, reg); + return ret; +} + static int t4_vpm_unit(int span, int channel) { int unit = 0; @@ -878,6 +1086,7 @@ static int t4_echocan(struct zt_chan *chan, int eclen) struct t4 *wc = chan->pvt; int channel; int unit; + if (!wc->vpm) return -ENODEV; @@ -888,14 +1097,25 @@ static int t4_echocan(struct zt_chan *chan, int eclen) channel = chan->chanpos; else channel = chan->chanpos + 4; - unit = t4_vpm_unit(chan->span->offset, channel); - if(debug & DEBUG_ECHOCAN) - printk("echocan: Card is %d, Channel is %d, Span is %d, unit is %d, unit offset is %d length %d\n", - wc->num, chan->chanpos, chan->span->offset, unit, channel, eclen); - if (eclen) - t4_vpm_out(wc,unit,channel,0x3e); - else - t4_vpm_out(wc,unit,channel,0x01); + if (wc->vpm450m) { + channel = channel << 2; + channel |= chan->span->offset; + if(debug & DEBUG_ECHOCAN) + printk("echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n", + wc->num, chan->chanpos, chan->span->offset, channel, eclen); + vpm450m_setec(wc->vpm450m, channel, eclen); +// Mark msleep(10); +// msleep(100); // longer test + } else { + unit = t4_vpm_unit(chan->span->offset, channel); + if(debug & DEBUG_ECHOCAN) + printk("echocan: Card is %d, Channel is %d, Span is %d, unit is %d, unit offset is %d length %d\n", + wc->num, chan->chanpos, chan->span->offset, unit, channel, eclen); + if (eclen) + t4_vpm_out(wc,unit,channel,0x3e); + else + t4_vpm_out(wc,unit,channel,0x01); + } return 0; } #endif @@ -907,6 +1127,7 @@ static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) struct t4 *wc = chan->pvt; #ifdef VPM_SUPPORT int j; + int channel; struct t4_span *ts = wc->tspans[chan->span->offset]; #endif @@ -944,6 +1165,13 @@ static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) ts->dtmfmutemask |= (1 << (chan->chanpos - 1)); else ts->dtmfmutemask &= ~(1 << (chan->chanpos - 1)); + if (wc->vpm450m) { + channel = (chan->chanpos) << 2; + if (!wc->t1e1) + channel += (4 << 2); + channel |= chan->span->offset; + vpm450m_setdtmf(wc->vpm450m, channel, j & ZT_TONEDETECT_ON, j & ZT_TONEDETECT_MUTE); + } return 0; #endif default: @@ -1135,7 +1363,7 @@ static int t4_shutdown(struct zt_span *span) } if (debug & DEBUG_MAIN) printk("Shutting down span %d (%s)\n", span->spanno, span->name); - + spin_lock_irqsave(&wc->reglock, flags); wasrunning = span->flags & ZT_FLAG_RUNNING; @@ -1199,7 +1427,7 @@ static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) wc->tspans[lc->sync - 1]->psync = span->offset + 1; } wc->checktiming = 1; - + /* If we're already running, then go ahead and apply the changes */ if (span->flags & ZT_FLAG_RUNNING) return t4_startup(span); @@ -1230,7 +1458,7 @@ static int t4_chanconfig(struct zt_chan *chan, int sigtype) /* (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); + 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); @@ -1243,6 +1471,7 @@ static int t4_chanconfig(struct zt_chan *chan, int sigtype) } else ts->sigchan = NULL; + } else { ts->sigchan = (sigtype == ZT_SIG_HARDHDLC) ? chan : NULL; @@ -1814,7 +2043,9 @@ static int t4_startup(struct zt_span *span) #ifdef VPM_SUPPORT if (!alreadyrunning && !wc->vpm) { wait_a_little(); - t4_vpm_init(wc); + t4_vpm400_init(wc); + if (!wc->vpm) + t4_vpm450_init(wc); wc->dmactrl |= wc->vpm; t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); } @@ -1942,11 +2173,13 @@ static inline void __receive_span(struct t4_span *ts) #ifdef VPM_SUPPORT int y; unsigned int merged; - if ((merged = ts->dtmfactive & ts->dtmfmutemask)) { + 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 (merged & (1 << y)) { memset(ts->span.chans[y].readchunk, ZT_XLAW(0, (ts->span.chans + y)), ZT_CHUNKSIZE); + } } } #endif @@ -2585,6 +2818,7 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) unsigned long flags; unsigned char cis; int x; + int needcheckvpm450=0; unsigned int status; #if 0 @@ -2599,17 +2833,18 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) inirq = 1; /* Make sure it's really for us */ status = t4_pci_in(wc, WC_INTR); -#if 1 +#if 1 t4_pci_out(wc, WC_INTR, status & 0x00000008); #endif /* Ignore if it's not for us */ - if (!(status & 0x7)) + if (!(status & 0x7)) { #ifdef LINUX26 return IRQ_NONE; #else return; #endif + } if (!wc->spansstarted) { printk("Not prepped yet!\n"); @@ -2622,7 +2857,8 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) wc->intcount++; #if 1 - if (wc->intcount < 20) + if ((wc->intcount < 20) && debug) + printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, __t4_framer_in(wc, 0, FRMR_CIS)); #endif @@ -2687,7 +2923,7 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) } #ifdef VPM_SUPPORT if (wc->vpm) { - if (!(wc->intcount % 16) && !(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) { + if (!wc->vpm450m && !(wc->intcount % 16) && !(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) { /* Check DTMF events */ int span = (wc->intcount >> 4) & 0x3; int y; @@ -2724,8 +2960,16 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) } } } + } + 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; + } } else if ((status & 0xff00) != 0xff00) - __t4_check_vpm(wc, (status & 0xff00) >> 8); + __t4_check_vpm400(wc, (status & 0xff00) >> 8); } #endif @@ -2746,6 +2990,11 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) } spin_unlock_irqrestore(&wc->reglock, flags); + if (needcheckvpm450 && vpmdtmfsupport) { + t4_check_vpm450(wc); + needcheckvpm450 = 0; + } + #ifndef ENABLE_WORKQUEUES t4_pci_out(wc, WC_INTR, 0); #endif @@ -2840,7 +3089,42 @@ static int t4_vpm_echotail(void) return echotail; } -static void t4_vpm_init(struct t4 *wc) +static void t4_vpm450_init(struct t4 *wc) +{ + unsigned int check1, check2; + int laws[4] = { 0, }; + int x; + if (!vpmsupport) { + printk("VPM450M: Support Disabled\n"); + return; + } + /* Turn on GPIO/DATA mux if supported */ + t4_gpio_setdir(wc, (1 << 24), (1 << 24)); + __t4_raw_oct_out(wc, 0x000a, 0x5678); + __t4_raw_oct_out(wc, 0x0004, 0x1234); + check1 = __t4_raw_oct_in(wc, 0x0004); + check2 = __t4_raw_oct_in(wc, 0x000a); + if (1 || debug) + printk("OCT Result: %04x/%04x\n", __t4_raw_oct_in(wc, 0x0004), __t4_raw_oct_in(wc, 0x000a)); + if (__t4_raw_oct_in(wc, 0x0004) != 0x1234) { + printk("VPM450: Not Present\n"); + return; + } + /* Setup alaw vs ulaw rules */ + for (x=0;x<wc->numspans;x++) { + if (wc->tspans[x]->span.channels > 24) + laws[x] = 1; + } + if (!(wc->vpm450m = init_vpm450m(wc, laws))) { + printk("VPM450: Failed to initialize\n"); + return; + } + wc->vpm = T4_VPM_PRESENT; + printk("VPM450: Present and operational servicing %d span(s)\n", vpmspans); + +} + +static void t4_vpm400_init(struct t4 *wc) { unsigned char reg; unsigned int mask; @@ -2848,7 +3132,7 @@ static void t4_vpm_init(struct t4 *wc) unsigned int i, x, y, gen2vpm=0; if (!vpmsupport) { - printk("VPM: Support Disabled\n"); + printk("VPM400M: Support Disabled\n"); return; } @@ -2869,18 +3153,18 @@ static void t4_vpm_init(struct t4 *wc) ver = t4_vpm_in(wc, x, 0x1a0); /* revision */ if ((ver != 0x26) && (ver != 0x33)) { - printk("VPM: %s\n", x ? "Inoperable" : "Not Present"); + printk("VPM400: %s\n", x ? "Inoperable" : "Not Present"); return; } if (ver == 0x33) { if (x && !gen2vpm) { - printk("VPM: Inconsistent\n"); + printk("VPM400: Inconsistent\n"); return; } ts->spanflags |= FLAG_VPM2GEN; gen2vpm++; } else if (gen2vpm) { - printk("VPM: Inconsistent\n"); + printk("VPM400: Inconsistent\n"); return; } @@ -2913,11 +3197,11 @@ static void t4_vpm_init(struct t4 *wc) reg &= 0xE0; if (ts->spantype == TYPE_E1) { if (x < vpmspans) - printk("VPM: Span %d A-law mode\n", spanno); + printk("VPM400: Span %d A-law mode\n", spanno); reg |= 0x01; } else { if (x < vpmspans) - printk("VPM: Span %d U-law mode\n", spanno); + printk("VPM400: Span %d U-law mode\n", spanno); reg &= ~0x01; } t4_vpm_out(wc,x,0x20,(reg | 0x20)); @@ -2972,7 +3256,7 @@ static void t4_vpm_init(struct t4 *wc) t4_vpm_out(wc, x, i, (x < 4) ? 0x55 : 0xAA); } - printk("VPM%s: Present and operational servicing %d span(s)\n", (gen2vpm ? "(2nd Gen)" : ""), vpmspans); + printk("VPM400%s: Present and operational servicing %d span(s)\n", (gen2vpm ? " (2nd Gen)" : ""), vpmspans); wc->vpm = T4_VPM_PRESENT; } @@ -3076,6 +3360,10 @@ static int t4_hardware_init_2(struct t4 *wc) int x; unsigned int falcver; + if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) { + wc->tspans[0]->spanflags |= FLAG_OCTOPT; + printk("Octasic optimized!\n"); + } /* Setup LEDS, take out of reset */ t4_pci_out(wc, WC_LEDS, 0x000000ff); t4_activate(wc); @@ -3308,6 +3596,21 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i } printk("Found a Wildcard: %s\n", wc->variety); + wc->gpio = 0x00000000; + t4_pci_out(wc, WC_GPIO, wc->gpio); + t4_gpio_setdir(wc, (1 << 17), (1 << 17)); + t4_gpio_setdir(wc, (0xff), (0xff)); + +#if 0 + for (x=0;x<0x10000;x++) { + __t4_raw_oct_out(wc, 0x0004, x); + __t4_raw_oct_out(wc, 0x000a, x ^ 0xffff); + if (__t4_raw_oct_in(wc, 0x0004) != x) + printk("Register 4 failed %04x\n", x); + if (__t4_raw_oct_in(wc, 0x000a) != (x ^ 0xffff)) + printk("Register 10 failed %04x\n", x); + } +#endif res = 0; } else res = -ENOMEM; @@ -3332,7 +3635,8 @@ static int t4_hardware_stop(struct t4 *wc) } t4_pci_out(wc, WC_RDADDR, 0x0000000); t4_pci_out(wc, WC_WRADDR, 0x0000000); - t4_pci_out(wc, WC_GPIO, 0x0000000); + wc->gpio = 0x00000000; + t4_pci_out(wc, WC_GPIO, wc->gpio); t4_pci_out(wc, WC_LEDS, 0x00000000); printk("\nStopped TE%dXXP, Turned off DMA\n", wc->numspans); @@ -3347,6 +3651,10 @@ static void __devexit t4_remove_one(struct pci_dev *pdev) /* Stop hardware */ t4_hardware_stop(wc); + /* Release vpm450m */ + if (wc->vpm450m) + release_vpm450m(wc->vpm450m); + wc->vpm450m = NULL; /* Unregister spans */ if (wc->tspans[0]->span.flags & ZT_FLAG_REGISTERED) zt_unregister(&wc->tspans[0]->span); @@ -3402,8 +3710,14 @@ static void __devexit t4_remove_one(struct pci_dev *pdev) static struct pci_device_id t4_pci_tbl[] __devinitdata = { { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct4xxp }, + + { 0xd161, 0x0410, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p3 }, + { 0xd161, 0x0405, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p3 }, { 0xd161, 0x0410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p2 }, { 0xd161, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p2 }, + + { 0xd161, 0x0205, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p3 }, + { 0xd161, 0x0210, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p3 }, { 0xd161, 0x0205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct205 }, { 0xd161, 0x0210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct210 }, { 0, } |