[Asterisk-cvs] zaptel wct4xxp.c,1.13,1.14
markster at lists.digium.com
markster at lists.digium.com
Thu Nov 20 18:40:41 CST 2003
Update of /usr/cvsroot/zaptel
In directory mongoose.digium.com:/tmp/cvs-serv12541
Modified Files:
wct4xxp.c
Log Message:
Detect E1 alignment errors and fix alignment
Index: wct4xxp.c
===================================================================
RCS file: /usr/cvsroot/zaptel/wct4xxp.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- wct4xxp.c 13 Nov 2003 17:55:25 -0000 1.13
+++ wct4xxp.c 21 Nov 2003 01:07:00 -0000 1.14
@@ -100,7 +100,9 @@
int syncpos[4]; /* span-relative sync sources */
int master; /* Are we master */
int ledreg; /* LED Register */
+ int e1check[4]; /* E1 check */
unsigned int dmactrl;
+ int e1recover; /* E1 recovery timer */
dma_addr_t readdma;
dma_addr_t writedma;
unsigned long memaddr; /* Base address of card */
@@ -138,6 +140,7 @@
static int t4_shutdown(struct zt_span *span);
static int t4_rbsbits(struct zt_chan *chan, int bits);
static int t4_maint(struct zt_span *span, int cmd);
+static int t4_reset_dma(struct t4 *wc);
static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data);
#define WC_RDADDR 0
@@ -905,6 +908,27 @@
return 0;
}
+static inline void e1_check(struct t4 *wc, int span, int val)
+{
+ if ((wc->spans[span].channels > 24) &&
+ (wc->spans[span].flags & ZT_FLAG_RUNNING) &&
+ !(wc->spans[span].alarms) &&
+ (!wc->e1recover)) {
+ if (val != 0x1b) {
+ wc->e1check[span]++;
+ } else
+ wc->e1check[span] = 0;
+ if (wc->e1check[span] > 100) {
+ /* Wait 1000 ms */
+ wc->e1recover = 1000 * 8;
+ memset(wc->e1check, 0, sizeof(wc->e1check));
+ if (debug)
+ printk("Detected loss of E1 alignment on span %d!\n", span);
+ t4_reset_dma(wc);
+ }
+ }
+}
+
static void t4_receiveprep(struct t4 *wc, int irq)
{
volatile unsigned int *readchunk;
@@ -913,12 +937,12 @@
unsigned int tmp;
if (irq & 1) {
/* First part */
- readchunk = wc->readchunk + 1;
+ readchunk = wc->readchunk;
if (!wc->last0)
dbl = 1;
wc->last0 = 0;
} else {
- readchunk = wc->readchunk + ZT_CHUNKSIZE * 32 + 1;
+ readchunk = wc->readchunk + ZT_CHUNKSIZE * 32;
if (wc->last0)
dbl = 1;
wc->last0 = 1;
@@ -930,19 +954,25 @@
printk("TE410P: Double/missed interrupt detected\n");
}
for (x=0;x<ZT_CHUNKSIZE;x++) {
- /* Once per chunk */
for (z=0;z<24;z++) {
/* All T1/E1 channels */
- tmp = readchunk[z];
+ tmp = readchunk[z+1];
wc->spans[3].chans[z].readchunk[x] = tmp & 0xff;
wc->spans[2].chans[z].readchunk[x] = (tmp & 0xff00) >> 8;
wc->spans[1].chans[z].readchunk[x] = (tmp & 0xff0000) >> 16;
wc->spans[0].chans[z].readchunk[x] = tmp >> 24;
}
if (wc->t1e1) {
+ if (wc->e1recover > 0)
+ wc->e1recover--;
+ tmp = readchunk[0];
+ e1_check(wc, 3, (tmp & 0x7f));
+ e1_check(wc, 2, (tmp & 0x7f00) >> 8);
+ e1_check(wc, 1, (tmp & 0x7f0000) >> 16);
+ e1_check(wc, 0, (tmp & 0x7f000000) >> 24);
for (z=24;z<31;z++) {
/* Only E1 channels now */
- tmp = readchunk[z];
+ tmp = readchunk[z+1];
if (wc->spans[3].channels > 24)
wc->spans[3].chans[z].readchunk[x] = tmp & 0xff;
if (wc->spans[2].channels > 24)
@@ -1353,6 +1383,25 @@
spin_unlock_irqrestore(&wc->reglock, flags);
+}
+
+static int t4_reset_dma(struct t4 *wc)
+{
+ /* Turn off DMA and such */
+ wc->dmactrl = 0x0;
+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
+ t4_pci_out(wc, WC_COUNT, 0);
+ t4_pci_out(wc, WC_RDADDR, 0);
+ t4_pci_out(wc, WC_WRADDR, 0);
+ t4_pci_out(wc, WC_INTR, 0);
+ /* Turn it all back on */
+ t4_pci_out(wc, WC_RDADDR, wc->readdma);
+ t4_pci_out(wc, WC_WRADDR, wc->writedma);
+ t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2));
+ t4_pci_out(wc, WC_INTR, 0);
+ wc->dmactrl = 0xc0000003 | (1 << 29);
+ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
+ return 0;
}
static int t4_hardware_init(struct t4 *wc)
More information about the svn-commits
mailing list