⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 base.c

📁 PCI base driver source code
💻 C
📖 第 1 页 / 共 5 页
字号:
			}
			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, &regs, 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 + -