📄 wcfxs.c
字号:
{ long newjiffies; newjiffies = jiffies + foo; while(jiffies < newjiffies);}static int wcfxs_init_voicedaa(struct wcfxs *wc, int card, int fast, int manual, int sane){ unsigned char reg16=0, reg26=0, reg30=0, reg31=0; long newjiffies; wc->modtype[card] = MOD_TYPE_FXO; /* Sanity check the ProSLIC */ reset_spi(wc, card); if (!sane && wcfxs_voicedaa_insane(wc, card)) return -2; /* Software reset */ wcfxs_setreg(wc, card, 1, 0x80); /* Wait just a bit */ wait_just_a_bit(HZ/10); /* Enable PCM, ulaw */ wcfxs_setreg(wc, card, 33, 0x28); /* Set On-hook speed, Ringer impedence, and ringer threshold */ reg16 |= (fxo_modes[_opermode].ohs << 6); reg16 |= (fxo_modes[_opermode].rz << 1); reg16 |= (fxo_modes[_opermode].rt); wcfxs_setreg(wc, card, 16, reg16); /* Set DC Termination: Tip/Ring voltage adjust, minimum operational current, current limitation */ reg26 |= (fxo_modes[_opermode].dcv << 6); reg26 |= (fxo_modes[_opermode].mini << 4); reg26 |= (fxo_modes[_opermode].ilim << 1); wcfxs_setreg(wc, card, 26, reg26); /* Set AC Impedence */ reg30 = (fxo_modes[_opermode].acim); wcfxs_setreg(wc, card, 30, reg30); /* Misc. DAA parameters */ reg31 = 0xa3; reg31 |= (fxo_modes[_opermode].ohs2 << 3); wcfxs_setreg(wc, card, 31, reg31); /* Set Transmit/Receive timeslot */ wcfxs_setreg(wc, card, 34, (3-card) * 8); wcfxs_setreg(wc, card, 35, 0x00); wcfxs_setreg(wc, card, 36, (3-card) * 8); wcfxs_setreg(wc, card, 37, 0x00); /* Enable ISO-Cap */ wcfxs_setreg(wc, card, 6, 0x00); /* Wait 1000ms for ISO-cap to come up */ newjiffies = jiffies; newjiffies += 2 * HZ; while((jiffies < newjiffies) && !(wcfxs_getreg(wc, card, 11) & 0xf0)) wait_just_a_bit(HZ/10); if (!(wcfxs_getreg(wc, card, 11) & 0xf0)) { printk("VoiceDAA did not bring up ISO link properly!\n"); return -1; } if (debug) printk("ISO-Cap is now up, line side: %02x rev %02x\n", wcfxs_getreg(wc, card, 11) >> 4, (wcfxs_getreg(wc, card, 13) >> 2) & 0xf); /* Enable on-hook line monitor */ wcfxs_setreg(wc, card, 5, 0x08); return 0; }static int wcfxs_init_proslic(struct wcfxs *wc, int card, int fast, int manual, int sane){ unsigned short tmp[5]; unsigned char r19; int x; int fxsmode=0; /* By default, don't send on hook */ wc->mod.fxs.idletxhookstate [card] = 1; /* Sanity check the ProSLIC */ if (!sane && wcfxs_proslic_insane(wc, card)) return -2; if (sane) { /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ wcfxs_setreg(wc, card, 14, 0x10); } if (wcfxs_proslic_init_indirect_regs(wc, card)) { printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); return -1; } /* Clear scratch pad area */ wcfxs_proslic_setreg_indirect(wc, card, 97,0); /* Clear digital loopback */ wcfxs_setreg(wc, card, 8, 0); /* Revision C optimization */ wcfxs_setreg(wc, card, 108, 0xeb); /* Disable automatic VBat switching for safety to prevent Q7 from accidently turning on and burning out. */ wcfxs_setreg(wc, card, 67, 0x17); /* Turn off Q7 */ wcfxs_setreg(wc, card, 66, 1); /* Flush ProSLIC digital filters by setting to clear, while saving old values */ for (x=0;x<5;x++) { tmp[x] = wcfxs_proslic_getreg_indirect(wc, card, x + 35); wcfxs_proslic_setreg_indirect(wc, card, x + 35, 0x8000); } /* Power up the DC-DC converter */ if (wcfxs_powerup_proslic(wc, card, fast)) { printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); return -1; } if (!fast) { /* Check for power leaks */ if (wcfxs_proslic_powerleak_test(wc, card)) { printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); } /* Power up again */ if (wcfxs_powerup_proslic(wc, card, fast)) { printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); return -1; }#ifndef NO_CALIBRATION /* Perform calibration */ if(manual) { if (wcfxs_proslic_manual_calibrate(wc, card)) { //printk("Proslic failed on Manual Calibration\n"); if (wcfxs_proslic_manual_calibrate(wc, card)) { printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); return -1; } printk("Proslic Passed Manual Calibration on Second Attempt\n"); } } else { if(wcfxs_proslic_calibrate(wc, card)) { //printk("ProSlic died on Auto Calibration.\n"); if (wcfxs_proslic_calibrate(wc, card)) { printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); return -1; } printk("Proslic Passed Auto Calibration on Second Attempt\n"); } } /* Perform DC-DC calibration */ wcfxs_setreg(wc, card, 93, 0x99); r19 = wcfxs_getreg(wc, card, 107); if ((r19 < 0x2) || (r19 > 0xd)) { printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); wcfxs_setreg(wc, card, 107, 0x8); } /* Save calibration vectors */ for (x=0;x<NUM_CAL_REGS;x++) wc->mod.fxs.calregs[card].vals[x] = wcfxs_getreg(wc, card, 96 + x);#endif } else { /* Restore calibration registers */ for (x=0;x<NUM_CAL_REGS;x++) wcfxs_setreg(wc, card, 96 + x, wc->mod.fxs.calregs[card].vals[x]); } /* Calibration complete, restore original values */ for (x=0;x<5;x++) { wcfxs_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); } if (wcfxs_proslic_verify_indirect_regs(wc, card)) { printk(KERN_INFO "Indirect Registers failed verification.\n"); return -1; }#if 0 /* Disable Auto Power Alarm Detect and other "features" */ wcfxs_setreg(wc, card, 67, 0x0e); blah = wcfxs_getreg(wc, card, 67);#endif#if 0 if (wcfxs_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix printk(KERN_INFO "ProSlic IndirectReg Died.\n"); return -1; }#endif wcfxs_setreg(wc, card, 1, 0x28); // U-Law 8-bit interface wcfxs_setreg(wc, card, 2, (3-card) * 8); // Tx Start count low byte 0 wcfxs_setreg(wc, card, 3, 0); // Tx Start count high byte 0 wcfxs_setreg(wc, card, 4, (3-card) * 8); // Rx Start count low byte 0 wcfxs_setreg(wc, card, 5, 0); // Rx Start count high byte 0 wcfxs_setreg(wc, card, 18, 0xff); // clear all interrupt wcfxs_setreg(wc, card, 19, 0xff); wcfxs_setreg(wc, card, 20, 0xff); wcfxs_setreg(wc, card, 73, 0x04); if (fxshonormode) { fxsmode = acim2tiss[fxo_modes[_opermode].acim]; wcfxs_setreg(wc, card, 10, 0x08 | fxsmode); if (fxo_modes[_opermode].ring_osc) wcfxs_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); if (fxo_modes[_opermode].ring_x) wcfxs_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); } if (lowpower) wcfxs_setreg(wc, card, 72, 0x10);#if 0 wcfxs_setreg(wc, card, 21, 0x00); // enable interrupt wcfxs_setreg(wc, card, 22, 0x02); // Loop detection interrupt wcfxs_setreg(wc, card, 23, 0x01); // DTMF detection interrupt#endif#if 0 /* Enable loopback */ wcfxs_setreg(wc, card, 8, 0x2); wcfxs_setreg(wc, card, 14, 0x0); wcfxs_setreg(wc, card, 64, 0x0); wcfxs_setreg(wc, card, 1, 0x08);#endif /* Beef up Ringing voltage to 89V */ if (boostringer) { if (wcfxs_proslic_setreg_indirect(wc, card, 21, 0x1d1)) return -1; printk("Boosting ringinger on slot %d (89V peak)\n", card + 1); } else if (lowpower) { if (wcfxs_proslic_setreg_indirect(wc, card, 21, 0x108)) return -1; printk("Reducing ring power on slot %d (50V peak)\n", card + 1); } return 0;}static int wcfxs_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data){ struct wcfxs_stats stats; struct wcfxs_regs regs; struct wcfxs_regop regop; struct wcfxs *wc = chan->pvt; int x; switch (cmd) { case ZT_ONHOOKTRANSFER: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (int *)data)) return -EFAULT; wc->mod.fxs.ohttimer[chan->chanpos - 1] = x << 3; wc->mod.fxs.idletxhookstate[chan->chanpos - 1] = 0x2; /* OHT mode when idle */ if (wc->mod.fxs.lasttxhook[chan->chanpos - 1] == 0x1) { /* Apply the change if appropriate */ wc->mod.fxs.lasttxhook[chan->chanpos - 1] = 0x2; wcfxs_setreg(wc, chan->chanpos - 1, 64, wc->mod.fxs.lasttxhook[chan->chanpos - 1]); } break; case WCFXS_GET_STATS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { stats.tipvolt = wcfxs_getreg(wc, chan->chanpos - 1, 80) * -376; stats.ringvolt = wcfxs_getreg(wc, chan->chanpos - 1, 81) * -376; stats.batvolt = wcfxs_getreg(wc, chan->chanpos - 1, 82) * -376; } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { stats.tipvolt = (signed char)wcfxs_getreg(wc, chan->chanpos - 1, 29) * 1000; stats.ringvolt = (signed char)wcfxs_getreg(wc, chan->chanpos - 1, 29) * 1000; stats.batvolt = (signed char)wcfxs_getreg(wc, chan->chanpos - 1, 29) * 1000; } else return -EINVAL; if (copy_to_user((struct wcfxs_stats *)data, &stats, sizeof(stats))) return -EFAULT; break; case WCFXS_GET_REGS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { for (x=0;x<NUM_INDIRECT_REGS;x++) regs.indirect[x] = wcfxs_proslic_getreg_indirect(wc, chan->chanpos -1, x); for (x=0;x<NUM_REGS;x++) regs.direct[x] = wcfxs_getreg(wc, chan->chanpos - 1, x); } else { memset(®s, 0, sizeof(regs)); for (x=0;x<NUM_FXO_REGS;x++) regs.direct[x] = wcfxs_getreg(wc, chan->chanpos - 1, x); } if (copy_to_user((struct wcfxs_regs *)data, ®s, sizeof(regs))) return -EFAULT; break; case WCFXS_SET_REG: if (copy_from_user(®op, (struct wcfxs_regop *)data, sizeof(regop))) return -EFAULT; if (regop.indirect) { if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); wcfxs_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); } else { regop.val &= 0xff; printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); wcfxs_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); } break; default: return -ENOTTY; } return 0;}static int wcfxs_open(struct zt_chan *chan){ struct wcfxs *wc = chan->pvt; if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) return -ENODEV; if (wc->dead) return -ENODEV; wc->usecount++;#ifndef LINUX26 MOD_INC_USE_COUNT;#endif return 0;}static int wcfxs_watchdog(struct zt_span *span, int event){ printk("TDM: Restarting DMA\n"); wcfxs_restart_dma(span->pvt); return 0;}static int wcfxs_close(struct zt_chan *chan){ struct wcfxs *wc = chan->pvt; int x; wc->usecount--;#ifndef LINUX26 MOD_DEC_USE_COUNT;#endif for (x=0;x<wc->cards;x++) wc->mod.fxs.idletxhookstate[x] = 1; /* If we're dead, release us now */ if (!wc->usecount && wc->dead) wcfxs_release(wc); return 0;}static int wcfxs_hooksig(struct zt_chan *chan, zt_txsig_t txsig){ struct wcfxs *wc = chan->pvt; int reg=0; if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { /* XXX Enable hooksig for FXO XXX */ switch(txsig) { case ZT_TXSIG_START: case ZT_TXSIG_OFFHOOK: wc->mod.fxo.offhook[chan->chanpos - 1] = 1; wcfxs_setreg(wc, chan->chanpos - 1, 5, 0x9); break; case ZT_TXSIG_ONHOOK: wc->mod.fxo.offhook[chan->chanpos - 1] = 0; wcfxs_setreg(wc, chan->chanpos - 1, 5, 0x8); break; default: printk("wcfxo: Can't set tx state to %d\n", txsig); } } else { switch(txsig) { case ZT_TXSIG_ONHOOK: switch(chan->sig) { case ZT_SIG_EM: case ZT_SIG_FXOKS: case ZT_SIG_FXOLS: wc->mod.fxs.lasttxhook[chan->chanpos-1] = wc->mod.fxs.idletxhookstate[chan->chanpos-1]; break; case ZT_SIG_FXOGS: wc->mod.fxs.lasttxhook[chan->chanpos-1] = 3; break; } break; case ZT_TXSIG_OFFHOOK: switch(chan->sig) { case ZT_SIG_EM: wc->mod.fxs.lasttxhook[chan->chanpos-1] = 5; break; default: wc->mod.fxs.lasttxhook[chan->chanpos-1] = wc->mod.fxs.idletxhookstate[chan->chanpos-1]; break; } break; case ZT_TXSIG_START: wc->mod.fxs.lasttxhook[chan->chanpos-1] = 4; break; case ZT_TXSIG_KEWL: wc->mod.fxs.lasttxhook[chan->chanpos-1] = 0; break; default: printk("wcfxs: Can't set tx state to %d\n", txsig); } if (debug) printk("Setting FXS hook state to %d (%02x)\n", txsig, reg);#if 1 wcfxs_setreg(wc, chan->chanpos - 1, 64, wc->mod.fxs.lasttxhook[chan->chanpos-1]);#endif } return 0;}static int wcfxs_initialize(struct wcfxs *wc){ int x; /* Zapata stuff */ sprintf(wc->span.name, "WCTDM/%d", wc->pos); sprintf(wc->span.desc, "%s Board %d", wc->variety, wc->pos + 1); wc->span.deflaw = ZT_LAW_MULAW; for (x=0;x<wc->cards;x++) { sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM; wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF; wc->chans[x].chanpos = x+1; wc->chans[x].pvt = wc; } wc->span.chans = wc->chans; wc->span.channels = wc->cards; wc->span.hooksig = wcfxs_hooksig; wc->span.open = wcfxs_open; wc->span.close = wcfxs_close; wc->span.flags = ZT_FLAG_RBS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -