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

📄 wct1xxp.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
				__t1_set_reg(wc, 0x1b, 0x9a);	/* Set ESR */		__t1_set_reg(wc, 0x1b, 0x82);	/* TSCLKM only now */		/* Reset LIRST bit and reset elastic stores */		wc->span.flags |= ZT_FLAG_RUNNING;	}	spin_unlock_irqrestore(&wc->lock, flags);}static int t1xxp_framer_sanity_check(struct t1xxp *wc){	int res;	int chipid;	unsigned long flags;	int x;	/* Sanity check */	spin_lock_irqsave(&wc->lock, flags);	for (x=0x0;x<192;x++)		__t1_set_reg(wc, x, 0);	res = __t1_get_reg(wc, 0x0f);	res = __t1_get_reg(wc, 0x0f);	chipid = ((res & 0x80) >> 5) | ((res & 0x30) >> 4);	wc->ise1 = (res & 0x80) ? (1 << 4) : 0;	spin_unlock_irqrestore(&wc->lock, flags);	printk("Framer: %s, Revision: %d (%s)\n", chips[chipid], res & 0xf, wc->ise1 ? "E1" : "T1");	return 0;}static int t1xxp_framer_hard_reset(struct t1xxp *wc){	int x;	unsigned long flags;	spin_lock_irqsave(&wc->lock, flags);	/* Initialize all registers to 0 */	for (x=0x0;x<192;x++)		__t1_set_reg(wc, x, 0);	if (wc->ise1) {		/* Set LOTCMC (switch to RCLCK if TCLK fails) */		__t1_set_reg(wc, 0x1a, 0x04);			 	/* RSYNC is an input */		__t1_set_reg(wc, 0x10, 0x20);		/* Rx elastic store enabled, 2.048 Mhz (in theory) */		__t1_set_reg(wc, 0x11, 0x06);		/* TSYNC is an input, Tsis mode */		__t1_set_reg(wc, 0x12, 0x08);		/* Tx elastic store enabled, 2.048 Mhz (in theory) */		__t1_set_reg(wc, 0x1b, 0x82);			} else {		/* Full-on sync required for T1 */		__t1_set_reg(wc, 0x2b, 0x08);	 	/* RSYNC is an input */		__t1_set_reg(wc, 0x2c, 0x08);		/* Enable tx RBS bits */		__t1_set_reg(wc, 0x35, 0x10);		/* TSYNC is output */		__t1_set_reg(wc, 0x36, 0x04);		/* Tx and Rx elastic store enabled, 2.048 Mhz (in theory) */		__t1_set_reg(wc, 0x37, 0x9c);		/* Setup Loopup / Loopdown codes */		__t1_set_reg(wc, 0x12, 0x22);		__t1_set_reg(wc, 0x14, 0x80);		__t1_set_reg(wc, 0x15, 0x80);	}	spin_unlock_irqrestore(&wc->lock, flags);	return 0;}static int t1xxp_rbsbits(struct zt_chan *chan, int bits){	struct t1xxp *wc = chan->pvt;	unsigned long flags;	int b,o;	unsigned char mask;		/* Byte offset */	spin_lock_irqsave(&wc->lock, flags);	if (wc->ise1) {                if (chan->chanpos < 16) {                       mask = ((bits << 4) | wc->chans[chan->chanpos - 1 + 16].txsig);                        __t1_set_reg(wc, 0x40 + chan->chanpos, mask);                }		else if (chan->chanpos > 16) {			mask = (bits | (wc->chans[chan->chanpos - 1 - 16].txsig << 4));			__t1_set_reg(wc, 0x40 + chan->chanpos - 16, mask);		}		wc->chans[chan->chanpos - 1].txsig = bits;	} else {		b = (chan->chanpos - 1) / 8;		o = (chan->chanpos - 1) % 8;		mask = (1 << o);		if (bits & ZT_ABIT) {			/* Set A-bit */			wc->txsiga[b] |= mask;		} else {			/* Clear A-bit */			wc->txsiga[b] &= ~mask;		}		if (bits & ZT_BBIT) {			/* Set B-bit */			wc->txsigb[b] |= mask;		} else {			wc->txsigb[b] &= ~mask;		}		/* Output new values */		__t1_set_reg(wc, 0x70 + b, wc->txsiga[b]);		__t1_set_reg(wc, 0x73 + b, wc->txsigb[b]);		__t1_set_reg(wc, 0x76 + b, wc->txsiga[b]);		__t1_set_reg(wc, 0x79 + b, wc->txsigb[b]);	}	spin_unlock_irqrestore(&wc->lock, flags);	return 0;}static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data){	switch(cmd) {	default:		return -ENOTTY;	}}static int t1xxp_startup(struct zt_span *span){	struct t1xxp *wc = span->pvt;	int i,alreadyrunning = span->flags & ZT_FLAG_RUNNING;	/* initialize the start value for the entire chunk of last ec buffer */	for(i = 0; i < span->channels; i++)	{		memset(wc->ec_chunk1[i],			ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE);		memset(wc->ec_chunk2[i],			ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE);	}	/* Reset framer with proper parameters and start */	if (wc->ise1)		t1xxp_e1_framer_start(wc);	else		t1xxp_t1_framer_start(wc);	printk("Calling startup (flags is %d)\n", span->flags);	if (!alreadyrunning) {		/* Only if we're not already going */		t1xxp_enable_interrupts(wc);		t1xxp_start_dma(wc);		span->flags |= ZT_FLAG_RUNNING;	}	return 0;}static int t1xxp_shutdown(struct zt_span *span){	struct t1xxp *wc = span->pvt;	unsigned long flags;	spin_lock_irqsave(&wc->lock, flags);	__t1xxp_stop_dma(wc);	__t1xxp_disable_interrupts(wc);	span->flags &= ~ZT_FLAG_RUNNING;	spin_unlock_irqrestore(&wc->lock, flags);	t1xxp_framer_hard_reset(wc);	return 0;}static int t1xxp_maint(struct zt_span *span, int cmd){	struct t1xxp *wc = span->pvt;	int res = 0;	unsigned long flags;	spin_lock_irqsave(&wc->lock, flags);	if (wc->ise1) {		switch(cmd) {		case ZT_MAINT_NONE:			__t1_set_reg(wc,0xa8,0); /* no loops */			break;		case ZT_MAINT_LOCALLOOP:			__t1_set_reg(wc,0xa8,0x40); /* local loop */			break;		case ZT_MAINT_REMOTELOOP:			__t1_set_reg(wc,0xa8,0x80); /* remote loop */			break;		case ZT_MAINT_LOOPUP:		case ZT_MAINT_LOOPDOWN:		case ZT_MAINT_LOOPSTOP:			res = -ENOSYS;			break;		default:			printk("wct1xxp/E1: Unknown maint command: %d\n", cmd);			res = -EINVAL;			break;		}	} else {		switch(cmd) {	    case ZT_MAINT_NONE:			__t1_set_reg(wc,0x19,0); /* no local loop */			__t1_set_reg(wc,0x0a,0); /* no remote loop */			break;	    case ZT_MAINT_LOCALLOOP:			__t1_set_reg(wc,0x19,0x40); /* local loop */			__t1_set_reg(wc,0x0a,0); /* no remote loop */			break;	    case ZT_MAINT_REMOTELOOP:			__t1_set_reg(wc,0x1e,0); /* no local loop */			__t1_set_reg(wc,0x0a,0x40); /* remote loop */			break;	    case ZT_MAINT_LOOPUP:			__t1_set_reg(wc,0x30,2); /* send loopup code */			__t1_set_reg(wc,0x12,0x22); /* send loopup code */			__t1_set_reg(wc,0x13,0x80); /* send loopup code */			break;	    case ZT_MAINT_LOOPDOWN:			__t1_set_reg(wc,0x30,2); /* send loopdown code */			__t1_set_reg(wc,0x12,0x62); /* send loopdown code */			__t1_set_reg(wc,0x13,0x90); /* send loopdown code */			break;	    case ZT_MAINT_LOOPSTOP:			__t1_set_reg(wc,0x30,0);	/* stop sending loopup code */			break;	    default:			printk("wct1xxp/T1: Unknown maint command: %d\n", cmd);			res = -EINVAL;	   }	}	spin_unlock_irqrestore(&wc->lock, flags);	return res;}static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype){	struct t1xxp *wc = chan->pvt;	unsigned long flags;	int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING;	spin_lock_irqsave(&wc->lock, flags);	if (alreadyrunning && !wc->ise1)		__t1xxp_set_clear(wc);	spin_unlock_irqrestore(&wc->lock, flags);	return 0;}static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc){	struct t1xxp *wc = span->pvt;	span->lineconfig = lc->lineconfig;	span->txlevel = lc->lbo;	span->rxlevel = 0;	/* Do we want to SYNC on receive or not */	wc->sync = lc->sync;	/* If already running, apply changes immediately */	if (span->flags & ZT_FLAG_RUNNING)		return t1xxp_startup(span);	return 0;}static int t1xxp_software_init(struct t1xxp *wc){	int x;	/* Find position */	for (x=0;x<WC_MAX_CARDS;x++) {		if (!cards[x]) {			cards[x] = wc;			break;		}	}	if (x >= WC_MAX_CARDS)		return -1;	wc->num = x;	sprintf(wc->span.name, "WCT1/%d", wc->num);	sprintf(wc->span.desc, "%s Card %d", wc->variety, wc->num);	wc->span.spanconfig = t1xxp_spanconfig;	wc->span.chanconfig = t1xxp_chanconfig;	wc->span.startup = t1xxp_startup;	wc->span.shutdown = t1xxp_shutdown;	wc->span.rbsbits = t1xxp_rbsbits;	wc->span.maint = t1xxp_maint;	wc->span.open = t1xxp_open;	wc->span.close = t1xxp_close;	if (wc->ise1)		wc->span.channels = 31;	else		wc->span.channels = 24;	wc->span.chans = wc->chans;	wc->span.flags = ZT_FLAG_RBS;	wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;	wc->span.ioctl = t1xxp_ioctl;	wc->span.pvt = wc;	if (wc->ise1)		wc->span.deflaw = ZT_LAW_ALAW;	else		wc->span.deflaw = ZT_LAW_MULAW;	init_waitqueue_head(&wc->span.maintq);	for (x=0;x<wc->span.channels;x++) {		sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1);		wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | 				      ZT_SIG_FXSLS | ZT_SIG_FXSGS | 				      ZT_SIG_FXSKS | ZT_SIG_FXOLS | 				      ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF;		wc->chans[x].pvt = wc;		wc->chans[x].chanpos = x + 1;	}	if (zt_register(&wc->span, 0)) {		printk("Unable to register span with zaptel\n");		return -1;	}	return 0;}static inline void __handle_leds(struct t1xxp *wc){	int oldreg;	wc->blinktimer++;	if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) {		/* Red/Blue alarm */#ifdef FANCY_ALARM		if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {			wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0;			__control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);		}		if (wc->blinktimer == 0xf) {			wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1);			__control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);			wc->blinktimer = -1;			wc->alarmpos++;			if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0])))				wc->alarmpos = 0;		}#else		if (wc->blinktimer == 160) {			wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0;			__control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);		} else if (wc->blinktimer == 480) {			wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1);			__control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);			wc->blinktimer = 0;		}#endif	} else if (wc->span.alarms & ZT_ALARM_YELLOW) {		/* Yellow Alarm */		if (!(wc->blinktimer % 2)) 			wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0;		else			wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1;		__control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);	} else {		/* No Alarm */		oldreg = wc->ledtestreg;		if (wc->span.maintstat != ZT_MAINT_NONE)			wc->ledtestreg |= BIT_TEST;		else			wc->ledtestreg &= ~BIT_TEST;		if (wc->span.flags & ZT_FLAG_RUNNING)			wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1;		else			wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1);		if (oldreg != wc->ledtestreg)			__control_set_reg(wc, WC_LEDTEST, wc->ledtestreg);	}}static void t1xxp_transmitprep(struct t1xxp *wc, int ints){	volatile unsigned char *txbuf;	int x,y;	int pos;	if (ints & 0x04 /* 0x01 */) {		/* We just finished sending the first buffer, start filling it		   now */		txbuf = wc->writechunk;	} else {		/* Just finished sending second buffer, fill it now */		txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE;	}	zt_transmit(&wc->span);	for (x=0;x<wc->offset;x++)		txbuf[x] = wc->tempo[x];	for (y=0;y<ZT_CHUNKSIZE;y++) {		for (x=0;x<wc->span.channels;x++) {			pos = y * 32 + wc->chanmap[x] + wc->offset;			/* Put channel number as outgoing data */			if (pos < 32 * ZT_CHUNKSIZE)				txbuf[pos] = wc->chans[x].writechunk[y];			else				wc->tempo[pos - 32 * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y];		}	}}static void t1xxp_receiveprep(struct t1xxp *wc, int ints){	volatile unsigned char *rxbuf;	volatile unsigned int *canary;	int x;	int y;	unsigned int oldcan;	if (ints & 0x04) {		/* Just received first buffer */		rxbuf = wc->readchunk;		canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4);	} else {		rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32;		canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 32 - 4);	}	oldcan = *canary;	if (((oldcan & 0xffff0000) >> 16) != CANARY) {		/* Check top part */		if (debug) printk("Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16);		wc->span.irqmisses++;	} else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) {		if (debug) printk("Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff);		wc->span.irqmisses++;	}	for (y=0;y<ZT_CHUNKSIZE;y++) {		for (x=0;x<wc->span.channels;x++) {			/* XXX Optimize, remove * and + XXX */			/* Must map received channels into appropriate data */			wc->chans[x].readchunk[y] = 				rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)];		}		if (!wc->ise1) {			for (x=3;x<32;x+=4) {				if (rxbuf[32 * y + ((x + WC_OFFSET) & 0x1f)] == 0x7f) {					if (wc->offset != (x-3)) {						/* Resync */						control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1);						wc->clocktimeout = 100;#if 1						if (debug) printk("T1: Lost our place, resyncing\n");#endif					}				}			}		} else {			if (!wc->clocktimeout && !wc->span.alarms) {				if ((rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)] & 0x7f) != 0x1b) {					if (wc->miss) {						if (debug) printk("Double miss (%d, %d)...\n", wc->misslast, rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]);						control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1);						wc->clocktimeout = 100;					} else {						wc->miss = 1;						wc->misslast = rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)];					}				} else {					wc->miss = 0;				}			} else {				wc->miss = 0;

⌨️ 快捷键说明

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