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

📄 base.c

📁 PCI base driver source code
💻 C
📖 第 1 页 / 共 5 页
字号:
	return res;
}

static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
{
	unsigned int tmp;
	writel(value, &wc->membase[addr]);
	if (pedanticpci) {
		/* Even though we do not support fast back-to-back
		 * transactions, some host bridges appear to generate them.
		 * This delay prevents this. 
		 */
		tmp = __t4_pci_in(wc, WC_VERSION);
		if ((tmp & 0xffff0000) != 0xc01a0000)
			printk("TE4XXP: Version Synchronization Error!\n");
	}
#if 0
	tmp = __t4_pci_in(wc, addr);
	if ((value != tmp) && (addr != WC_LEDS) && (addr != WC_LDATA) &&
		(addr != WC_GPIO) && (addr != WC_INTR))
		printk("Tried to load %08x into %08x, but got %08x instead\n", value, addr, tmp);
#endif		
}

static inline void __t4_gpio_set(struct t4 *wc, unsigned bits, unsigned int val)
{
	unsigned int newgpio;
	newgpio = wc->gpio & (~bits);
	newgpio |= val;
	if (newgpio != wc->gpio) {
		wc->gpio = newgpio;
		__t4_pci_out(wc, WC_GPIO, wc->gpio);
	}	
}

static inline void __t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val)
{
	unsigned int newgpioctl;
	newgpioctl = wc->gpioctl & (~bits);
	newgpioctl |= val;
	if (newgpioctl != wc->gpioctl) {
		wc->gpioctl = newgpioctl;
		__t4_pci_out(wc, WC_GPIOCTL, wc->gpioctl);
	}
}

static inline void t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val)
{
	unsigned long flags;
	spin_lock_irqsave(&wc->reglock, flags);
	__t4_gpio_setdir(wc, bits, val);
	spin_unlock_irqrestore(&wc->reglock, flags);
}

static inline void t4_gpio_set(struct t4 *wc, unsigned int bits, unsigned int val)
{
	unsigned long flags;
	spin_lock_irqsave(&wc->reglock, flags);
	__t4_gpio_set(wc, bits, val);
	spin_unlock_irqrestore(&wc->reglock, flags);
}

static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
{
	unsigned long flags;
	spin_lock_irqsave(&wc->reglock, flags);
	__t4_pci_out(wc, addr, value);
	spin_unlock_irqrestore(&wc->reglock, flags);
}

static inline void __t4_set_led(struct t4 *wc, int span, int color)
{
	int oldreg = wc->ledreg;
	wc->ledreg &= ~(0x3 << (span << 1));
	wc->ledreg |= (color << (span << 1));
	if (oldreg != wc->ledreg)
		__t4_pci_out(wc, WC_LEDS, wc->ledreg);
}

static inline void t4_activate(struct t4 *wc)
{
	wc->ledreg |= WC_ACTIVATE;
	t4_pci_out(wc, WC_LEDS, wc->ledreg);
}

static inline unsigned int t4_pci_in(struct t4 *wc, const unsigned int addr)
{
	unsigned int ret;
	unsigned long flags;t
	
	spin_lock_irqsave(&wc->reglock, flags);
	ret = __t4_pci_in(wc, addr);
	spin_unlock_irqrestore(&wc->reglock, flags);
	return ret;
}

static inline unsigned int __t4_framer_in(struct t4 *wc, int unit, const unsigned int addr)
{
	unsigned int ret;
	unit &= 0x3;
	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LREAD);
	if (pedanticpci) {
		__t4_pci_out(wc, WC_VERSION, 0);
	}
	ret = __t4_pci_in(wc, WC_LDATA);
 	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
	return ret & 0xff;
}

static inline unsigned int t4_framer_in(struct t4 *wc, int unit, const unsigned int addr)
{
	unsigned long flags;
	unsigned int ret;
	spin_lock_irqsave(&wc->reglock, flags);
	ret = __t4_framer_in(wc, unit, addr);
	spin_unlock_irqrestore(&wc->reglock, flags);
	return ret;

}

static inline void __t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value)
{
	unit &= 0x3;
	if (unlikely(debug & DEBUG_REGS))
		printk("Writing %02x to address %02x of unit %d\n", value, addr, unit);
	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
	__t4_pci_out(wc, WC_LDATA, value);
	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LWRITE);
	__t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));	
	if (unlikely(debug & DEBUG_REGS)) printk("Write complete\n");
#if 0
	if ((addr != FRMR_TXFIFO) && (addr != FRMR_CMDR) && (addr != 0xbc))
	{ unsigned int tmp;
	tmp = __t4_framer_in(wc, unit, addr);
	if (tmp != value) {
		printk("Expected %d from unit %d register %d but got %d instead\n", value, unit, addr, tmp);
	} }
#endif	
}

static inline void t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value)
{
	unsigned long flags;
	spin_lock_irqsave(&wc->reglock, flags);
	__t4_framer_out(wc, unit, addr, value);
	spin_unlock_irqrestore(&wc->reglock, flags);
}

#ifdef VPM_SUPPORT

static inline void wait_a_little(void)
{
	unsigned long newjiffies=jiffies+2;
	while(jiffies < newjiffies);
}

static inline unsigned int __t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr)
{
	unsigned int ret;
	unit &= 0x7;
	__t4_pci_out(wc, WC_LADDR, (addr & 0x1ff) | ( unit << 12));
	__t4_pci_out(wc, WC_LADDR, (addr & 0x1ff) | ( unit << 12) | (1 << 11) | WC_LREAD);
	ret = __t4_pci_in(wc, WC_LDATA);
	__t4_pci_out(wc, WC_LADDR, 0);
	return ret & 0xff;
}

static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
{
	int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT;
	if (!octopt) 
		__t4_gpio_set(wc, 0xff, (addr >> 8));
	__t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff));
	if (!octopt)
		__t4_pci_out(wc, WC_LADDR, (WC_LWRITE));
	__t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE));
	if (!octopt)
		__t4_gpio_set(wc, 0xff, (value >> 8));
	__t4_pci_out(wc, WC_LDATA, (value & 0xffff));
	__t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE | WC_LCS));
	__t4_pci_out(wc, WC_LADDR, (0));
}

static inline unsigned int __t4_raw_oct_in(struct t4 *wc, const unsigned int addr)
{
	unsigned int ret;
	int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT;
	if (!octopt)
		__t4_gpio_set(wc, 0xff, (addr >> 8));
	__t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff));
	if (!octopt)
		__t4_pci_out(wc, WC_LADDR, (WC_LWRITE));
	__t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE));
#ifdef PEDANTIC_OCTASIC_CHECKING 
	__t4_pci_out(wc, WC_LADDR, (WC_LALE));
#endif
	if (!octopt) {
		__t4_gpio_setdir(wc, 0xff, 0x00);
		__t4_gpio_set(wc, 0xff, 0x00);
	}
	__t4_pci_out(wc, WC_LADDR, (WC_LREAD | WC_LALE | WC_LCS));
	if (octopt) {
		ret = __t4_pci_in(wc, WC_LDATA) & 0xffff;
	} else {
		ret = __t4_pci_in(wc, WC_LDATA) & 0xff;
		ret |= (__t4_pci_in(wc, WC_GPIO) & 0xff) << 8;
	}
	__t4_pci_out(wc, WC_LADDR, (0));
	if (!octopt)
		__t4_gpio_setdir(wc, 0xff, 0xff);
	return ret & 0xffff;
}

static inline unsigned int __t4_oct_in(struct t4 *wc, unsigned int addr)
{
#ifdef PEDANTIC_OCTASIC_CHECKING
	int count = 1000;
#endif
	__t4_raw_oct_out(wc, 0x0008, (addr >> 20));
	__t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1));
	__t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1));
#ifdef PEDANTIC_OCTASIC_CHECKING
	while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count);
	if (count != 1000)
		printk("Yah, read can be slow...\n");
	if (!count)
		printk("Read timed out!\n");
#endif
	return __t4_raw_oct_in(wc, 0x0004);
}

static inline unsigned int t4_oct_in(struct t4 *wc, const unsigned int addr)
{
	unsigned long flags;
	unsigned int ret;

	spin_lock_irqsave(&wc->reglock, flags);
	ret = __t4_oct_in(wc, addr);
	spin_unlock_irqrestore(&wc->reglock, flags);
	return ret;
}

static inline unsigned int t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr)
{
	unsigned long flags;
	unsigned int ret;
	spin_lock_irqsave(&wc->reglock, flags);
	ret = __t4_vpm_in(wc, unit, addr);
	spin_unlock_irqrestore(&wc->reglock, flags);
	return ret;
}

static inline void __t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value)
{
	unit &= 0x7;
	if (debug & DEBUG_REGS)
		printk("Writing %02x to address %02x of ec unit %d\n", value, addr, unit);
	__t4_pci_out(wc, WC_LADDR, (addr & 0xff));
	__t4_pci_out(wc, WC_LDATA, value);
	__t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11));
	__t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11) | WC_LWRITE);
	__t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11));
	__t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff));	
	__t4_pci_out(wc, WC_LADDR, 0);
	if (debug & DEBUG_REGS) printk("Write complete\n");

      
#if 0
	{ unsigned int tmp;
	tmp = t4_vpm_in(wc, unit, addr);
	if (tmp != value) {
		printk("Expected %d from unit %d echo register %d but got %d instead\n", value, unit, addr, tmp);
	} }
#endif
}

static inline void __t4_oct_out(struct t4 *wc, unsigned int addr, unsigned int value)
{
#ifdef PEDANTIC_OCTASIC_CHECKING
	int count = 1000;
#endif
	__t4_raw_oct_out(wc, 0x0008, (addr >> 20));
	__t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1));
	__t4_raw_oct_out(wc, 0x0004, value);
	__t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1);
#ifdef PEDANTIC_OCTASIC_CHECKING
	while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count);
	if (count != 1000)
		printk("Yah, write can be slow\n");
	if (!count)
		printk("Write timed out!\n");
#endif
}

static inline void t4_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
{
	unsigned long flags;

	spin_lock_irqsave(&wc->reglock, flags);
	__t4_oct_out(wc, addr, value);
	spin_unlock_irqrestore(&wc->reglock, flags);
}

static inline void t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value)
{
	unsigned long flags;
	spin_lock_irqsave(&wc->reglock, flags);
	__t4_vpm_out(wc, unit, addr, value);
	spin_unlock_irqrestore(&wc->reglock, flags);
}

static const char vpm_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', '*', '#'};

static void t4_check_vpm450(struct t4 *wc)
{
	int channel, tone, start, span;

	if (vpm450m_checkirq(wc->vpm450m)) {
		while(vpm450m_getdtmf(wc->vpm450m, &channel, &tone, &start)) {
			span = channel & 0x3;
			channel >>= 2;
			if (!wc->t1e1)
				channel -= 5;
			else
				channel -= 1;
			if (unlikely(debug))
				printk("Got tone %s of '%c' on channel %d of span %d\n",
					(start ? "START" : "STOP"), tone, channel, span + 1);
			if (test_bit(channel, &wc->tspans[span]->dtmfmask) && (tone != 'u')) {
				if (start) {
					/* The octasic is supposed to mute us, but...  Yah, you
					   guessed it.  */
					if (test_bit(channel, &wc->tspans[span]->dtmfmutemask)) {
						unsigned long flags;
						struct zt_chan *chan = &wc->tspans[span]->span.chans[channel];
						int y;
						spin_lock_irqsave(&chan->lock, flags);
						for (y=0;y<chan->numbufs;y++) {
							if ((chan->inreadbuf > -1) && (chan->readidx[y]))
								memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]);
						}
						spin_unlock_irqrestore(&chan->lock, flags);
					}
					set_bit(channel, &wc->tspans[span]->dtmfactive);
					zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFDOWN | tone));
				} else {
					clear_bit(channel, &wc->tspans[span]->dtmfactive);
					zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFUP | tone));
				}
			}
		}
	}
}

static void t4_check_vpm400(struct t4 *wc, unsigned int newio)
{
	unsigned int digit, regval = 0;
	unsigned int regbyte;
	int x, i;
	short energy=0;
	static unsigned int lastio = 0;
	struct t4_span *ts;

	if (debug && (newio != lastio)) 
		printk("Last was %08x, new is %08x\n", lastio, newio);

	lastio = newio;
 
	for(x = 0; x < 8; x++) {
		if (newio & (1 << (7 - x)))
			continue;
		ts = wc->tspans[x%4];
		/* Start of DTMF detection process */	
		regbyte = t4_vpm_in(wc, x, 0xb8);
		t4_vpm_out(wc, x, 0xb8, regbyte); /* Write 1 to clear */
		regval = regbyte << 8;
		regbyte = t4_vpm_in(wc, x, 0xb9);
		t4_vpm_out(wc, x, 0xb9, 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;
				regbyte = t4_vpm_in(wc, x, 0xa8 + i);
				digit = vpm_digits[regbyte];
				if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) {
					energy = t4_vpm_in(wc, x, 0x58 + channel);
					energy = ZT_XLAW(energy, ts->chans);
					ts->dtmfenergy[base] = energy;
				}
				set_bit(base, &ts->dtmfactive);
				if (ts->dtmfdigit[base]) {
					if (ts->dtmfmask & (1 << base))
						zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base]));
				}
				ts->dtmfdigit[base] = digit;
				if (test_bit(base, &ts->dtmfmask))
					zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFDOWN | digit));
				if (test_bit(base, &ts->dtmfmutemask)) {
					/* Mute active receive buffer*/
					unsigned long flags;
					struct zt_chan *chan = &ts->span.chans[base];
					int y;
					spin_lock_irqsave(&chan->lock, flags);
					for (y=0;y<chan->numbufs;y++) {
						if ((chan->inreadbuf > -1) && (chan->readidx[y]))
							memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]);
					}
					spin_unlock_irqrestore(&chan->lock, flags);
				}
				if (debug)
					printk("Digit Seen: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x);
				

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -