summaryrefslogtreecommitdiff
path: root/wct1xxp.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-09-03 02:32:50 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-09-03 02:32:50 +0000
commitc40b2fa76bb9b59efd40c11dc328440242eee3fe (patch)
treebacb3878cfacaf3520e18405efff40113e176566 /wct1xxp.c
parent1c9885532e2572eeb5a95fa240c501d5fb91459a (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-xwct1xxp.c486
1 files changed, 382 insertions, 104 deletions
diff --git a/wct1xxp.c b/wct1xxp.c
index 45c72d9..2d15692 100755
--- a/wct1xxp.c
+++ b/wct1xxp.c
@@ -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 = {