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

📄 wct4xxp.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Start DMA, enabling DMA interrupts on read only */		wc->dmactrl = 0xc0000003 | (1 << 29);		if (noburst)			wc->dmactrl |= (1 << 26);		__t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);	}	spin_unlock_irqrestore(&wc->reglock, flags);	if (wc->syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno);	if (wc->syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno);	if (wc->syncs[2] == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno);	if (wc->syncs[3] == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno);	return 0;}static inline void e1_check(struct t4 *wc, int span, int val){	if ((wc->spans[span].channels > 24) &&	    (wc->spans[span].flags & ZT_FLAG_RUNNING) &&	    !(wc->spans[span].alarms) &&	    (!wc->e1recover))   {		if (val != 0x1b) {			wc->e1check[span]++;		} else			wc->e1check[span] = 0;		if (wc->e1check[span] > 100) {			/* Wait 1000 ms */			wc->e1recover = 1000 * 8;			memset(wc->e1check, 0, sizeof(wc->e1check));			if (debug)				printk("Detected loss of E1 alignment on span %d!\n", span);			t4_reset_dma(wc);		}	}}static void t4_receiveprep(struct t4 *wc, int irq){	volatile unsigned int *readchunk;	int dbl = 0;	int x,y,z;	unsigned int tmp;	int offset=0;	if (!wc->t1e1)		offset = 4;	if (irq & 1) {		/* First part */		readchunk = wc->readchunk;		if (!wc->last0) 			dbl = 1;		wc->last0 = 0;	} else {		readchunk = wc->readchunk + ZT_CHUNKSIZE * 32;		if (wc->last0) 			dbl = 1;		wc->last0 = 1;	}	if (dbl) {		for (x=0;x<4;x++)			wc->spans[x].irqmisses++;		if (debug)			printk("TE410P: Double/missed interrupt detected\n");	}	for (x=0;x<ZT_CHUNKSIZE;x++) {		for (z=0;z<24;z++) {			/* All T1/E1 channels */			tmp = readchunk[z+1+offset];			wc->spans[3].chans[z].readchunk[x] = tmp & 0xff;			wc->spans[2].chans[z].readchunk[x] = (tmp & 0xff00) >> 8;			wc->spans[1].chans[z].readchunk[x] = (tmp & 0xff0000) >> 16;			wc->spans[0].chans[z].readchunk[x] = tmp >> 24;		}		if (wc->t1e1) {			if (wc->e1recover > 0)				wc->e1recover--;			tmp = readchunk[0];			e1_check(wc, 3, (tmp & 0x7f));			e1_check(wc, 2, (tmp & 0x7f00) >> 8);			e1_check(wc, 1, (tmp & 0x7f0000) >> 16);			e1_check(wc, 0, (tmp & 0x7f000000) >> 24);			for (z=24;z<31;z++) {				/* Only E1 channels now */				tmp = readchunk[z+1];				if (wc->spans[3].channels > 24)					wc->spans[3].chans[z].readchunk[x] = tmp & 0xff;				if (wc->spans[2].channels > 24)					wc->spans[2].chans[z].readchunk[x] = (tmp & 0xff00) >> 8;				if (wc->spans[1].channels > 24)					wc->spans[1].chans[z].readchunk[x] = (tmp & 0xff0000) >> 16;				if (wc->spans[0].channels > 24)					wc->spans[0].chans[z].readchunk[x] = tmp >> 24;			}		}		/* Advance pointer by 4 TDM frame lengths */		readchunk += 32;	}	for (x=0;x<4;x++) {		if (wc->spans[x].flags & ZT_FLAG_RUNNING) {			for (y=0;y<wc->spans[x].channels;y++) {				/* Echo cancel double buffered data */				zt_ec_chunk(&wc->spans[x].chans[y], 				    wc->spans[x].chans[y].readchunk, 					wc->ec_chunk2[x][y]);				memcpy(wc->ec_chunk2[x][y],wc->ec_chunk1[x][y],					ZT_CHUNKSIZE);				memcpy(wc->ec_chunk1[x][y],					wc->spans[x].chans[y].writechunk,						ZT_CHUNKSIZE);			}			zt_receive(&wc->spans[x]);		}	}}static void t4_transmitprep(struct t4 *wc, int irq){	volatile unsigned int *writechunk;	int x,y,z;	unsigned int tmp;	int offset=0;	if (!wc->t1e1)		offset = 4;	if (irq & 1) {		/* First part */		writechunk = wc->writechunk + 1;	} else {		writechunk = wc->writechunk + ZT_CHUNKSIZE * 32 + 1;	}	for (y=0;y<4;y++) {		if (wc->spans[y].flags & ZT_FLAG_RUNNING) 			zt_transmit(&wc->spans[y]);	}	for (x=0;x<ZT_CHUNKSIZE;x++) {		/* Once per chunk */		for (z=0;z<24;z++) {			/* All T1/E1 channels */			tmp = (wc->spans[3].chans[z].writechunk[x]) | 				  (wc->spans[2].chans[z].writechunk[x] << 8) |				  (wc->spans[1].chans[z].writechunk[x] << 16) |				  (wc->spans[0].chans[z].writechunk[x] << 24);			writechunk[z+offset] = tmp;		}		if (wc->t1e1) {			for (z=24;z<31;z++) {				/* Only E1 channels now */				tmp = 0;				if (wc->spans[3].channels > 24)					tmp |= wc->spans[3].chans[z].writechunk[x];				if (wc->spans[2].channels > 24)					tmp |= (wc->spans[2].chans[z].writechunk[x] << 8);				if (wc->spans[1].channels > 24)					tmp |= (wc->spans[1].chans[z].writechunk[x] << 16);				if (wc->spans[0].channels > 24)					tmp |= (wc->spans[0].chans[z].writechunk[x] << 24);				writechunk[z] = tmp;			}		}		/* Advance pointer by 4 TDM frame lengths */		writechunk += 32;	}}static void __t4_check_sigbits(struct t4 *wc, int span){	int a,i,rxs;	if (!(wc->spans[span].flags & ZT_FLAG_RUNNING))		return;	if (wc->spantype[span] == TYPE_E1) {		for (i = 0; i < 15; i++) {			a = __t4_framer_in(wc, span, 0x71 + i);			/* Get high channel in low bits */			rxs = (a & 0xf);			if (!(wc->spans[span].chans[i+16].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i+16].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i+16], rxs);			}			rxs = (a >> 4) & 0xf;			if (!(wc->spans[span].chans[i].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i], rxs);			}		}	} else if (wc->spans[span].lineconfig & ZT_CONFIG_D4) {		for (i = 0; i < 24; i+=4) {			a = __t4_framer_in(wc, span, 0x70 + (i>>2));			/* Get high channel in low bits */			rxs = (a & 0x3) << 2;			if (!(wc->spans[span].chans[i+3].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i+3].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i+3], rxs);			}			rxs = (a & 0xc);			if (!(wc->spans[span].chans[i+2].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i+2].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i+2], rxs);			}			rxs = (a >> 2) & 0xc;			if (!(wc->spans[span].chans[i+1].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i+1].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i+1], rxs);			}			rxs = (a >> 4) & 0xc;			if (!(wc->spans[span].chans[i].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i], rxs);			}		}	} else {		for (i = 0; i < 24; i+=2) {			a = __t4_framer_in(wc, span, 0x70 + (i>>1));			/* Get high channel in low bits */			rxs = (a & 0xf);			if (!(wc->spans[span].chans[i+1].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i+1].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i+1], rxs);			}			rxs = (a >> 4) & 0xf;			if (!(wc->spans[span].chans[i].sig & ZT_SIG_CLEAR)) {				if (wc->spans[span].chans[i].rxsig != rxs)					zt_rbsbits(&wc->spans[span].chans[i], rxs);			}		}	}}static void __t4_do_counters(struct t4 *wc){	int span;	for (span=0;span<4;span++) {		if (wc->alarmtimer[span]) {			if (!--wc->alarmtimer[span]) {				wc->spans[span].alarms &= ~(ZT_ALARM_RECOVER);				zt_alarm_notify(&wc->spans[span]);			}		}	}}static void __t4_check_alarms(struct t4 *wc, int span){	unsigned char c,d;	int alarms;	int x,j;	if (!(wc->spans[span].flags & ZT_FLAG_RUNNING))		return;	c = __t4_framer_in(wc, span, 0x4c);	d = __t4_framer_in(wc, span, 0x4d);	/* Assume no alarms */	alarms = 0;	/* And consider only carrier alarms */	wc->spans[span].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN);	if (wc->spantype[span] == TYPE_E1) {		if (c & 0x04) {			/* No multiframe found, force RAI high after 400ms only if			   we haven't found a multiframe since last loss			   of frame */			if (!(wc->spanflags[span] & FLAG_NMF)) {				__t4_framer_out(wc, span, 0x20, 0x9f | 0x20);	/* LIM0: Force RAI High */				wc->spanflags[span] |= FLAG_NMF;				printk("NMF workaround on!\n");			}			__t4_framer_out(wc, span, 0x1e, 0xc3);	/* Reset to CRC4 mode */			__t4_framer_out(wc, span, 0x1c, 0xf2);	/* Force Resync */			__t4_framer_out(wc, span, 0x1c, 0xf0);	/* Force Resync */		} else if (!(c & 0x02)) {			if ((wc->spanflags[span] & FLAG_NMF)) {				__t4_framer_out(wc, span, 0x20, 0x9f);	/* LIM0: Clear forced RAI */				wc->spanflags[span] &= ~FLAG_NMF;				printk("NMF workaround off!\n");			}		}	} else {		/* Detect loopup code if we're not sending one */		if ((!wc->spans[span].mainttimer) && (d & 0x08)) {			/* Loop-up code detected */			if ((wc->loopupcnt[span]++ > 80)  && (wc->spans[span].maintstat != ZT_MAINT_REMOTELOOP)) {				__t4_framer_out(wc, span, 0x36, 0x08);	/* LIM0: Disable any local loop */				__t4_framer_out(wc, span, 0x37, 0xf6 );	/* LIM1: Enable remote loop */				wc->spans[span].maintstat = ZT_MAINT_REMOTELOOP;			}		} else			wc->loopupcnt[span] = 0;		/* Same for loopdown code */		if ((!wc->spans[span].mainttimer) && (d & 0x10)) {			/* Loop-down code detected */			if ((wc->loopdowncnt[span]++ > 80)  && (wc->spans[span].maintstat == ZT_MAINT_REMOTELOOP)) {				__t4_framer_out(wc, span, 0x36, 0x08);	/* LIM0: Disable any local loop */				__t4_framer_out(wc, span, 0x37, 0xf0 );	/* LIM1: Disable remote loop */				wc->spans[span].maintstat = ZT_MAINT_NONE;			}		} else			wc->loopdowncnt[span] = 0;	}	if (wc->spans[span].lineconfig & ZT_CONFIG_NOTOPEN) {		for (x=0,j=0;x < wc->spans[span].channels;x++)			if ((wc->spans[span].chans[x].flags & ZT_FLAG_OPEN) ||			    (wc->spans[span].chans[x].flags & ZT_FLAG_NETDEV))				j++;		if (!j)			alarms |= ZT_ALARM_NOTOPEN;	}	if (c & 0xa0) {		if (wc->alarmcount[span] >= alarmdebounce) 			alarms |= ZT_ALARM_RED;		else			wc->alarmcount[span]++;	} else		wc->alarmcount[span] = 0;	if (c & 0x4)		alarms |= ZT_ALARM_BLUE;	if (((!wc->spans[span].alarms) && alarms) || 	    (wc->spans[span].alarms && (!alarms))) 		wc->checktiming = 1;	/* Keep track of recovering */	if ((!alarms) && wc->spans[span].alarms) 		wc->alarmtimer[span] = ZT_ALARMSETTLE_TIME;	if (wc->alarmtimer[span])		alarms |= ZT_ALARM_RECOVER;	/* If receiving alarms, go into Yellow alarm state */	if (alarms && !(wc->spanflags[span] & FLAG_SENDINGYELLOW)) {		unsigned char fmr4;#if 1		printk("wct4xxp: Setting yellow alarm on span %d\n", span + 1);#endif		/* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */		fmr4 = __t4_framer_in(wc, span, 0x20);		__t4_framer_out(wc, span, 0x20, fmr4 | 0x20);		wc->spanflags[span] |= FLAG_SENDINGYELLOW;	} else if ((!alarms) && (wc->spanflags[span] & FLAG_SENDINGYELLOW)) {		unsigned char fmr4;#if 1		printk("wct4xxp: Clearing yellow alarm on span %d\n", span + 1);#endif		/* We manually do yellow alarm to handle RECOVER  */		fmr4 = __t4_framer_in(wc, span, 0x20);		__t4_framer_out(wc, span, 0x20, fmr4 & ~0x20);		wc->spanflags[span] &= ~FLAG_SENDINGYELLOW;	}	/* Re-check the timing source when we enter/leave alarm, not withstanding	   yellow alarm */	if (c & 0x10)		alarms |= ZT_ALARM_YELLOW;	if (wc->spans[span].mainttimer || wc->spans[span].maintstat) 		alarms |= ZT_ALARM_LOOPBACK;	wc->spans[span].alarms = alarms;	zt_alarm_notify(&wc->spans[span]);}static inline void __handle_leds(struct t4 *wc){	int x;	wc->blinktimer++;	for (x=0;x<4;x++) {		if (wc->spans[x].flags & ZT_FLAG_RUNNING) {			if (wc->spans[x].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) {#ifdef FANCY_ALARM				if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {					__t4_set_led(wc, x, WC_RED);				}				if (wc->blinktimer == 0xf) {					__t4_set_led(wc, x, WC_OFF);				}#else				if (wc->blinktimer == 160) {					__t4_set_led(wc, x, WC_RED);				} else if (wc->blinktimer == 480) {					__t4_set_led(wc, x, WC_OFF);				}#endif			} else if (wc->spans[x].alarms & ZT_ALARM_YELLOW) {				/* Yellow Alarm */				__t4_set_led(wc, x, WC_YELLOW);			} else if (wc->spans[x].mainttimer || wc->spans[x].maintstat) {#ifdef FANCY_ALARM				if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {					__t4_set_led(wc, x, WC_GREEN);				}				if (wc->blinktimer == 0xf) {					__t4_set_led(wc, x, WC_OFF);				}#else				if (wc->blinktimer == 160) {					__t4_set_led(wc, x, WC_GREEN);				} else if (wc->blinktimer == 480) {					__t4_set_led(wc, x, WC_OFF);				}#endif			} else {				/* No Alarm */				__t4_set_led(wc, x, WC_GREEN);			}		}	else				__t4_set_led(wc, x, WC_OFF);	}#ifdef FANCY_ALARM	if (wc->blinktimer == 0xf) {		wc->blinktimer = -1;		wc->alarmpos++;		if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0])))			wc->alarmpos = 0;	}#else	if (wc->blinktimer == 480)		wc->blinktimer = 0;#endif}#ifdef LINUX26static irqreturn_t t4_interrupt(int irq, void *dev_id, struct pt_regs *regs)#elsestatic void t4_interrupt(int irq, void *dev_id, struct pt_regs *regs)#endif{	struct t4 *wc = dev_id;	unsigned long flags;	int x;		unsigned int status;#if 0	unsigned int status2;#endif#if 0	if (wc->intcount < 20)		printk("Pre-interrupt\n");#endif

⌨️ 快捷键说明

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