📄 wcfxs.c
字号:
{ volatile unsigned int *readchunk; int x; if (ints & 0x08) readchunk = wc->readchunk + ZT_CHUNKSIZE; else /* Read is at interrupt address. Valid data is available at normal offset */ readchunk = wc->readchunk; for (x=0;x<ZT_CHUNKSIZE;x++) { if (wc->cardflag & (1 << 3)) wc->chans[3].readchunk[x] = (readchunk[x] >> 24) & 0xff; if (wc->cardflag & (1 << 2)) wc->chans[2].readchunk[x] = (readchunk[x] >> 16) & 0xff; if (wc->cardflag & (1 << 1)) wc->chans[1].readchunk[x] = (readchunk[x] >> 8) & 0xff; if (wc->cardflag & (1 << 0)) wc->chans[0].readchunk[x] = (readchunk[x]) & 0xff; }#ifdef AUDIO_RINGCHECK for (x=0;x<wc->cards;x++) ring_check(wc, x);#endif /* XXX We're wasting 8 taps. We should get closer :( */ for (x=0;x<wc->cards;x++) { if (wc->cardflag & (1 << x)) zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); } zt_receive(&wc->span);}static void wcfxs_stop_dma(struct wcfxs *wc);static void wcfxs_reset_tdm(struct wcfxs *wc);static void wcfxs_restart_dma(struct wcfxs *wc);static inline void __write_8bits(struct wcfxs *wc, unsigned char bits){ /* Drop chip select */ int x; wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios &= ~BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); for (x=0;x<8;x++) { /* Send out each bit, MSB first, drop SCLK as we do so */ if (bits & 0x80) wc->ios |= BIT_SDI; else wc->ios &= ~BIT_SDI; wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Now raise SCLK high again and repeat */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); bits <<= 1; } /* Finally raise CS back high again */ wc->ios |= BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); }static inline void __reset_spi(struct wcfxs *wc){ /* Drop chip select and clock once and raise and clock once */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios &= ~BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios |= BIT_SDI; wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Now raise SCLK high again and repeat */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Finally raise CS back high again */ wc->ios |= BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Clock again */ wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Now raise SCLK high again and repeat */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); }static inline unsigned char __read_8bits(struct wcfxs *wc){ unsigned char res=0, c; int x; wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Drop chip select */ wc->ios &= ~BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); for (x=0;x<8;x++) { res <<= 1; /* Get SCLK */ wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Read back the value */ c = inb(wc->ioaddr + WC_AUXR); if (c & BIT_SDO) res |= 1; /* Now raise SCLK high again */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); } /* Finally raise CS back high again */ wc->ios |= BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* And return our result */ return res;}static void __wcfxs_setcreg(struct wcfxs *wc, unsigned char reg, unsigned char val){ outb(val, wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));}static unsigned char __wcfxs_getcreg(struct wcfxs *wc, unsigned char reg){ return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));}static inline void __wcfxs_setcard(struct wcfxs *wc, int card){ if (wc->curcard != card) { __wcfxs_setcreg(wc, WC_CS, (1 << card)); wc->curcard = card; }}static void __wcfxs_setreg(struct wcfxs *wc, int card, unsigned char reg, unsigned char value){ __wcfxs_setcard(wc, card); if (wc->modtype[card] == MOD_TYPE_FXO) { __write_8bits(wc, 0x20); __write_8bits(wc, reg & 0x7f); } else { __write_8bits(wc, reg & 0x7f); } __write_8bits(wc, value);}static void wcfxs_setreg(struct wcfxs *wc, int card, unsigned char reg, unsigned char value){ unsigned long flags; spin_lock_irqsave(&wc->lock, flags); __wcfxs_setreg(wc, card, reg, value); spin_unlock_irqrestore(&wc->lock, flags);}static unsigned char __wcfxs_getreg(struct wcfxs *wc, int card, unsigned char reg){ __wcfxs_setcard(wc, card); if (wc->modtype[card] == MOD_TYPE_FXO) { __write_8bits(wc, 0x60); __write_8bits(wc, reg & 0x7f); } else { __write_8bits(wc, reg | 0x80); } return __read_8bits(wc);}static inline void reset_spi(struct wcfxs *wc, int card){ unsigned long flags; spin_lock_irqsave(&wc->lock, flags); __wcfxs_setcard(wc, card); __reset_spi(wc); __reset_spi(wc); spin_unlock_irqrestore(&wc->lock, flags);}static unsigned char wcfxs_getreg(struct wcfxs *wc, int card, unsigned char reg){ unsigned long flags; unsigned char res; spin_lock_irqsave(&wc->lock, flags); res = __wcfxs_getreg(wc, card, reg); spin_unlock_irqrestore(&wc->lock, flags); return res;}static int __wait_access(struct wcfxs *wc, int card){ unsigned char data; long origjiffies; int count = 0; #define MAX 6000 /* attempts */ origjiffies = jiffies; /* Wait for indirect access */ while (count++ < MAX) { data = __wcfxs_getreg(wc, card, I_STATUS); if (!data) return 0; } if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); return 0;}static int wcfxs_proslic_setreg_indirect(struct wcfxs *wc, int card, unsigned char address, unsigned short data){ unsigned long flags; int res = -1; spin_lock_irqsave(&wc->lock, flags); if(!__wait_access(wc, card)) { __wcfxs_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); __wcfxs_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); __wcfxs_setreg(wc, card, IAA,address); res = 0; }; spin_unlock_irqrestore(&wc->lock, flags); return res;}static int wcfxs_proslic_getreg_indirect(struct wcfxs *wc, int card, unsigned char address){ unsigned long flags; int res = -1; char *p=NULL; spin_lock_irqsave(&wc->lock, flags); if (!__wait_access(wc, card)) { __wcfxs_setreg(wc, card, IAA, address); if (!__wait_access(wc, card)) { unsigned char data1, data2; data1 = __wcfxs_getreg(wc, card, IDA_LO); data2 = __wcfxs_getreg(wc, card, IDA_HI); res = data1 | (data2 << 8); } else p = "Failed to wait inside\n"; } else p = "failed to wait\n"; spin_unlock_irqrestore(&wc->lock, flags); if (p) printk(p); return res;}static int wcfxs_proslic_init_indirect_regs(struct wcfxs *wc, int card){ unsigned char i; for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++) { if(wcfxs_proslic_setreg_indirect(wc, card, indirect_regs[i].address,indirect_regs[i].initial)) return -1; } return 0;}static int wcfxs_proslic_verify_indirect_regs(struct wcfxs *wc, int card){ int passed = 1; unsigned short i, initial; int j; for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++) { if((j = wcfxs_proslic_getreg_indirect(wc, card, (unsigned char) indirect_regs[i].address)) < 0) { printk("Failed to read indirect register %d\n", i); return -1; } initial= indirect_regs[i].initial; if ( j != initial ) { printk("!!!!!!! %s iREG %X = %X should be %X\n", indirect_regs[i].name,indirect_regs[i].address,j,initial ); passed = 0; } } if (passed) { if (debug) printk("Init Indirect Registers completed successfully.\n"); } else { printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); return -1; } return 0;}static inline void wcfxs_voicedaa_check_hook(struct wcfxs *wc, int card){#ifndef AUDIO_RINGCHECK unsigned char res;#endif signed char b; int poopy = 0; /* Try to track issues that plague slot one FXO's */ b = wcfxs_getreg(wc, card, 5); if ((b & 0x2) || !(b & 0x8)) { /* Not good -- don't look at anything else */ if (debug) printk("Poopy (%02x) on card %d!\n", b, card + 1); poopy++; } b &= 0x9b; if (wc->mod.fxo.offhook[card]) { if (b != 0x9) wcfxs_setreg(wc, card, 5, 0x9); } else { if (b != 0x8) wcfxs_setreg(wc, card, 5, 0x8); } if (poopy) return;#ifndef AUDIO_RINGCHECK if (!wc->mod.fxo.offhook[card]) { res = wcfxs_getreg(wc, card, 5); if ((res & 0x60) && wc->mod.fxo.battery[card]) { wc->mod.fxo.ringdebounce[card] += (ZT_CHUNKSIZE * 4); if (wc->mod.fxo.ringdebounce[card] >= ZT_CHUNKSIZE * 64) { if (!wc->mod.fxo.wasringing[card]) { wc->mod.fxo.wasringing[card] = 1; zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); } wc->mod.fxo.ringdebounce[card] = ZT_CHUNKSIZE * 64; } } else { wc->mod.fxo.ringdebounce[card] -= ZT_CHUNKSIZE; if (wc->mod.fxo.ringdebounce[card] <= 0) { if (wc->mod.fxo.wasringing[card]) { wc->mod.fxo.wasringing[card] =0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); } wc->mod.fxo.ringdebounce[card] = 0; } } }#endif b = wcfxs_getreg(wc, card, 29);#if 0 { static int count = 0; if (!(count++ % 100)) { printk("Card %d: Voltage: %d Debounce %d\n", card + 1, b, wc->mod.fxo.battdebounce[card]); } }#endif if (abs(b) < BATT_THRESH) { wc->mod.fxo.nobatttimer[card]++;#if 0 if (wc->mod.fxo.battery[card]) printk("Battery loss: %d (%d debounce)\n", b, wc->mod.fxo.battdebounce[card]);#endif if (wc->mod.fxo.battery[card] && !wc->mod.fxo.battdebounce[card]) { if (debug) printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); wc->mod.fxo.battery[card] = 0;#ifdef JAPAN if ((!wc->ohdebounce) && wc->offhook) { zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); if (debug) printk("Signalled On Hook\n");#ifdef ZERO_BATT_RING wc->onhook++;#endif }#else zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);#endif wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE; } else if (!wc->mod.fxo.battery[card]) wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE; } else if (abs(b) > BATT_THRESH) { if (!wc->mod.fxo.battery[card] && !wc->mod.fxo.battdebounce[card]) { if (debug) printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, (b < 0) ? "-" : "+"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("Signalled Off Hook\n"); }#else zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);#endif wc->mod.fxo.battery[card] = 1; wc->mod.fxo.nobatttimer[card] = 0; wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE; } else if (wc->mod.fxo.battery[card]) wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE; if (wc->mod.fxo.lastpol[card] >= 0) { if (b < 0) { wc->mod.fxo.lastpol[card] = -1; wc->mod.fxo.polaritydebounce[card] = POLARITY_DEBOUNCE; } } if (wc->mod.fxo.lastpol[card] <= 0) { if (b > 0) { wc->mod.fxo.lastpol[card] = 1; wc->mod.fxo.polaritydebounce[card] = POLARITY_DEBOUNCE; } } } else { /* It's something else... */ wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE; } if (wc->mod.fxo.battdebounce[card]) wc->mod.fxo.battdebounce[card]--; if (wc->mod.fxo.polaritydebounce[card]) { wc->mod.fxo.polaritydebounce[card]--; if (wc->mod.fxo.polaritydebounce[card] < 1) { if (wc->mod.fxo.lastpol[card] != wc->mod.fxo.polarity[card]) { if (debug) printk("%lu Polarity reversed (%d -> %d)\n", jiffies, wc->mod.fxo.polarity[card], wc->mod.fxo.lastpol[card]); if (wc->mod.fxo.polarity[card]) zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); wc->mod.fxo.polarity[card] = wc->mod.fxo.lastpol[card]; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -