📄 base.c
字号:
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 + -