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

📄 wcfxs.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 5 页
字号:
{	volatile unsigned int *readchunk;	int x;	if (ints & 0x08)		readchunk = wc->readchunk + ZT_CHUNKSIZE;	else		/* Read is at interrupt address.  Valid data is available at normal offset */		readchunk = wc->readchunk;	for (x=0;x<ZT_CHUNKSIZE;x++) {		if (wc->cardflag & (1 << 3))			wc->chans[3].readchunk[x] = (readchunk[x] >> 24) & 0xff;		if (wc->cardflag & (1 << 2))			wc->chans[2].readchunk[x] = (readchunk[x] >> 16) & 0xff;		if (wc->cardflag & (1 << 1))			wc->chans[1].readchunk[x] = (readchunk[x] >> 8) & 0xff;		if (wc->cardflag & (1 << 0))			wc->chans[0].readchunk[x] = (readchunk[x]) & 0xff;	}#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 :( */	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);	}	zt_receive(&wc->span);}static void wcfxs_stop_dma(struct wcfxs *wc);static void wcfxs_reset_tdm(struct wcfxs *wc);static void wcfxs_restart_dma(struct wcfxs *wc);static inline void __write_8bits(struct wcfxs *wc, unsigned char bits){	/* Drop chip select */	int x;	wc->ios |= BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	wc->ios &= ~BIT_CS;	outb(wc->ios, wc->ioaddr + WC_AUXD);	for (x=0;x<8;x++) {		/* Send out each bit, MSB first, drop SCLK as we do so */		if (bits & 0x80)			wc->ios |= BIT_SDI;		else			wc->ios &= ~BIT_SDI;		wc->ios &= ~BIT_SCLK;		outb(wc->ios, wc->ioaddr + WC_AUXD);		/* Now raise SCLK high again and repeat */		wc->ios |= BIT_SCLK;		outb(wc->ios, wc->ioaddr + WC_AUXD);		bits <<= 1;	}	/* Finally raise CS back high again */	wc->ios |= BIT_CS;	outb(wc->ios, wc->ioaddr + WC_AUXD);	}static inline void __reset_spi(struct wcfxs *wc){	/* Drop chip select and clock once and raise and clock once */	wc->ios |= BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	wc->ios &= ~BIT_CS;	outb(wc->ios, wc->ioaddr + WC_AUXD);	wc->ios |= BIT_SDI;	wc->ios &= ~BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	/* Now raise SCLK high again and repeat */	wc->ios |= BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	/* Finally raise CS back high again */	wc->ios |= BIT_CS;	outb(wc->ios, wc->ioaddr + WC_AUXD);	/* Clock again */	wc->ios &= ~BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	/* Now raise SCLK high again and repeat */	wc->ios |= BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	}static inline unsigned char __read_8bits(struct wcfxs *wc){	unsigned char res=0, c;	int x;	wc->ios |= BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	/* Drop chip select */	wc->ios &= ~BIT_CS;	outb(wc->ios, wc->ioaddr + WC_AUXD);	for (x=0;x<8;x++) {		res <<= 1;		/* Get SCLK */		wc->ios &= ~BIT_SCLK;		outb(wc->ios, wc->ioaddr + WC_AUXD);		/* Read back the value */		c = inb(wc->ioaddr + WC_AUXR);		if (c & BIT_SDO)			res |= 1;		/* Now raise SCLK high again */		wc->ios |= BIT_SCLK;		outb(wc->ios, wc->ioaddr + WC_AUXD);	}	/* Finally raise CS back high again */	wc->ios |= BIT_CS;	outb(wc->ios, wc->ioaddr + WC_AUXD);	wc->ios &= ~BIT_SCLK;	outb(wc->ios, wc->ioaddr + WC_AUXD);	/* And return our result */	return res;}static void __wcfxs_setcreg(struct wcfxs *wc, unsigned char reg, unsigned char val){	outb(val, wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));}static unsigned char __wcfxs_getcreg(struct wcfxs *wc, unsigned char reg){	return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2));}static inline void __wcfxs_setcard(struct wcfxs *wc, int card){	if (wc->curcard != card) {		__wcfxs_setcreg(wc, WC_CS, (1 << card));		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 {		__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 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 {		__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 int wcfxs_proslic_setreg_indirect(struct wcfxs *wc, int card, unsigned char address, unsigned short data){	unsigned long flags;	int res = -1;	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;	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 )		{			 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;	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 * 4);			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);					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);					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		if (abs(b) < BATT_THRESH) {		wc->mod.fxo.nobatttimer[card]++;#if 0		if (wc->mod.fxo.battery[card])			printk("Battery loss: %d (%d debounce)\n", b, wc->mod.fxo.battdebounce[card]);#endif		if (wc->mod.fxo.battery[card] && !wc->mod.fxo.battdebounce[card]) {			if (debug)				printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1);			wc->mod.fxo.battery[card] =  0;#ifdef	JAPAN			if ((!wc->ohdebounce) && wc->offhook) {				zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);				if (debug)					printk("Signalled On Hook\n");#ifdef	ZERO_BATT_RING				wc->onhook++;#endif			}#else			zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);#endif			wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE;		} else if (!wc->mod.fxo.battery[card])			wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE;	} else if (abs(b) > BATT_THRESH) {		if (!wc->mod.fxo.battery[card] && !wc->mod.fxo.battdebounce[card]) {			if (debug)				printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, 					(b < 0) ? "-" : "+");			    #ifdef	ZERO_BATT_RING			if (wc->onhook) {				wc->onhook = 0;				zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);				if (debug)					printk("Signalled Off Hook\n");			}#else			zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);#endif			wc->mod.fxo.battery[card] = 1;			wc->mod.fxo.nobatttimer[card] = 0;			wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE;		} else if (wc->mod.fxo.battery[card])			wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE;		if (wc->mod.fxo.lastpol[card] >= 0) {		    if (b < 0) {			wc->mod.fxo.lastpol[card] = -1;			wc->mod.fxo.polaritydebounce[card] = POLARITY_DEBOUNCE;		    }		} 		if (wc->mod.fxo.lastpol[card] <= 0) {		    if (b > 0) {			wc->mod.fxo.lastpol[card] = 1;			wc->mod.fxo.polaritydebounce[card] = POLARITY_DEBOUNCE;		    }		}	} else {		/* It's something else... */		wc->mod.fxo.battdebounce[card] = BATT_DEBOUNCE;	}	if (wc->mod.fxo.battdebounce[card])		wc->mod.fxo.battdebounce[card]--;	if (wc->mod.fxo.polaritydebounce[card]) {	        wc->mod.fxo.polaritydebounce[card]--;		if (wc->mod.fxo.polaritydebounce[card] < 1) {		    if (wc->mod.fxo.lastpol[card] != wc->mod.fxo.polarity[card]) {			if (debug)				printk("%lu Polarity reversed (%d -> %d)\n", jiffies, 			       wc->mod.fxo.polarity[card], 			       wc->mod.fxo.lastpol[card]);			if (wc->mod.fxo.polarity[card])			    zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY);			wc->mod.fxo.polarity[card] = wc->mod.fxo.lastpol[card];		    }		}	}}

⌨️ 快捷键说明

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