📄 wct1xxp.c
字号:
__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; unsigned 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 (%s)\n", chips[chipid], res & 0xf, wc->ise1 ? "E1" : "T1"); return 0;}static int t1xxp_framer_hard_reset(struct t1xxp *wc){ int x; unsigned long flags; spin_lock_irqsave(&wc->lock, flags); /* Initialize all registers to 0 */ for (x=0x0;x<192;x++) __t1_set_reg(wc, x, 0); 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); /* Tx elastic store enabled, 2.048 Mhz (in theory) */ __t1_set_reg(wc, 0x1b, 0x82); } else { /* Full-on sync required for T1 */ __t1_set_reg(wc, 0x2b, 0x08); /* RSYNC is an input */ __t1_set_reg(wc, 0x2c, 0x08); /* Enable tx RBS bits */ __t1_set_reg(wc, 0x35, 0x10); /* 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;}static int t1xxp_rbsbits(struct zt_chan *chan, int bits){ struct t1xxp *wc = chan->pvt; unsigned long flags; int b,o; unsigned char mask; /* Byte offset */ spin_lock_irqsave(&wc->lock, flags); if (wc->ise1) { if (chan->chanpos < 16) { mask = ((bits << 4) | wc->chans[chan->chanpos - 1 + 16].txsig); __t1_set_reg(wc, 0x40 + chan->chanpos, mask); } else if (chan->chanpos > 16) { mask = (bits | (wc->chans[chan->chanpos - 1 - 16].txsig << 4)); __t1_set_reg(wc, 0x40 + chan->chanpos - 16, mask); } wc->chans[chan->chanpos - 1].txsig = bits; } else { b = (chan->chanpos - 1) / 8; o = (chan->chanpos - 1) % 8; 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; } /* 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;}static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data){ switch(cmd) { default: return -ENOTTY; }}static int t1xxp_startup(struct zt_span *span){ struct t1xxp *wc = span->pvt; 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 */ 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) { /* Only if we're not already going */ t1xxp_enable_interrupts(wc); t1xxp_start_dma(wc); span->flags |= ZT_FLAG_RUNNING; } return 0;}static int t1xxp_shutdown(struct zt_span *span){ struct t1xxp *wc = span->pvt; unsigned long flags; spin_lock_irqsave(&wc->lock, flags); __t1xxp_stop_dma(wc); __t1xxp_disable_interrupts(wc); span->flags &= ~ZT_FLAG_RUNNING; spin_unlock_irqrestore(&wc->lock, flags); t1xxp_framer_hard_reset(wc); return 0;}static int t1xxp_maint(struct zt_span *span, int cmd){ struct t1xxp *wc = span->pvt; int res = 0; unsigned 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){ struct t1xxp *wc = chan->pvt; unsigned long flags; int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; spin_lock_irqsave(&wc->lock, flags); if (alreadyrunning && !wc->ise1) __t1xxp_set_clear(wc); spin_unlock_irqrestore(&wc->lock, flags); return 0;}static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc){ struct t1xxp *wc = span->pvt; span->lineconfig = lc->lineconfig; span->txlevel = lc->lbo; span->rxlevel = 0; /* Do we want to SYNC on receive or not */ wc->sync = lc->sync; /* If already running, apply changes immediately */ if (span->flags & ZT_FLAG_RUNNING) return t1xxp_startup(span); return 0;}static int t1xxp_software_init(struct t1xxp *wc){ int x; /* Find position */ for (x=0;x<WC_MAX_CARDS;x++) { if (!cards[x]) { cards[x] = wc; break; } } if (x >= WC_MAX_CARDS) return -1; wc->num = x; sprintf(wc->span.name, "WCT1/%d", wc->num); sprintf(wc->span.desc, "%s Card %d", wc->variety, wc->num); wc->span.spanconfig = t1xxp_spanconfig; wc->span.chanconfig = t1xxp_chanconfig; wc->span.startup = t1xxp_startup; wc->span.shutdown = t1xxp_shutdown; wc->span.rbsbits = t1xxp_rbsbits; wc->span.maint = t1xxp_maint; wc->span.open = t1xxp_open; wc->span.close = t1xxp_close; 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; wc->span.ioctl = t1xxp_ioctl; wc->span.pvt = wc; if (wc->ise1) wc->span.deflaw = ZT_LAW_ALAW; else wc->span.deflaw = ZT_LAW_MULAW; init_waitqueue_head(&wc->span.maintq); 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_EM_E1 | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; wc->chans[x].pvt = wc; wc->chans[x].chanpos = x + 1; } if (zt_register(&wc->span, 0)) { printk("Unable to register span with zaptel\n"); return -1; } return 0;}static inline void __handle_leds(struct t1xxp *wc){ int oldreg; wc->blinktimer++; if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { /* Red/Blue alarm */#ifdef FANCY_ALARM if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); } if (wc->blinktimer == 0xf) { wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); wc->blinktimer = -1; wc->alarmpos++; if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) wc->alarmpos = 0; }#else if (wc->blinktimer == 160) { wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); } else if (wc->blinktimer == 480) { wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); wc->blinktimer = 0; }#endif } else if (wc->span.alarms & ZT_ALARM_YELLOW) { /* Yellow Alarm */ if (!(wc->blinktimer % 2)) wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; else wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); } 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 wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); if (oldreg != wc->ledtestreg) __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); }}static void t1xxp_transmitprep(struct t1xxp *wc, int ints){ volatile unsigned char *txbuf; int x,y; int pos; if (ints & 0x04 /* 0x01 */) { /* We just finished sending the first buffer, start filling it now */ txbuf = wc->writechunk; } else { /* Just finished sending second buffer, fill it now */ txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE; } zt_transmit(&wc->span); for (x=0;x<wc->offset;x++) txbuf[x] = wc->tempo[x]; for (y=0;y<ZT_CHUNKSIZE;y++) { for (x=0;x<wc->span.channels;x++) { pos = y * 32 + wc->chanmap[x] + wc->offset; /* Put channel number as outgoing data */ if (pos < 32 * ZT_CHUNKSIZE) txbuf[pos] = wc->chans[x].writechunk[y]; else wc->tempo[pos - 32 * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y]; } }}static void t1xxp_receiveprep(struct t1xxp *wc, int ints){ volatile unsigned char *rxbuf; volatile unsigned int *canary; int x; int y; unsigned int oldcan; if (ints & 0x04) { /* Just received first buffer */ rxbuf = wc->readchunk; canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); } else { rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32; canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 32 - 4); } oldcan = *canary; if (((oldcan & 0xffff0000) >> 16) != CANARY) { /* Check top part */ if (debug) printk("Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16); wc->span.irqmisses++; } else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) { if (debug) printk("Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff); wc->span.irqmisses++; } for (y=0;y<ZT_CHUNKSIZE;y++) { 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 + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; } if (!wc->ise1) { for (x=3;x<32;x+=4) { if (rxbuf[32 * y + ((x + WC_OFFSET) & 0x1f)] == 0x7f) { if (wc->offset != (x-3)) { /* Resync */ control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); wc->clocktimeout = 100;#if 1 if (debug) printk("T1: Lost our place, resyncing\n");#endif } } } } else { if (!wc->clocktimeout && !wc->span.alarms) { if ((rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)] & 0x7f) != 0x1b) { if (wc->miss) { if (debug) printk("Double miss (%d, %d)...\n", wc->misslast, rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]); control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); wc->clocktimeout = 100; } else { wc->miss = 1; wc->misslast = rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]; } } else { wc->miss = 0; } } else { wc->miss = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -