📄 wcfxs.c
字号:
extern int l1_data_A_sram_free(unsigned long addr);#endif#endifstatic int wcfxs_init_proslic(struct wcfxs *wc, int card, int fast , int manual, int sane);static void wait_just_a_bit(int foo);#ifdef AUDIO_RINGCHECKstatic inline void ring_check(struct wcfxs *wc, int card){ int x; short sample; if (wc->modtype[card] != MOD_TYPE_FXO) return; wc->mod.fxo.pegtimer[card] += ZT_CHUNKSIZE; for (x=0;x<ZT_CHUNKSIZE;x++) { /* Look for pegging to indicate ringing */ sample = ZT_XLAW(wc->chans[card].readchunk[x], (&(wc->chans[card]))); if ((sample > 10000) && (wc->mod.fxo.peg[card] != 1)) { if (debug > 1) printk("High peg!\n"); if ((wc->mod.fxo.pegtimer[card] < PEGTIME) && (wc->mod.fxo.pegtimer[card] > MINPEGTIME)) wc->mod.fxo.pegcount[card]++; wc->mod.fxo.pegtimer[card] = 0; wc->mod.fxo.peg[card] = 1; } else if ((sample < -10000) && (wc->mod.fxo.peg[card] != -1)) { if (debug > 1) printk("Low peg!\n"); if ((wc->mod.fxo.pegtimer[card] < (PEGTIME >> 2)) && (wc->mod.fxo.pegtimer[card] > (MINPEGTIME >> 2))) wc->mod.fxo.pegcount[card]++; wc->mod.fxo.pegtimer[card] = 0; wc->mod.fxo.peg[card] = -1; } } if (wc->mod.fxo.pegtimer[card] > PEGTIME) { /* Reset pegcount if our timer expires */ wc->mod.fxo.pegcount[card] = 0; } /* Decrement debouncer if appropriate */ if (wc->mod.fxo.ringdebounce[card]) wc->mod.fxo.ringdebounce[card]--; if (!wc->mod.fxo.offhook[card] && !wc->mod.fxo.ringdebounce[card]) { if (!wc->mod.fxo.ring[card] && (wc->mod.fxo.pegcount[card] > PEGCOUNT)) { /* It's ringing */ if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); if (!wc->mod.fxo.offhook[card]) zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); wc->mod.fxo.ring[card] = 1; } if (wc->mod.fxo.ring[card] && !wc->mod.fxo.pegcount[card]) { /* No more ring */ if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); wc->mod.fxo.ring[card] = 0; } }}#endif//static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e};//int swi = 0;//static short sw[] = {2048, 1023, -1024, -2048, -1023, 1024};#define LOG_LEN 64#define LOG_START 0int logdma1[LOG_LEN];int logdma2[20];int logdma3[20];int ilogdma = 0;int serialnum = 0;int notzero=0;static inline void wcfxs_transmitprep(struct wcfxs *wc, u8 *writechunk){ int x; /* Calculate Transmission */ zt_transmit(&wc->span); for (x=0;x<ZT_CHUNKSIZE;x++) { if (wc->cardflag & (1 << 7)) writechunk[8*x+7] = wc->chans[7].writechunk[x]; if (wc->cardflag & (1 << 6)) writechunk[8*x+6] = wc->chans[6].writechunk[x]; if (wc->cardflag & (1 << 5)) writechunk[8*x+5] = wc->chans[5].writechunk[x]; if (wc->cardflag & (1 << 4)) writechunk[8*x+4] = wc->chans[4].writechunk[x]; if (wc->cardflag & (1 << 3)) writechunk[8*x+3] = wc->chans[3].writechunk[x]; if (wc->cardflag & (1 << 2)) writechunk[8*x+2] = wc->chans[2].writechunk[x]; if (wc->cardflag & (1 << 1)) writechunk[8*x+1] = wc->chans[1].writechunk[x]; if (wc->cardflag & (1 << 0)) { writechunk[8*x+0] = wc->chans[0].writechunk[x]; //writechunk[8*x+0] = ZT_LIN2MU(sw[swi++]); //if (swi == 6) swi = 0; } }}static inline void wcfxs_receiveprep(struct wcfxs *wc, u8 *readchunk){ int x; //int echo_before; for (x=0;x<ZT_CHUNKSIZE;x++) { if (wc->cardflag & (1 << 7)) wc->chans[7].readchunk[x] = readchunk[8*x+7]; if (wc->cardflag & (1 << 6)) wc->chans[6].readchunk[x] = readchunk[8*x+6]; if (wc->cardflag & (1 << 5)) wc->chans[5].readchunk[x] = readchunk[8*x+5]; if (wc->cardflag & (1 << 4)) wc->chans[4].readchunk[x] = readchunk[8*x+4]; if (wc->cardflag & (1 << 3)) wc->chans[3].readchunk[x] = readchunk[8*x+3]; if (wc->cardflag & (1 << 2)) wc->chans[2].readchunk[x] = readchunk[8*x+2]; if (wc->cardflag & (1 << 1)) wc->chans[1].readchunk[x] = readchunk[8*x+1]; if (wc->cardflag & (1 << 0)) wc->chans[0].readchunk[x] = readchunk[8*x+0]; }#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 :( */ //echo_before = cycles(); 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); } //echo_sams = cycles() - echo_before; zt_receive(&wc->span);}/* we have only one card at the moment */static inline void __wcfxs_setcard(struct wcfxs *wc, int card){ if (wc->curcard != card) { //printk("wc->curcard: %d card: %d\n", wc->curcard, card); #ifdef NOT_NEEDED __wcfxs_setcreg(wc, WC_CS, (1 << card)); #endif if (card < 4) { #ifdef CONFIG_4FX_SPI_INTERFACE bfsi_spi_write_8_bits(SPI_NCSB, card+1); #else sport_tx_byte(SPI_NCSB, card+1); #endif } else { #ifdef CONFIG_4FX_SPI_INTERFACE bfsi_spi_write_8_bits(SPI_NCSB, 0x40 + (card-4) + 1); #else sport_tx_byte(SPI_NCSB, 0x40 + (card-4) + 1); #endif } 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 { //#define DAISY #ifdef DAISY __write_8bits(wc, 0x01); // 3210 daisy chain mode #endif __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 inline void wcfxs_set_led(struct wcfxs *wc, int port, int colour){ unsigned long flags; spin_lock_irqsave(&wc->lock, flags); fx_set_led(port, colour); wc->curcard = -1; /* leds mess up current card setting */ 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 { #ifdef DAISY __write_8bits(wc, 0x01); // 3210 daisy chain mode #endif __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 unsigned char translate_3215(unsigned char address){ int x; for (x=0;x<sizeof(indirect_regs)/sizeof(indirect_regs[0]);x++) { if (indirect_regs[x].address == address) { address = indirect_regs[x].altaddr; break; } } return address;}static int wcfxs_proslic_setreg_indirect(struct wcfxs *wc, int card, unsigned char address, unsigned short data){ unsigned long flags; int res = -1; /* Translate 3215 addresses */ if (wc->flags[card] & FLAG_3215) { address = translate_3215(address); if (address == 255) return 0; } 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; /* Translate 3215 addresses */ if (wc->flags[card] & FLAG_3215) { address = translate_3215(address); if (address == 255) return 0; } 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 && (!(wc->flags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) { 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; reg5 = b; reg12 = wcfxs_getreg(wc, card, 12); loop_i = wcfxs_getreg(wc, card, 28); line_v = wcfxs_getreg(wc, card, 29); 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 * NUM_CARDS); 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); wcfxs_set_led(wc, card+1, FX_LED_GREEN); 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); wcfxs_set_led(wc, card+1, FX_LED_RED); /* leds mess up current card setting */ wc->curcard = -1; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -