diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2002-09-03 02:32:50 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2002-09-03 02:32:50 +0000 |
commit | c40b2fa76bb9b59efd40c11dc328440242eee3fe (patch) | |
tree | bacb3878cfacaf3520e18405efff40113e176566 /wct1xxp.c | |
parent | 1c9885532e2572eeb5a95fa240c501d5fb91459a (diff) |
Version 0.3.0 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@100 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wct1xxp.c')
-rwxr-xr-x | wct1xxp.c | 486 |
1 files changed, 382 insertions, 104 deletions
@@ -96,10 +96,10 @@ static char *chips[] = "DS2154", "DS21354", "DS21554", - "Unknown Chip (4)", + "Unknown Chip (7)", }; -static int chanmap[] = +static int chanmap_t1[] = { 2,1,0, 6,5,4, 10,9,8, @@ -109,6 +109,16 @@ static int chanmap[] = 26,25,24, 30,29,28 }; +static int chanmap_e1[] = +{ 2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + #ifdef FANCY_ALARM static int altab[] = { 0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, @@ -118,32 +128,42 @@ static int altab[] = { struct t1xxp { struct pci_dev *dev; spinlock_t lock; + int ise1; int num; /* Our offset for finding channel 1 */ int offset; char *variety; int intcount; int usecount; + int clocktimeout; int sync; int dead; int blinktimer; int alarmtimer; + int loopupcnt; + int loopdowncnt; + int *chanmap; #ifdef FANCY_ALARM int alarmpos; #endif unsigned char ledtestreg; unsigned char outbyte; unsigned long ioaddr; + /* T1 signalling */ unsigned char txsiga[3]; unsigned char txsigb[3]; dma_addr_t readdma; dma_addr_t writedma; volatile unsigned char *writechunk; /* Double-word aligned write memory */ volatile unsigned char *readchunk; /* Double-word aligned read memory */ + unsigned char ec_chunk1[31][ZT_CHUNKSIZE]; + unsigned char ec_chunk2[31][ZT_CHUNKSIZE]; struct zt_span span; /* Span */ - struct zt_chan chans[24]; /* Channels */ + struct zt_chan chans[31]; /* Channels */ }; +int debug = 0; /* doesnt do anything */ + static struct t1xxp *cards[WC_MAX_CARDS]; static inline void start_alarm(struct t1xxp *wc) @@ -270,7 +290,7 @@ static void t1xxp_enable_interrupts(struct t1xxp *wc) /* Clear interrupts */ outb(0xff, wc->ioaddr + WC_INTSTAT); /* Enable interrupts (we care about all of them) */ - outb(0x3f, wc->ioaddr + WC_MASK0); + outb(0x3f, wc->ioaddr + WC_MASK0); /* No external interrupts */ outb(0x00, wc->ioaddr + WC_MASK1); } @@ -283,7 +303,7 @@ static void t1xxp_start_dma(struct t1xxp *wc) schedule_timeout(1); outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); outb(0x01, wc->ioaddr + WC_OPER); - printk("Started DMA\n"); + if (debug) printk("Started DMA\n"); } static void __t1xxp_stop_dma(struct t1xxp *wc) @@ -302,6 +322,13 @@ static void __t1xxp_set_clear(struct t1xxp *wc) /* Setup registers */ int x,y; unsigned char b; + + /* No such thing under E1 */ + if (wc->ise1) { + printk("Can't set clear mode on an E1!\n"); + return; + } + for (x=0;x<3;x++) { b = 0; for (y=0;y<8;y++) @@ -311,7 +338,7 @@ static void __t1xxp_set_clear(struct t1xxp *wc) } } -static void t1xxp_framer_start(struct t1xxp *wc) +static void t1xxp_t1_framer_start(struct t1xxp *wc) { int i; char *coding, *framing; @@ -369,19 +396,93 @@ static void t1xxp_framer_start(struct t1xxp *wc) spin_unlock_irqrestore(&wc->lock, flags); } +static void t1xxp_e1_framer_start(struct t1xxp *wc) +{ + int i; + char *coding, *framing; + unsigned long endjiffies; + int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; + long flags; + char *crcing = ""; + unsigned char ccr1, tcr1; + + spin_lock_irqsave(&wc->lock, flags); + + /* Build up config */ + ccr1 = 0; + tcr1 = 8; + if (wc->span.lineconfig & ZT_CONFIG_CCS) { + coding = "CCS"; /* Receive CCS */ + ccr1 |= 8; + } else { + tcr1 |= 0x20; + coding = "CAS"; + } + if (wc->span.lineconfig & ZT_CONFIG_HDB3) { + ccr1 |= 0x44; /* TX/RX HDB3 */ + framing = "HDB3"; + } else { + framing = "AMI"; + } + if (wc->span.lineconfig & ZT_CONFIG_CRC4) { + ccr1 |= 0x11; + crcing = " with CRC4"; + } + __t1_set_reg(wc, 0x12, tcr1); + __t1_set_reg(wc, 0x14, ccr1); + __t1_set_reg(wc, 0x18, 0x20); /* 120 Ohm */ + + +#if 0 /* XXX Does LBO Matter? XXX */ + /* Set outgoing LBO */ + __t1_set_reg(wc, 0x7c, wc->span.txlevel << 5); +#endif + + printk("Using %s/%s coding/framing%s 120 Ohms\n", coding, framing,crcing); + if (!alreadyrunning) { + + __t1_set_reg(wc,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ + __t1_set_reg(wc,0x20,0x1b); /* TAFR */ + __t1_set_reg(wc,0x21,0x5f); /* TNAFR */ + __t1_set_reg(wc,0x40,0xb); /* TSR1 */ + for(i = 0x41; i <= 0x4f; i++) __t1_set_reg(wc,i,0x55); + for(i = 0x22; i <= 0x25; i++) __t1_set_reg(wc,i,0xff); + spin_unlock_irqrestore(&wc->lock, flags); + + /* Wait 100ms to give plenty of time for reset */ + endjiffies = jiffies + 10; + while(endjiffies < jiffies); + + spin_lock_irqsave(&wc->lock, flags); + + __t1_set_reg(wc, 0x1b, 0x9a); /* Set ESR */ + __t1_set_reg(wc, 0x1b, 0x82); /* TSCLKM only now */ + + /* Reset LIRST bit and reset elastic stores */ + + wc->span.flags |= ZT_FLAG_RUNNING; + } + spin_unlock_irqrestore(&wc->lock, flags); +} + static int t1xxp_framer_sanity_check(struct t1xxp *wc) { int res; int chipid; long flags; + int x; /* Sanity check */ spin_lock_irqsave(&wc->lock, flags); + for (x=0x0;x<192;x++) + __t1_set_reg(wc, x, 0); + res = __t1_get_reg(wc, 0x0f); res = __t1_get_reg(wc, 0x0f); chipid = ((res & 0x80) >> 5) | ((res & 0x30) >> 4); + wc->ise1 = (res & 0x80) ? (1 << 4) : 0; spin_unlock_irqrestore(&wc->lock, flags); - printk("Framer: %s, Revision: %d\n", chips[chipid], res & 0xf); + printk("Framer: %s, Revision: %d (%s)\n", chips[chipid], res & 0xf, wc->ise1 ? "E1" : "T1"); return 0; } @@ -395,25 +496,44 @@ static int t1xxp_framer_hard_reset(struct t1xxp *wc) for (x=0x0;x<192;x++) __t1_set_reg(wc, x, 0); - /* Full-on sync required */ - __t1_set_reg(wc, 0x2b, 0x08); + if (wc->ise1) { + /* Set LOTCMC (switch to RCLCK if TCLK fails) */ + __t1_set_reg(wc, 0x1a, 0x04); + + /* RSYNC is an input */ + __t1_set_reg(wc, 0x10, 0x20); + + /* Rx elastic store enabled, 2.048 Mhz (in theory) */ + __t1_set_reg(wc, 0x11, 0x06); + + /* TSYNC is an input, Tsis mode */ + __t1_set_reg(wc, 0x12, 0x08); - /* RSYNC is an input */ - __t1_set_reg(wc, 0x2c, 0x08); + /* Tx elastic store enabled, 2.048 Mhz (in theory) */ + __t1_set_reg(wc, 0x1b, 0x82); - /* Enable tx RBS bits */ - __t1_set_reg(wc, 0x35, 0x10); - /* TSYNC is output */ - __t1_set_reg(wc, 0x36, 0x04); + + } else { + /* Full-on sync required for T1 */ + __t1_set_reg(wc, 0x2b, 0x08); + /* RSYNC is an input */ + __t1_set_reg(wc, 0x2c, 0x08); - /* Tx and Rx elastic store enabled, 2.048 Mhz (in theory) */ - __t1_set_reg(wc, 0x37, 0x9c); + /* Enable tx RBS bits */ + __t1_set_reg(wc, 0x35, 0x10); - /* Setup Loopup / Loopdown codes */ - __t1_set_reg(wc, 0x12, 0x22); - __t1_set_reg(wc, 0x14, 0x80); - __t1_set_reg(wc, 0x15, 0x80); + /* TSYNC is output */ + __t1_set_reg(wc, 0x36, 0x04); + + /* Tx and Rx elastic store enabled, 2.048 Mhz (in theory) */ + __t1_set_reg(wc, 0x37, 0x9c); + + /* Setup Loopup / Loopdown codes */ + __t1_set_reg(wc, 0x12, 0x22); + __t1_set_reg(wc, 0x14, 0x80); + __t1_set_reg(wc, 0x15, 0x80); + } spin_unlock_irqrestore(&wc->lock, flags); return 0; @@ -428,30 +548,39 @@ static int t1xxp_rbsbits(struct zt_chan *chan, int bits) /* Byte offset */ spin_lock_irqsave(&wc->lock, flags); + if (wc->ise1) { + if (chan->chanpos > 15) { + mask = (bits | (wc->chans[chan->chanpos - 15].txsig << 4)); + __t1_set_reg(wc, 0x41 + chan->chanpos - 15, mask); + } else if (chan->chanpos < 15) { + mask = ((bits << 4) | wc->chans[chan->chanpos + 15].txsig); + __t1_set_reg(wc, 0x41 + chan->chanpos, mask); + } + } else { + b = (chan->chanpos - 1) / 8; + o = (chan->chanpos - 1) % 8; - b = (chan->chanpos - 1) / 8; - o = (chan->chanpos - 1) % 8; - - mask = (1 << o); + mask = (1 << o); - if (bits & ZT_ABIT) { - /* Set A-bit */ - wc->txsiga[b] |= mask; - } else { - /* Clear A-bit */ - wc->txsiga[b] &= ~mask; - } - if (bits & ZT_BBIT) { - /* Set B-bit */ - wc->txsigb[b] |= mask; - } else { - wc->txsigb[b] &= ~mask; + if (bits & ZT_ABIT) { + /* Set A-bit */ + wc->txsiga[b] |= mask; + } else { + /* Clear A-bit */ + wc->txsiga[b] &= ~mask; + } + if (bits & ZT_BBIT) { + /* Set B-bit */ + wc->txsigb[b] |= mask; + } else { + wc->txsigb[b] &= ~mask; + } + /* Output new values */ + __t1_set_reg(wc, 0x70 + b, wc->txsiga[b]); + __t1_set_reg(wc, 0x73 + b, wc->txsigb[b]); + __t1_set_reg(wc, 0x76 + b, wc->txsiga[b]); + __t1_set_reg(wc, 0x79 + b, wc->txsigb[b]); } - /* Output new values */ - __t1_set_reg(wc, 0x70 + b, wc->txsiga[b]); - __t1_set_reg(wc, 0x73 + b, wc->txsigb[b]); - __t1_set_reg(wc, 0x76 + b, wc->txsiga[b]); - __t1_set_reg(wc, 0x79 + b, wc->txsigb[b]); spin_unlock_irqrestore(&wc->lock, flags); return 0; } @@ -468,9 +597,22 @@ static int t1xxp_startup(struct zt_span *span) { struct t1xxp *wc = span->pvt; - int alreadyrunning = span->flags & ZT_FLAG_RUNNING; + int i,alreadyrunning = span->flags & ZT_FLAG_RUNNING; + + /* initialize the start value for the entire chunk of last ec buffer */ + for(i = 0; i < span->channels; i++) + { + memset(wc->ec_chunk1[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + memset(wc->ec_chunk2[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + } + /* Reset framer with proper parameters and start */ - t1xxp_framer_start(wc); + if (wc->ise1) + t1xxp_e1_framer_start(wc); + else + t1xxp_t1_framer_start(wc); printk("Calling startup (flags is %d)\n", span->flags); if (!alreadyrunning) { @@ -497,10 +639,67 @@ static int t1xxp_shutdown(struct zt_span *span) return 0; } -static int t1xxp_maint(struct zt_span *span, int mode) +static int t1xxp_maint(struct zt_span *span, int cmd) { - /* XXX Implement me XXX */ - return -1; + struct t1xxp *wc = span->pvt; + int res = 0; + long flags; + spin_lock_irqsave(&wc->lock, flags); + if (wc->ise1) { + switch(cmd) { + case ZT_MAINT_NONE: + __t1_set_reg(wc,0xa8,0); /* no loops */ + break; + case ZT_MAINT_LOCALLOOP: + __t1_set_reg(wc,0xa8,0x40); /* local loop */ + break; + case ZT_MAINT_REMOTELOOP: + __t1_set_reg(wc,0xa8,0x80); /* remote loop */ + break; + case ZT_MAINT_LOOPUP: + case ZT_MAINT_LOOPDOWN: + case ZT_MAINT_LOOPSTOP: + res = -ENOSYS; + break; + default: + printk("wct1xxp/E1: Unknown maint command: %d\n", cmd); + res = -EINVAL; + break; + } + } else { + switch(cmd) { + case ZT_MAINT_NONE: + __t1_set_reg(wc,0x19,0); /* no local loop */ + __t1_set_reg(wc,0x0a,0); /* no remote loop */ + break; + case ZT_MAINT_LOCALLOOP: + __t1_set_reg(wc,0x19,0x40); /* local loop */ + __t1_set_reg(wc,0x0a,0); /* no remote loop */ + break; + case ZT_MAINT_REMOTELOOP: + __t1_set_reg(wc,0x1e,0); /* no local loop */ + __t1_set_reg(wc,0x0a,0x40); /* remote loop */ + break; + case ZT_MAINT_LOOPUP: + __t1_set_reg(wc,0x30,2); /* send loopup code */ + __t1_set_reg(wc,0x12,0x22); /* send loopup code */ + __t1_set_reg(wc,0x13,0x80); /* send loopup code */ + break; + case ZT_MAINT_LOOPDOWN: + __t1_set_reg(wc,0x30,2); /* send loopdown code */ + __t1_set_reg(wc,0x12,0x62); /* send loopdown code */ + __t1_set_reg(wc,0x13,0x90); /* send loopdown code */ + break; + case ZT_MAINT_LOOPSTOP: + __t1_set_reg(wc,0x30,0); /* stop sending loopup code */ + break; + default: + printk("wct1xxp/T1: Unknown maint command: %d\n", cmd); + res = -EINVAL; + } + } + spin_unlock_irqrestore(&wc->lock, flags); + return res; } static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) @@ -511,7 +710,7 @@ static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) spin_lock_irqsave(&wc->lock, flags); - if (alreadyrunning) + if (alreadyrunning && !wc->ise1) __t1xxp_set_clear(wc); spin_unlock_irqrestore(&wc->lock, flags); @@ -525,7 +724,6 @@ static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) span->txlevel = lc->lbo; span->rxlevel = 0; /* Do we want to SYNC on receive or not */ - span->syncsrc = 0; wc->sync = lc->sync; /* If already running, apply changes immediately */ if (span->flags & ZT_FLAG_RUNNING) @@ -556,7 +754,10 @@ static int t1xxp_software_init(struct t1xxp *wc) wc->span.maint = t1xxp_maint; wc->span.open = t1xxp_open; wc->span.close = t1xxp_close; - wc->span.channels = 24; + if (wc->ise1) + wc->span.channels = 31; + else + wc->span.channels = 24; wc->span.chans = wc->chans; wc->span.flags = ZT_FLAG_RBS; wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; @@ -564,7 +765,7 @@ static int t1xxp_software_init(struct t1xxp *wc) wc->span.pvt = wc; wc->span.deflaw = ZT_LAW_MULAW; init_waitqueue_head(&wc->span.maintq); - for (x=0;x<24;x++) { + for (x=0;x<wc->span.channels;x++) { sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | @@ -620,6 +821,10 @@ static inline void __handle_leds(struct t1xxp *wc) } else { /* No Alarm */ oldreg = wc->ledtestreg; + if (wc->span.maintstat != ZT_MAINT_NONE) + wc->ledtestreg |= BIT_TEST; + else + wc->ledtestreg &= ~BIT_TEST; if (wc->span.flags & ZT_FLAG_RUNNING) wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; else @@ -643,9 +848,9 @@ static void t1xxp_transmitprep(struct t1xxp *wc, int ints) } zt_transmit(&wc->span); for (y=0;y<ZT_CHUNKSIZE;y++) { - for (x=0;x<24;x++) { + for (x=0;x<wc->span.channels;x++) { /* Put channel number as outgoing data */ - txbuf[y * 32 + ((chanmap[x] + wc->offset) & 0x1f)] = + txbuf[y * 32 + ((wc->chanmap[x] + wc->offset) & 0x1f)] = wc->chans[x].writechunk[y]; } } @@ -662,29 +867,32 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints) } else { rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32; } - for (x=3;x<32;x+=4) { - if (rxbuf[(x + WC_OFFSET) & 0x1f] == 0x7f) { - if (wc->offset != (x-3)) { - wc->offset = x - 3; + if (!wc->ise1) { + for (x=3;x<32;x+=4) { + if (rxbuf[(x + WC_OFFSET) & 0x1f] == 0x7f) { + if (wc->offset != (x-3)) { + wc->offset = x - 3; #if 1 - printk("New offset: %d\n", wc->offset); + if (debug) printk("New offset: %d\n", wc->offset); #endif + } } } } for (y=0;y<ZT_CHUNKSIZE;y++) { - for (x=0;x<24;x++) { + for (x=0;x<wc->span.channels;x++) { /* XXX Optimize, remove * and + XXX */ /* Must map received channels into appropriate data */ wc->chans[x].readchunk[y] = - rxbuf[32 * y + ((chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; + rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; } } - /* XXX We should apply echo cancellation closer -- we're wasting - 8 taps XXX */ - for (x=0;x<24;x++) - zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); - + for (x=0;x<wc->span.channels;x++) { + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, + wc->ec_chunk2[x]); + memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); + memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); + } zt_receive(&wc->span); } @@ -692,18 +900,36 @@ static void __t1xxp_check_sigbits(struct t1xxp *wc, int x) { int a,b,i,y,rxs; - a = __t1_get_reg(wc, 0x60 + x); - b = __t1_get_reg(wc, 0x63 + x); - for (y=0;y<8;y++) { - i = x * 8 + y; - rxs = 0; - if (a & (1 << y)) - rxs |= ZT_ABIT; - if (b & (1 << y)) - rxs |= ZT_BBIT; - if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) - zt_rbsbits(&wc->chans[i], rxs); + if (wc->ise1) { + /* Read 5 registers at a time, loading 10 channels at a time */ + for (i = (x *5); i < (x * 5) + 5; i++) { + a = __t1_get_reg(wc, 0x31 + i); + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->chans[i+15].sig & ZT_SIG_CLEAR)) { + if (wc->chans[i+15].rxsig != rxs) + zt_rbsbits(&wc->chans[i+15], rxs); + } + rxs = (a >> 4) & 0xf; + if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->chans[i].rxsig != rxs) + zt_rbsbits(&wc->chans[i], rxs); + } + } + } else { + a = __t1_get_reg(wc, 0x60 + x); + b = __t1_get_reg(wc, 0x63 + x); + for (y=0;y<8;y++) { + i = x * 8 + y; + rxs = 0; + if (a & (1 << y)) + rxs |= ZT_ABIT; + if (b & (1 << y)) + rxs |= ZT_BBIT; + if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->chans[i].rxsig != rxs) + zt_rbsbits(&wc->chans[i], rxs); + } } } } @@ -714,13 +940,18 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) int alarms; int x,j; - /* Get RIR3 */ - c = __t1_get_reg(wc, 0x10); - wc->span.rxlevel = c >> 6; - - /* Get status register s*/ - __t1_set_reg(wc, 0x20, 0xff); - c = __t1_get_reg(wc, 0x20); + if (wc->ise1) { + __t1_set_reg(wc, 0x06, 0xff); + c = __t1_get_reg(wc, 0x6); + } else { + /* Get RIR2 */ + c = __t1_get_reg(wc, 0x31); + wc->span.rxlevel = c >> 6; + + /* Get status register s*/ + __t1_set_reg(wc, 0x20, 0xff); + c = __t1_get_reg(wc, 0x20); + } /* Assume no alarms */ alarms = 0; @@ -728,6 +959,31 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) /* And consider only carrier alarms */ wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + if (wc->ise1) { + /* XXX Implement me XXX */ + } else { + /* Detect loopup code if we're not sending one */ + if ((!wc->span.mainttimer) && (c & 0x80)) { + /* Loop-up code detected */ + if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { + __t1_set_reg(wc, 0x1e, 0); /* No local loop */ + __t1_set_reg(wc, 0x0a, 0x40); /* Remote Loop */ + wc->span.maintstat = ZT_MAINT_REMOTELOOP; + } + } else + wc->loopupcnt = 0; + /* Same for loopdown code */ + if ((!wc->span.mainttimer) && (c & 0x40)) { + /* Loop-down code detected */ + if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { + __t1_set_reg(wc, 0x1e, 0); /* No local loop */ + __t1_set_reg(wc, 0x0a, 0x0); /* No remote Loop */ + wc->span.maintstat = ZT_MAINT_NONE; + } + } else + wc->loopdowncnt = 0; + } + if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { for (x=0,j=0;x < wc->span.channels;x++) if ((wc->chans[x].flags & ZT_FLAG_OPEN) || @@ -737,12 +993,18 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) alarms |= ZT_ALARM_NOTOPEN; } - /* Check actual alarm status */ - if (c & 0x3) - alarms |= ZT_ALARM_RED; - if (c & 0x8) - alarms |= ZT_ALARM_BLUE; - + if (wc->ise1) { + if (c & 0x9) + alarms |= ZT_ALARM_RED; + if (c & 0x2) + alarms |= ZT_ALARM_BLUE; + } else { + /* Check actual alarm status */ + if (c & 0x3) + alarms |= ZT_ALARM_RED; + if (c & 0x8) + alarms |= ZT_ALARM_BLUE; + } /* Keep track of recovering */ if ((!alarms) && wc->span.alarms) wc->alarmtimer = ZT_ALARMSETTLE_TIME; @@ -752,11 +1014,14 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) #if 0 printk("Going into yellow alarm\n"); #endif - __t1_set_reg(wc, 0x35, 0x11); + if (wc->ise1) + __t1_set_reg(wc, 0x21, 0x7f); + else + __t1_set_reg(wc, 0x35, 0x11); } if (wc->span.alarms != alarms) { - d = __control_get_reg(wc, 0); + d = __control_get_reg(wc, WC_CLOCK); start_alarm(wc); if (!(alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && wc->sync) { @@ -767,7 +1032,7 @@ static void __t1xxp_check_alarms(struct t1xxp *wc) wc->span.syncsrc = 0; d &= ~1; } - __control_set_reg(wc, 0, d); + __control_set_reg(wc, WC_CLOCK, d); } if (wc->alarmtimer) alarms |= ZT_ALARM_RECOVER; @@ -788,7 +1053,10 @@ static void __t1xxp_do_counters(struct t1xxp *wc) #if 0 printk("Coming out of alarm\n"); #endif - __t1_set_reg(wc, 0x35, 0x10); + if (wc->ise1) + __t1_set_reg(wc, 0x21, 0x5f); + else + __t1_set_reg(wc, 0x35, 0x10); zt_alarm_notify(&wc->span); } } @@ -808,9 +1076,13 @@ static void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs) return; if (!wc->intcount) { - printk("Got interrupt: 0x%04x\n", ints); + if (debug) printk("Got interrupt: 0x%04x\n", ints); } wc->intcount++; + + if (wc->clocktimeout && !--wc->clocktimeout) + control_set_reg(wc, WC_CLOCK, 0x00 | wc->sync | wc->ise1); + if (ints & 0x0f) { t1xxp_receiveprep(wc, ints); t1xxp_transmitprep(wc, ints); @@ -873,28 +1145,33 @@ static int t1xxp_hardware_init(struct t1xxp *wc) /* Start at writedma */ outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ /* First frame */ - outl(wc->writedma + ZT_CHUNKSIZE * 32, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ + outl(wc->writedma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ /* Second frame */ outl(wc->writedma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE); /* End */ outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ /* First frame */ - outl(wc->readdma + ZT_CHUNKSIZE * 32, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ + outl(wc->readdma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ /* Second frame */ outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */ - printk("Setting up DMA (write/read = %08x/%08x)\n", wc->writedma, wc->readdma); + if (debug) printk("Setting up DMA (write/read = %08x/%08x)\n", wc->writedma, wc->readdma); /* Check out the controller */ - printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION)); + if (debug) printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION)); control_set_reg(wc, WC_LEDTEST, 0x00); - control_set_reg(wc, WC_CLOCK, 0x00); + control_set_reg(wc, WC_CLOCK, 0x02); + wc->clocktimeout = 100; + /* Sanity check also determines e1 or t1 */ if (t1xxp_framer_sanity_check(wc)) return -1; - + if (wc->ise1) + wc->chanmap = chanmap_e1; + else + wc->chanmap = chanmap_t1; /* Reset the T1 and report */ t1xxp_framer_hard_reset(wc); start_alarm(wc); @@ -917,12 +1194,13 @@ static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_devic wc->ioaddr = pci_resource_start(pdev, 0); wc->dev = pdev; wc->variety = (char *)(ent->driver_data); + wc->offset = 28; /* And you thought 42 was the answer */ wc->writechunk = /* 32 channels, Double-buffer, Read/Write */ (unsigned char *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); if (!wc->writechunk) { - printk("wcmodem: Unable to allocate DMA-able memory\n"); + printk("wct1xxp: Unable to allocate DMA-able memory\n"); return -ENOMEM; } @@ -987,7 +1265,7 @@ static void __devexit t1xxp_remove_one(struct pci_dev *pdev) t1xxp_stop_stuff(wc); /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 24 * 4, (void *)wc->writechunk, wc->writedma); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); free_irq(pdev->irq, wc); /* Reset PCI chip and registers */ @@ -1002,7 +1280,7 @@ static void __devexit t1xxp_remove_one(struct pci_dev *pdev) } static struct pci_device_id t1xxp_pci_tbl[] __devinitdata = { - { 0xe159, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) "LSS Wildcard T100P T1/PRI Board" }, + { 0xe159, 0x0001, 0x6159, PCI_ANY_ID, 0, 0, (unsigned long) "LSS Wildcard T100P T1/PRI Board" }, }; static struct pci_driver t1xxp_driver = { |