📄 wcfxs.c
字号:
wcfxs_restart_dma(span->pvt);#endif return 0;}static int wcfxs_close(struct zt_chan *chan){ struct wcfxs *wc = chan->pvt; wc->usecount--;#ifndef LINUX26 MOD_DEC_USE_COUNT;#else module_put(THIS_MODULE);#endif if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) wc->mod.fxs.idletxhookstate[chan->chanpos - 1] = 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: wcfxs_set_led(wc, chan->chanpos, FX_LED_GREEN); 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: wcfxs_set_led(wc, chan->chanpos, FX_LED_GREEN); 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: wcfxs_set_led(wc, chan->chanpos, FX_LED_RED); 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 | ZT_SIG_CLEAR; wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; 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; wc->span.ioctl = wcfxs_ioctl; wc->span.watchdog = wcfxs_watchdog; init_waitqueue_head(&wc->span.maintq); wc->span.pvt = wc; if (zt_register(&wc->span, 0)) { printk("Unable to register span with zaptel\n"); return -1; } return 0;}static void wcfxs_post_initialize(struct wcfxs *wc){ int x; /* Finalize signalling */ for (x=0;x<wc->cards;x++) { if (wc->cardflag & (1 << x)) { if (wc->modtype[x] == MOD_TYPE_FXO) wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; else wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; } }}int wcfxs_proc_read(char *buf, char **start, off_t offset, int count, int *eof, void *data){ int len; len = sprintf(buf, "3050 reg5.....: 0x%x\n" "3050 reg12....: 0x%x\n" "3050 loop_i...: 0x%x\n" "3050 line_v...: 0x%x\n", reg5, reg12, loop_i, line_v); *eof=1; return len;}static int wcfxs_hardware_init(struct wcfxs *wc){ /* Hardware stuff */ unsigned char x; char port_type[FX_MAX_PORTS]; int i; #ifdef CONFIG_4FX_SPI_INTERFACE bfsi_spi_init(SPI_BAUDS, (1<<SPI_NCSA) | (1<<SPI_NCSB)); #else sport_interface_init ( SPI_BAUDS, (1<<SPI_NCSA) | (1<<SPI_NCSB) ); #endif // select port 1 SPI device //bfsi_spi_write_8_bits(2, 2); create_proc_read_entry("wcfxs", 0, NULL, wcfxs_proc_read, NULL); bfsi_sport_init(regular_interrupt_processing, ZT_CHUNKSIZE, debug); bfsi_reset(RESET_BIT); #ifdef DAISY /* put 3210 in daisy chain mode */ __write_8bits(wc, 0x00); /* reg 0 write */ __write_8bits(wc, 0x80); /* value to write (set bit 7) */ #endif /* auto-detect each port type */ fx_auto_detect(port_type, RESET_BIT); for(i=0; i<FX_MAX_PORTS; i++) { printk("port: %d port_type: %c\n", i+1, port_type[i]); } bfsi_reset(RESET_BIT); //{ u8 reg; //reg = fx_read_fxs(1); //printk("reg = 0x%x\n", reg); //}#define NEW_CODE#ifdef NEW_CODE /* configure daughter cards */ for (x=0;x<wc->cards;x++) { int sane=0,ret=0,readi=0; if (port_type[x] == 'O') { if (!(ret = wcfxs_init_voicedaa(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name); } else printk("Module %d: Not installed\n", x); } else { sane=0; /* Init with Automatic Calibaration */ if (!(ret = wcfxs_init_proslic(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); if (debug) { readi = wcfxs_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Module %d: Installed -- AUTO FXS\n",x); } else { if(ret != -2) { sane=1; /* Init with Manual Calibration */ if (!wcfxs_init_proslic(wc, x, 0, 1, sane)) { wc->cardflag |= (1 << x); if (debug) { readi = wcfxs_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Module %d: Installed -- MANUAL FXS\n",x); } else { printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC"); } } } } }#endif //#define OLD_CODE#ifdef OLD_CODE for (x=0;x<wc->cards;x++) { int sane=0,ret=0,readi=0; /* Init with Auto Calibration */ if (!(ret=wcfxs_init_proslic(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); if (debug) { readi = wcfxs_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Module %d: Installed -- AUTO FXS/DPO\n",x); } else { if(ret!=-2) { sane=1; /* Init with Manual Calibration */ if (!wcfxs_init_proslic(wc, x, 0, 1, sane)) { wc->cardflag |= (1 << x); if (debug) { readi = wcfxs_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Module %d: Installed -- MANUAL FXS\n",x); } else { printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC"); } } else { if (!(ret = wcfxs_init_voicedaa(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name); } else printk("Module %d: Not installed\n", x); } } }#endif /* Return error if nothing initialized okay. */ if (!wc->cardflag && !timingonly) { printk("couldn't init OK...returning -1\n"); bfsi_sport_close(); return -1; } return 0;}static int wcfxs_init_one(struct wcfxs_desc *d){ int res; struct wcfxs *wc; int x; int y; static int initd_ifaces=0; wcfxs_init_ok = 0; if(initd_ifaces){ memset((void *)ifaces,0,(sizeof(struct wcfxs *))*WC_MAX_IFACES); initd_ifaces=1; } for (x=0;x<WC_MAX_IFACES;x++) if (!ifaces[x]) break; if (x >= WC_MAX_IFACES) { printk("Too many interfaces\n"); return -EIO; } wc = kmalloc(sizeof(struct wcfxs), GFP_KERNEL); if (wc) { ifaces[x] = wc; memset(wc, 0, sizeof(struct wcfxs)); spin_lock_init(&wc->lock); wc->curcard = -1; wc->cards = NUM_CARDS; wc->pos = x; wc->variety = d->name; wc->irq = IRQ_SPORT0_RX; devs = wc; for (y=0;y<NUM_CARDS;y++) wc->flags[y] = d->flags; if (wcfxs_initialize(wc)) { printk("wcfxs: Unable to intialize FXS\n"); kfree(wc); return -EIO; } if (wcfxs_hardware_init(wc)) { zt_unregister(&wc->span); printk("wcfxs_hardware_init() failed...\n"); kfree(wc); return -EIO; } wcfxs_init_ok = 1; wcfxs_post_initialize(wc); printk("Found: %s (%d modules)\n", wc->variety, wc->cards); res = 0; } else res = -ENOMEM; return res;}static void wcfxs_release(struct wcfxs *wc){ printk("wcfxs_init_ok = %d\n", wcfxs_init_ok); if (wcfxs_init_ok) { /* disable serial port, this will stop DMA and interrupts */ bfsi_sport_close(); zt_unregister(&wc->span); kfree(wc); } remove_proc_entry("wcfxs", NULL); printk("Freed a Wildcard\n");}static int __init wcfxs_init(void){ int x; printk(KERN_ALERT "Code test: code function addr = 0x%p\n", zt_ec_chunk); for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { if (!strcmp(fxo_modes[x].name, opermode)) break; } if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { _opermode = x; } else { printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); for (x=0;x<sizeof(fxo_modes) / sizeof(fxo_modes[0]); x++) printk(" %s\n", fxo_modes[x].name); printk("Note this option is CASE SENSITIVE!\n"); return -ENODEV; } wcfxs_init_one(&wcfxs_bf); wait_just_a_bit(10); printk("wcfxs_init_ok = %d\n", wcfxs_init_ok); return 0;}static void __exit wcfxs_cleanup(void){ wcfxs_release(devs); #ifdef OLD_DR if (loopback) { for(r=0; r<ZT_CHUNKSIZE*2; r++) { printk("[%03d] ", r*8); for(c=0; c<8; c++) { printk("0x%02x 0x%02x ", iTxBuffer1[r*8+c]&0xff, iRxBuffer1[r*8+c]&0xff); } printk("\n"); } //for(r=0; r<10; r++) { // printk("[%03d] 0x%04x 0x%04x %d\n", r, logdma1[r], logdma2[r], logdma3[r]); //} for(r=0; r<LOG_LEN; r++) { printk("[%03d] %d\n", r, logdma1[r]); } printk("serialnum = %d ilogdma = %d\n",serialnum, ilogdma); } #endif}module_param(debug, int, 0600);module_param(loopcurrent, int, 0600);module_param(robust, int, 0600);module_param(_opermode, int, 0600);module_param(opermode, charp, 0600);module_param(timingonly, int, 0600);module_param(lowpower, int, 0600);module_param(boostringer, int, 0600);module_param(fxshonormode, int, 0600);module_param(loopback, int, 0600); /* uCasterisk test mode *///module_param(internalclock, int, 0600); /* uCasterisk test mode */MODULE_DESCRIPTION("Wildcard TDM400P Zaptel Driver");MODULE_AUTHOR("Mark Spencer <markster@digium.com>");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifmodule_init(wcfxs_init);module_exit(wcfxs_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -