📄 base.c
字号:
}
regval = regval >> 1;
}
if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN))
continue;
/* Start of DTMF off detection process */
regbyte = t4_vpm_in(wc, x, 0xbc);
t4_vpm_out(wc, x, 0xbc, regbyte); /* Write 1 to clear */
regval = regbyte << 8;
regbyte = t4_vpm_in(wc, x, 0xbd);
t4_vpm_out(wc, x, 0xbd, regbyte);
regval |= regbyte;
for(i = 0; (i < MAX_DTMF_DET) && regval; i++) {
if(regval & 0x0001) {
int channel = (i << 1) + (x >> 2);
int base = channel - 1;
if (!wc->t1e1)
base -= 4;
clear_bit(base, &ts->dtmfactive);
if (ts->dtmfdigit[base]) {
if (test_bit(base, &ts->dtmfmask))
zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
}
digit = ts->dtmfdigit[base];
ts->dtmfdigit[base] = 0;
if (debug)
printk("Digit Gone: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x);
}
regval = regval >> 1;
}
}
}
#endif
static void hdlc_stop(struct t4 *wc, unsigned int span)
{
struct t4_span *t = wc->tspans[span];
unsigned char imr0, imr1, mode;
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);
t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00);
}
imr0 = t4_framer_in(wc, span, FRMR_IMR0);
imr1 = t4_framer_in(wc, span, FRMR_IMR1);
/* Disable HDLC interrupts */
imr0 |= HDLC_IMR0_MASK;
t4_framer_out(wc, span, FRMR_IMR0, imr0);
imr1 |= HDLC_IMR1_MASK;
t4_framer_out(wc, span, FRMR_IMR1, imr1);
mode = t4_framer_in(wc, span, FRMR_MODE);
mode &= ~FRMR_MODE_HRAC;
t4_framer_out(wc, span, FRMR_MODE, mode);
t->sigactive = 0;
}
static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd)
{
__t4_framer_out(wc, span, FRMR_CMDR, cmd);
}
static inline void t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd)
{
int sis;
int loops = 0;
/* XXX could be time consuming XXX */
for (;;) {
sis = t4_framer_in(wc, span, FRMR_SIS);
if (!(sis & 0x04))
break;
if (!loops++ && (debug & DEBUG_FRAMER)) {
printk("!!!SIS Waiting before cmd %02x\n", cmd);
}
}
if (loops && (debug & DEBUG_FRAMER))
printk("!!!SIS waited %d loops\n", loops);
t4_framer_out(wc, span, FRMR_CMDR, cmd);
}
static int hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan, unsigned char mode)
{
struct t4_span *t = wc->tspans[span];
unsigned char imr0, imr1;
int offset = chan->chanpos;
unsigned long flags;
if (debug & DEBUG_FRAMER) printk("Starting HDLC controller for channel %d span %d\n", offset, span+1);
if (mode != FRMR_MODE_NO_ADDR_CMP)
return -1;
mode |= FRMR_MODE_HRAC;
/* Make sure we're in the right mode */
t4_framer_out(wc, span, FRMR_MODE, mode);
t4_framer_out(wc, span, FRMR_TSEO, 0x00);
t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode);
/* Set the interframe gaps, etc */
t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS);
t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC);
/* Set up the time slot that we want to tx/rx on */
t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8)));
imr0 = t4_framer_in(wc, span, FRMR_IMR0);
imr1 = t4_framer_in(wc, span, FRMR_IMR1);
/* Enable our interrupts again */
imr0 &= ~HDLC_IMR0_MASK;
t4_framer_out(wc, span, FRMR_IMR0, imr0);
imr1 &= ~HDLC_IMR1_MASK;
t4_framer_out(wc, span, FRMR_IMR1, imr1);
/* Reset the signaling controller */
t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES);
spin_lock_irqsave(&wc->reglock, flags);
t->sigchan = chan;
spin_unlock_irqrestore(&wc->reglock, flags);
t->sigactive = 0;
return 0;
}
static void __set_clear(struct t4 *wc, int span)
{
int i,j;
int oldnotclear;
unsigned short val=0;
struct t4_span *ts = wc->tspans[span];
oldnotclear = ts->notclear;
if ((ts->spantype == TYPE_T1) || (ts->spantype == TYPE_J1)) {
for (i=0;i<24;i++) {
j = (i/8);
if (ts->span.chans[i].flags & ZT_FLAG_CLEAR) {
val |= 1 << (7 - (i % 8));
ts->notclear &= ~(1 << i);
} else
ts->notclear |= (1 << i);
if ((i % 8)==7) {
if (debug)
printk("Putting %d in register %02x on span %d\n",
val, 0x2f + j, span + 1);
__t4_framer_out(wc, span, 0x2f + j, val);
val = 0;
}
}
} else {
for (i=0;i<31;i++) {
if (ts->span.chans[i].flags & ZT_FLAG_CLEAR)
ts->notclear &= ~(1 << i);
else
ts->notclear |= (1 << i);
}
}
if (ts->notclear != oldnotclear) {
unsigned char reg;
reg = __t4_framer_in(wc, span, FRMR_IMR0);
if (ts->notclear)
reg &= ~0x08;
else
reg |= 0x08;
__t4_framer_out(wc, span, FRMR_IMR0, reg);
}
}
#if 0
static void set_clear(struct t4 *wc, int span)
{
unsigned long flags;
spin_lock_irqsave(&wc->reglock, flags);
__set_clear(wc, span);
spin_unlock_irqrestore(&wc->reglock, flags);
}
#endif
static int t4_dacs(struct zt_chan *dst, struct zt_chan *src)
{
struct t4 *wc;
struct t4_span *ts;
wc = dst->pvt;
ts = wc->tspans[dst->span->offset];
if (src && (src->pvt != dst->pvt)) {
if (ts->spanflags & FLAG_2NDGEN)
t4_tsi_unassign(wc, dst->span->offset, dst->chanpos);
wc = src->pvt;
if (ts->spanflags & FLAG_2NDGEN)
t4_tsi_unassign(wc, src->span->offset, src->chanpos);
if (debug)
printk("Unassigning %d/%d by default and...\n", src->span->offset, src->chanpos);
if (debug)
printk("Unassigning %d/%d by default\n", dst->span->offset, dst->chanpos);
return -1;
}
if (src) {
t4_tsi_assign(wc, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
if (debug)
printk("Assigning channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
} else {
t4_tsi_unassign(wc, dst->span->offset, dst->chanpos);
if (debug)
printk("Unassigning channel %d/%d!\n", dst->span->offset, dst->chanpos);
}
return 0;
}
#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;
switch(vpmspans) {
case 4:
unit = span;
unit += (channel & 1) << 2;
break;
case 2:
unit = span;
unit += (channel & 0x3) << 1;
break;
case 1:
unit = span;
unit += (channel & 0x7);
}
return unit;
}
static int t4_echocan(struct zt_chan *chan, int eclen)
{
struct t4 *wc = chan->pvt;
int channel;
int unit;
if (!wc->vpm)
return -ENODEV;
if (chan->span->offset >= vpmspans)
return -ENODEV;
if (wc->t1e1)
channel = chan->chanpos;
else
channel = chan->chanpos + 4;
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
static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
{
struct t4_regs regs;
int x;
struct t4 *wc = chan->pvt;
#ifdef VPM_SUPPORT
int j;
int channel;
struct t4_span *ts = wc->tspans[chan->span->offset];
#endif
#ifdef VPM_SUPPORT
if (dtmfthreshold == 0)
dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
if (lastdtmfthreshold != dtmfthreshold) {
lastdtmfthreshold = dtmfthreshold;
t4_vpm_set_dtmf_threshold(wc, dtmfthreshold);
}
#endif
switch(cmd) {
case WCT4_GET_REGS:
for (x=0;x<NUM_PCI;x++)
regs.pci[x] = t4_pci_in(wc, x);
for (x=0;x<NUM_REGS;x++)
regs.regs[x] = t4_framer_in(wc, chan->span->offset, x);
if (copy_to_user((struct t4_regs *)data, ®s, sizeof(regs)))
return -EFAULT;
break;
#ifdef VPM_SUPPORT
case ZT_TONEDETECT:
if (get_user(j, (int *)data))
return -EFAULT;
if (!wc->vpm)
return -ENOSYS;
if (j && (vpmdtmfsupport == 0))
return -ENOSYS;
if (j & ZT_TONEDETECT_ON)
set_bit(chan->chanpos - 1, &ts->dtmfmask);
else
clear_bit(chan->chanpos - 1, &ts->dtmfmask);
if (j & ZT_TONEDETECT_MUTE)
set_bit(chan->chanpos - 1, &ts->dtmfmutemask);
else
clear_bit(chan->chanpos - 1, &ts->dtmfmutemask);
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:
return -ENOTTY;
}
return 0;
}
static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts)
{
int res, i, size = 32;
unsigned char buf[32];
res = zt_hdlc_getbuf(ts->sigchan, buf, &size);
if (debug & DEBUG_FRAMER) printk("Got buffer sized %d and res %d for %d\n", size, res, span);
if (size > 0) {
ts->sigactive = 1;
if (debug & DEBUG_FRAMER) {
printk("TX(");
for (i = 0; i < size; i++)
printk((i ? " %02x" : "%02x"), buf[i]);
printk(")\n");
}
for (i = 0; i < size; i++)
t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]);
if (res) /* End of message */ {
if (debug & DEBUG_FRAMER) printk("transmiting XHF|XME\n");
t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME);
#if 0
ts->sigactive = (__t4_framer_in(wc, span, FRMR_SIS) & FRMR_SIS_XFW) ? 0 : 1;
#endif
++ts->frames_out;
if ((debug & DEBUG_FRAMER) && !(ts->frames_out & 0x0f))
printk("Transmitted %d frames on span %d\n", ts->frames_out, span);
} else { /* Still more to transmit */
if (debug & DEBUG_FRAMER) printk("transmiting XHF\n");
t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF);
}
}
else if (res < 0)
ts->sigactive = 0;
}
static void t4_hdlc_hard_xmit(struct zt_chan *chan)
{
struct t4 *wc = chan->pvt;
int span = chan->span->offset;
struct t4_span *ts = wc->tspans[span];
unsigned long flags;
spin_lock_irqsave(&wc->reglock, flags);
if (!ts->sigchan) {
printk("t4_hdlc_hard_xmit: Invalid (NULL) signalling channel\n");
spin_unlock_irqrestore(&wc->reglock, flags);
return;
}
spin_unlock_irqrestore(&wc->reglock, flags);
if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit on channel %s (sigchan %s), sigactive=%d\n", chan->name, ts->sigchan->name, ts->sigactive);
if ((ts->sigchan == chan) && !ts->sigactive)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -