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

📄 wcfxs.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 5 页
字号:
static inline void wcfxs_proslic_check_hook(struct wcfxs *wc, int card){	char res;	int hook;	/* For some reason we have to debounce the	   hook detector.  */	res = wcfxs_getreg(wc, card, 68);	hook = (res & 1);	if (hook != wc->mod.fxs.lastrxhook[card]) {		/* Reset the debounce (must be multiple of 4ms) */		wc->mod.fxs.debounce[card] = 8 * (4 * 8);#if 0		printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mod.fxs.debounce[card]);#endif	} else {		if (wc->mod.fxs.debounce[card] > 0) {			wc->mod.fxs.debounce[card]-= 4 * ZT_CHUNKSIZE;#if 0			printk("Sustaining hook %d, %d\n", hook, wc->mod.fxs.debounce[card]);#endif			if (!wc->mod.fxs.debounce[card]) {#if 0				printk("Counted down debounce, newhook: %d...\n", hook);#endif				wc->mod.fxs.debouncehook[card] = hook;			}			if (!wc->mod.fxs.oldrxhook[card] && wc->mod.fxs.debouncehook[card]) {				/* Off hook */#if 1				if (debug)#endif									printk("wcfxs: Card %d Going off hook\n", card);				zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);				if (robust)					wcfxs_init_proslic(wc, card, 1, 0, 1);				wc->mod.fxs.oldrxhook[card] = 1;						} else if (wc->mod.fxs.oldrxhook[card] && !wc->mod.fxs.debouncehook[card]) {				/* On hook */#if 1				if (debug)#endif									printk("wcfxs: Card %d Going on hook\n", card);				zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);				wc->mod.fxs.oldrxhook[card] = 0;			}		}	}	wc->mod.fxs.lastrxhook[card] = hook;	}static inline void wcfxs_proslic_recheck_sanity(struct wcfxs *wc, int card){	int res;	/* Check loopback */	res = wcfxs_getreg(wc, card, 8);	if (res) {		printk("Ouch, part reset, quickly restoring reality (%d)\n", card);		wcfxs_init_proslic(wc, card, 1, 0, 1);	} else {		res = wcfxs_getreg(wc, card, 64);		if (!res && (res != wc->mod.fxs.lasttxhook[card])) {			if (wc->mod.fxs.palarms[card]++ < MAX_ALARMS) {				printk("Power alarm on module %d, resetting!\n", card + 1);				if (wc->mod.fxs.lasttxhook[card] == 4)					wc->mod.fxs.lasttxhook[card] = 1;				wcfxs_setreg(wc, card, 64, wc->mod.fxs.lasttxhook[card]);			} else {				if (wc->mod.fxs.palarms[card] == MAX_ALARMS)					printk("Too many power alarms on card %d, NOT resetting!\n", card + 1);			}		}	}}#ifdef LINUX26static irqreturn_t wcfxs_interrupt(int irq, void *dev_id, struct pt_regs *regs)#elsestatic void wcfxs_interrupt(int irq, void *dev_id, struct pt_regs *regs)#endif{	struct wcfxs *wc = dev_id;	unsigned char ints;	int x;	ints = inb(wc->ioaddr + WC_INTSTAT);	outb(ints, wc->ioaddr + WC_INTSTAT);	if (!ints)#ifdef LINUX26		return IRQ_NONE;#else		return;#endif			if (ints & 0x10) {		/* Stop DMA, wait for watchdog */		printk("TDM PCI Master abort\n");		wcfxs_stop_dma(wc);#ifdef LINUX26		return IRQ_RETVAL(1);#else		return;#endif			}		if (ints & 0x20) {		printk("PCI Target abort\n");#ifdef LINUX26		return IRQ_RETVAL(1);#else		return;#endif			}	for (x=0;x<4;x++) {		if ((x < wc->cards) && (wc->cardflag & (1 << x)) &&			(wc->modtype[x] == MOD_TYPE_FXS)) {			if (wc->mod.fxs.lasttxhook[x] == 0x4) {				/* RINGing, prepare for OHT */				wc->mod.fxs.ohttimer[x] = OHT_TIMER << 3;				wc->mod.fxs.idletxhookstate[x] = 0x2;	/* OHT mode when idle */			} else {				if (wc->mod.fxs.ohttimer[x]) {					wc->mod.fxs.ohttimer[x]-= ZT_CHUNKSIZE;					if (!wc->mod.fxs.ohttimer[x]) {						wc->mod.fxs.idletxhookstate[x] = 0x1;	/* Switch to active */						if (wc->mod.fxs.lasttxhook[x] == 0x2) {							/* Apply the change if appropriate */							wc->mod.fxs.lasttxhook[x] = 0x1;							wcfxs_setreg(wc, x, 64, wc->mod.fxs.lasttxhook[x]);						}					}				}			}		}	}	if (ints & 0x0f) {		wc->intcount++;		x = wc->intcount % 4;		if ((x < wc->cards) && (wc->cardflag & (1 << x))) {			if (wc->modtype[x] == MOD_TYPE_FXS) {				wcfxs_proslic_check_hook(wc, x);				if (!(wc->intcount & 0xfc))					wcfxs_proslic_recheck_sanity(wc, x);			} else if (wc->modtype[x] == MOD_TYPE_FXO) {				wcfxs_voicedaa_check_hook(wc, x);			}		}		if (!(wc->intcount % 10000)) {			/* Accept an alarm once per 10 seconds */			for (x=0;x<4;x++) 				if (wc->modtype[x] == MOD_TYPE_FXS) {					if (wc->mod.fxs.palarms[x])						wc->mod.fxs.palarms[x]--;				}		}		wcfxs_receiveprep(wc, ints);		wcfxs_transmitprep(wc, ints);	}#ifdef LINUX26	return IRQ_RETVAL(1);#endif			}static int wcfxs_voicedaa_insane(struct wcfxs *wc, int card){	int blah;	blah = wcfxs_getreg(wc, card, 2);	if (blah != 0x3)		return -2;	blah = wcfxs_getreg(wc, card, 11);	if (debug)		printk("VoiceDAA System: %02x\n", blah & 0xf);	return 0;}static int wcfxs_proslic_insane(struct wcfxs *wc, int card){	int blah,insane_report;	insane_report=0;	blah = wcfxs_getreg(wc, card, 0);	if (debug) 		printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf));#if	0	if ((blah & 0x30) >> 4) {		printk("ProSLIC on module %d is not a 3210.\n", card);		return -1;	}#endif	if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) {		/* SLIC not loaded */		return -1;	}	if ((blah & 0xf) < 3) {		printk("ProSLIC 3210 version %d is too old\n", blah & 0xf);		return -1;	}	blah = wcfxs_getreg(wc, card, 8);	if (blah != 0x2) {		printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah);		return -1;	} else if ( insane_report)		printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah);	blah = wcfxs_getreg(wc, card, 64);	if (blah != 0x0) {		printk("ProSLIC on module %d insane (2)\n", card);		return -1;	} else if ( insane_report)		printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah);	blah = wcfxs_getreg(wc, card, 11);	if (blah != 0x33) {		printk("ProSLIC on module %d insane (3)\n", card);		return -1;	} else if ( insane_report)		printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah);	/* Just be sure it's setup right. */	wcfxs_setreg(wc, card, 30, 0);	if (debug) 		printk("ProSLIC on module %d seems sane.\n", card);	return 0;}static int wcfxs_proslic_powerleak_test(struct wcfxs *wc, int card){	unsigned long origjiffies;	unsigned char vbat;	/* Turn off linefeed */	wcfxs_setreg(wc, card, 64, 0);	/* Power down */	wcfxs_setreg(wc, card, 14, 0x10);	/* Wait for one second */	origjiffies = jiffies;	while((vbat = wcfxs_getreg(wc, card, 82)) > 0x6) {		if ((jiffies - origjiffies) >= (HZ/2))			break;;	}	if (vbat < 0x06) {		printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card,		       376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ));		return -1;	} else if (debug) {		printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000);	}	return 0;}static int wcfxs_powerup_proslic(struct wcfxs *wc, int card, int fast){	unsigned char vbat;	unsigned long origjiffies;	int lim;	/* Set period of DC-DC converter to 1/64 khz */	wcfxs_setreg(wc, card, 92, 0xff /* was 0xff */);	/* Wait for VBat to powerup */	origjiffies = jiffies;	/* Disable powerdown */	wcfxs_setreg(wc, card, 14, 0);	/* If fast, don't bother checking anymore */	if (fast)		return 0;	while((vbat = wcfxs_getreg(wc, card, 82)) < 0xc0) {		/* Wait no more than 500ms */		if ((jiffies - origjiffies) > HZ/2) {			break;		}	}	if (vbat < 0xc0) {		printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM400P??\n",		       card, (int)(((jiffies - origjiffies) * 1000 / HZ)),			vbat * 375);		return -1;	} else if (debug) {		printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",		       card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));	}        /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */        /* If out of range, just set it to the default value     */        lim = (loopcurrent - 20) / 3;        if ( loopcurrent > 41 ) {                lim = 0;                if (debug)                        printk("Loop current out of range! Setting to default 20mA!\n");        }        else if (debug)                        printk("Loop current set to %dmA!\n",(lim*3)+20);        wcfxs_setreg(wc,card,LOOP_I_LIMIT,lim);	/* Engage DC-DC converter */	wcfxs_setreg(wc, card, 93, 0x19 /* was 0x19 */);#if 0	origjiffies = jiffies;	while(0x80 & wcfxs_getreg(wc, card, 93)) {		if ((jiffies - origjiffies) > 2 * HZ) {			printk("Timeout waiting for DC-DC calibration on module %d\n", card);			return -1;		}	}#if 0	/* Wait a full two seconds */	while((jiffies - origjiffies) < 2 * HZ);	/* Just check to be sure */	vbat = wcfxs_getreg(wc, card, 82);	printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",		       card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));#endif#endif	return 0;}static int wcfxs_proslic_manual_calibrate(struct wcfxs *wc, int card){	unsigned long origjiffies;	unsigned char i;	wcfxs_setreg(wc, card, 21, 0);//(0)  Disable all interupts in DR21	wcfxs_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21	wcfxs_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21	wcfxs_setreg(wc, card, 64, 0);//(0)	wcfxs_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration.	wcfxs_setreg(wc, card, 96, 0x47); //(0x47)	Calibrate common mode and differential DAC mode DAC + ILIM	origjiffies=jiffies;	while( wcfxs_getreg(wc,card,96)!=0 ){		if((jiffies-origjiffies)>80)			return -1;	}//Initialized DR 98 and 99 to get consistant results.// 98 and 99 are the results registers and the search should have same intial conditions./*******************************The following is the manual gain mismatch calibration****************************//*******************************This is also available as a function *******************************************/	// Delay 10ms	origjiffies=jiffies; 	while((jiffies-origjiffies)<1);	wcfxs_proslic_setreg_indirect(wc, card, 88,0);	wcfxs_proslic_setreg_indirect(wc,card,89,0);	wcfxs_proslic_setreg_indirect(wc,card,90,0);	wcfxs_proslic_setreg_indirect(wc,card,91,0);	wcfxs_proslic_setreg_indirect(wc,card,92,0);	wcfxs_proslic_setreg_indirect(wc,card,93,0);	wcfxs_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time	wcfxs_setreg(wc, card, 99,0x10);	for ( i=0x1f; i>0; i--)	{		wcfxs_setreg(wc, card, 98,i);		origjiffies=jiffies; 		while((jiffies-origjiffies)<4);		if((wcfxs_getreg(wc,card,88)) == 0)			break;	} // for	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;	/* 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;}#endifstatic void wait_just_a_bit(int foo)

⌨️ 快捷键说明

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