⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wcfxs.c

📁 IP04是一个使用Blackfin开源硬件结合Asterisk开源软件建立的IPPBX系统.
💻 C
📖 第 1 页 / 共 5 页
字号:
	for ( i=0x1f; i>0; i--)	{		wcfxs_setreg(wc, card, 99,i);		origjiffies=jiffies; 		while((jiffies-origjiffies)<4);		if((wcfxs_getreg(wc,card,89)) == 0)			break;	}//for/*******************************The preceding is the manual gain mismatch calibration****************************//**********************************The following is the longitudinal Balance Cal***********************************/	wcfxs_setreg(wc,card,64,1);	while((jiffies-origjiffies)<10); // Sleep 100?	wcfxs_setreg(wc, card, 64, 0);	wcfxs_setreg(wc, card, 23, 0x4);  // enable interrupt for the balance Cal	wcfxs_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration	wcfxs_setreg(wc, card, 96,0x40);	wcfxs_getreg(wc,card,96); /* Read Reg 96 just cause */	wcfxs_setreg(wc, card, 21, 0xFF);	wcfxs_setreg(wc, card, 22, 0xFF);	wcfxs_setreg(wc, card, 23, 0xFF);	/**The preceding is the longitudinal Balance Cal***/	return(0);}#if 1static int wcfxs_proslic_calibrate(struct wcfxs *wc, int card){	unsigned long origjiffies;	int x;	printk("Start automatic calibration\n");	/* Perform all calibrations */	wcfxs_setreg(wc, card, 97, 0x1f);		/* Begin, no speedup */	wcfxs_setreg(wc, card, 96, 0x5f);	/* Wait for it to finish */	origjiffies = jiffies;	while(wcfxs_getreg(wc, card, 96)) {		if ((jiffies - origjiffies) > 2 * HZ) {			printk("Timeout waiting for calibration of module %d\n", card);			return -1;		}	}		if (debug) {		/* Print calibration parameters */		printk("Calibration Vector Regs 98 - 107: \n");		for (x=98;x<108;x++) {			printk("%d: %02x\n", x, wcfxs_getreg(wc, card, x));		}	}	return 0;}#endif/* wait 'foo' jiffies then return.     DR - modified to use a better delay mechanism that the orginal   busy-waiting method, which locked the kernel up for some rather   long times (e.g. seconds), at least on non-preemptable kernels.*/static void wait_just_a_bit(int foo){	set_current_state(TASK_INTERRUPTIBLE);	schedule_timeout(foo);}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;		//printk("Entering: wcfxs_init_voicedaa\n");	/* Sanity check */	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, (card) * 8);	wcfxs_setreg(wc, card, 35, 0x00);	wcfxs_setreg(wc, card, 36, (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);	/* DR 6/1105: Debug code used to trap bad reads, 	   see notes in __write_8bits 	{	        int i;		unsigned char r;		for(i=0; i<1000; i++) {			r = wcfxs_getreg(wc, card, 31);			if (r != 0xa3) {				printk("bad read! Check if CS is going low\n");				break;			}		}       		printk("  1000 reads OK!\n");	}	*/		/* Optional digital loopback, used for testing Blackfin DMA */	if (loopback) {		wcfxs_setreg(wc, card, 10, 0x01);		printk("loopback enabled\n");	}	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;	manual = 1;	/* 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, (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, (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);	}	wcfxs_setreg(wc, card, 64, 0x01);	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(&regs, 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, &regs, sizeof(regs)))			return -EFAULT;		break;	case WCFXS_SET_REG:		if (copy_from_user(&regop, (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;#else	try_module_get(THIS_MODULE);#endif		return 0;}static int wcfxs_watchdog(struct zt_span *span, int event){	printk("TDM: Restarting DMA\n");#ifdef NOT_NEEDED_YET

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -