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

📄 wcte11xp.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
}static void t1xxp_receiveprep(struct t1 *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->spantype != TYPE_E1) {			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, 0x06 | wc->sync | clockextra);						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, 0x06 | wc->sync | clockextra);						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;			}		} 	}	/* Store the next canary */	canary = (unsigned int *)(rxbuf + ZT_CHUNKSIZE * 32 - 4);	*canary = (wc->canary++) | (CANARY << 16);	for (x=0;x<wc->span.channels;x++) {		zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, 			wc->ec_chunk2[x]);		memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE);		memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE);	}	zt_receive(&wc->span);}static void __t1_check_alarms(struct t1 *wc){	unsigned char c,d;	int alarms;	int x,j;	if (!(wc->span.flags & ZT_FLAG_RUNNING))		return;	c = __t1_framer_in(wc, 0x4c);	if (wc->spanflags & FLAG_FALC12)		d = __t1_framer_in(wc, 0x4f);	else		d = __t1_framer_in(wc, 0x4d);	/* Assume no alarms */	alarms = 0;	/* And consider only carrier alarms */	wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN);	if (wc->spantype == 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 & FLAG_NMF)) {				__t1_framer_out(wc, 0x20, 0x9f | 0x20);	/* LIM0: Force RAI High */				wc->spanflags |= FLAG_NMF;				printk("NMF workaround on!\n");			}			__t1_framer_out(wc, 0x1e, 0xc3);	/* Reset to CRC4 mode */			__t1_framer_out(wc, 0x1c, 0xf2);	/* Force Resync */			__t1_framer_out(wc, 0x1c, 0xf0);	/* Force Resync */		} else if (!(c & 0x02)) {			if ((wc->spanflags & FLAG_NMF)) {				__t1_framer_out(wc, 0x20, 0x9f);	/* LIM0: Clear forced RAI */				wc->spanflags &= ~FLAG_NMF;				printk("NMF workaround off!\n");			}		}	} else {		/* Detect loopup code if we're not sending one */		if ((!wc->span.mainttimer) && (d & 0x08)) {			/* Loop-up code detected */			if ((wc->loopupcnt++ > 80)  && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) {				__t1_framer_out(wc, 0x36, 0x08);	/* LIM0: Disable any local loop */				__t1_framer_out(wc, 0x37, 0xf6 );	/* LIM1: Enable remote loop */				wc->span.maintstat = ZT_MAINT_REMOTELOOP;			}		} else			wc->loopupcnt = 0;		/* Same for loopdown code */		if ((!wc->span.mainttimer) && (d & 0x10)) {			/* Loop-down code detected */			if ((wc->loopdowncnt++ > 80)  && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) {				__t1_framer_out(wc, 0x36, 0x08);	/* LIM0: Disable any local loop */				__t1_framer_out(wc, 0x37, 0xf0 );	/* LIM1: Disable remote loop */				wc->span.maintstat = ZT_MAINT_NONE;			}		} else			wc->loopdowncnt = 0;	}	if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) {		for (x=0,j=0;x < wc->span.channels;x++)			if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) ||			    (wc->span.chans[x].flags & ZT_FLAG_NETDEV))				j++;		if (!j)			alarms |= ZT_ALARM_NOTOPEN;	}	if (c & 0xa0) {		if (wc->alarmcount >= alarmdebounce) 			alarms |= ZT_ALARM_RED;		else			wc->alarmcount++;	} else		wc->alarmcount = 0;	if (c & 0x4)		alarms |= ZT_ALARM_BLUE;	if (((!wc->span.alarms) && alarms) || 	    (wc->span.alarms && (!alarms))) 		wc->checktiming = 1;	/* Keep track of recovering */	if ((!alarms) && wc->span.alarms) 		wc->alarmtimer = ZT_ALARMSETTLE_TIME;	if (wc->alarmtimer)		alarms |= ZT_ALARM_RECOVER;	/* If receiving alarms, go into Yellow alarm state */	if (alarms && !(wc->spanflags & FLAG_SENDINGYELLOW)) {		unsigned char fmr4;#if 1		printk("wcte1xxp: Setting yellow alarm\n");#endif		/* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */		fmr4 = __t1_framer_in(wc, 0x20);		__t1_framer_out(wc, 0x20, fmr4 | 0x20);		wc->spanflags |= FLAG_SENDINGYELLOW;	} else if ((!alarms) && (wc->spanflags & FLAG_SENDINGYELLOW)) {		unsigned char fmr4;#if 1		printk("wcte1xxp: Clearing yellow alarm\n");#endif		/* We manually do yellow alarm to handle RECOVER  */		fmr4 = __t1_framer_in(wc, 0x20);		__t1_framer_out(wc, 0x20, fmr4 & ~0x20);		wc->spanflags &= ~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->span.mainttimer || wc->span.maintstat) 		alarms |= ZT_ALARM_LOOPBACK;	wc->span.alarms = alarms;	zt_alarm_notify(&wc->span);}static void __t1_do_counters(struct t1 *wc){	if (wc->alarmtimer) {		if (!--wc->alarmtimer) {			wc->span.alarms &= ~(ZT_ALARM_RECOVER);			zt_alarm_notify(&wc->span);		}	}}#ifdef LINUX26static irqreturn_t t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)#elsestatic void t1xxp_interrupt(int irq, void *dev_id, struct pt_regs *regs)#endif{	struct t1 *wc = dev_id;	unsigned char ints;	unsigned long flags;	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 (!wc->intcount) {		if (debug) printk("Got interrupt: 0x%04x\n", ints);	}	wc->intcount++;	if (wc->clocktimeout && !--wc->clocktimeout) 		control_set_reg(wc, WC_CLOCK, 0x04 | wc->sync | clockextra);	if (ints & 0x0f) {		t1xxp_receiveprep(wc, ints);		t1xxp_transmitprep(wc, ints);	}	spin_lock_irqsave(&wc->lock, flags);#if 1	__handle_leds(wc);#endif	/* Count down timers */	__t1_do_counters(wc);	/* Do some things that we don't have to do very often */	x = wc->intcount & 15 /* 63 */;	switch(x) {	case 0:	case 1:		break;	case 2:		__t1_check_sigbits(wc);		break;	case 4:		/* Check alarms 1/4 as frequently */		if (!(wc->intcount & 0x30))			__t1_check_alarms(wc);		break;	}		spin_unlock_irqrestore(&wc->lock, flags);	if (ints & 0x10) 		printk("PCI Master abort\n");	if (ints & 0x20)		printk("PCI Target abort\n");#ifdef LINUX26	return IRQ_RETVAL(1);#endif		}static int t1xxp_hardware_init(struct t1 *wc){	unsigned int falcver;	unsigned int x;	/* Hardware PCI stuff */	/* Reset chip and registers */	outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL);	/* Set all outputs to 0 */	outb(0x00, wc->ioaddr + WC_AUXD);	/* Set all to outputs except AUX1 (TDO). */	outb(0xfd, wc->ioaddr + WC_AUXC);	/* Configure the serial port: double clock, 20ns width, no inversion,	   MSB first */	outb(0xc8, wc->ioaddr + WC_SERC);	/* Internally delay FSC by one */	outb(0x01, wc->ioaddr + WC_FSCDELAY);	/* Back to normal, with automatic DMA wrap around */	outb(DELAY | 0x01, wc->ioaddr + WC_CNTL);		/* Make sure serial port and DMA are out of reset */	outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL);		/* Setup DMA Addresses */	/* Start at writedma */	outl(wc->writedma,                    wc->ioaddr + WC_DMAWS);		/* Write start */	/* First frame */	outl(wc->writedma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI);		/* Middle (interrupt) */	/* Second frame */	outl(wc->writedma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE);			/* End */		outl(wc->readdma,                    	 wc->ioaddr + WC_DMARS);	/* Read start */	/* First frame */	outl(wc->readdma + ZT_CHUNKSIZE * 32 - 4, 	 wc->ioaddr + WC_DMARI);	/* Middle (interrupt) */	/* Second frame */	outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE);	/* End */		if (debug) printk("Setting up DMA (write/read = %08lx/%08lx)\n", (long)wc->writedma, (long)wc->readdma);	if (t1e1override > -1) {		if (t1e1override)			wc->spantype = TYPE_E1;		else			wc->spantype = TYPE_T1;	} else {		if (control_get_reg(wc, WC_CLOCK) & 0x20)			wc->spantype = TYPE_T1;		else			wc->spantype = TYPE_E1;	}	/* Check out the controller */	if (debug); printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION));	control_set_reg(wc, WC_LEDTEST, 0x00);	if (wc->spantype == TYPE_E1)		wc->chanmap = chanmap_e1;	else		wc->chanmap = chanmap_t1;	/* Setup clock appropriately */	control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra);	wc->clocktimeout = 100;	/* Perform register test on FALC */		for (x=0;x<256;x++) {		t1_framer_out(wc, 0x14, x);		if ((falcver = t1_framer_in(wc, 0x14)) != x) 			printk("Wrote '%x' but read '%x'\n", x, falcver);	}		t1_framer_out(wc, 0x4a, 0xaa);	falcver = t1_framer_in(wc ,0x4a);	printk("FALC version: %08x\n", falcver);	if (!falcver)		wc->spanflags |= FLAG_FALC12;		start_alarm(wc);	return 0;}static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){	int res;	struct t1 *wc;	unsigned int *canary;		if (pci_enable_device(pdev)) {		res = -EIO;	} else {		wc = kmalloc(sizeof(struct t1), GFP_KERNEL);		if (wc) {			memset(wc, 0x0, sizeof(struct t1));			spin_lock_init(&wc->lock);			wc->ioaddr = pci_resource_start(pdev, 0);			wc->dev = pdev;			wc->offset = 28;	/* And you thought 42 was the answer */			wc->writechunk = 				/* 32 channels, Double-buffer, Read/Write */				(unsigned char *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma);			if (!wc->writechunk) {				printk("wcte11xp: Unable to allocate DMA-able memory\n");				return -ENOMEM;			}			/* Read is after the whole write piece (in bytes) */			wc->readchunk = wc->writechunk + ZT_CHUNKSIZE * 32 * 2;			/* Same thing...  */			wc->readdma = wc->writedma + ZT_CHUNKSIZE * 32 * 2;			/* Initialize Write/Buffers to all blank data */			memset((void *)wc->writechunk,0x00,ZT_MAX_CHUNKSIZE * 2 * 2 * 32);			/* Initialize canary */			canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4);			*canary = (CANARY << 16) | (0xffff);			/* Enable bus mastering */			pci_set_master(pdev);			/* Keep track of which device we are */			pci_set_drvdata(pdev, wc);			if (request_irq(pdev->irq, t1xxp_interrupt, SA_INTERRUPT | SA_SHIRQ, "t1xxp", wc)) {				printk("t1xxp: Unable to request IRQ %d\n", pdev->irq);				kfree(wc);				return -EIO;			}			/* Initialize hardware */			t1xxp_hardware_init(wc);			/* We now know which version of card we have */			wc->variety = "Digium Wildcard TE110P T1/E1";			/* Misc. software stuff */			t1xxp_software_init(wc);			printk("Found a Wildcard: %s\n", wc->variety);			res = 0;		} else			res = -ENOMEM;	}	return res;}static void t1xxp_stop_stuff(struct t1 *wc){	/* Kill clock */	control_set_reg(wc, WC_CLOCK, 0);	/* Turn off LED's */	control_set_reg(wc, WC_LEDTEST, 0);}static void __devexit t1xxp_remove_one(struct pci_dev *pdev){	struct t1 *wc = pci_get_drvdata(pdev);	if (wc) {		/* Stop any DMA */		__t1xxp_stop_dma(wc);		/* In case hardware is still there */		__t1xxp_disable_interrupts(wc);				t1xxp_stop_stuff(wc);		/* Immediately free resources */		pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma);		free_irq(pdev->irq, wc);		/* Reset PCI chip and registers */		outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL);		/* Release span, possibly delayed */		if (!wc->usecount)			t1xxp_release(wc);		else			wc->dead = 1;	}}static struct pci_device_id t1xxp_pci_tbl[] = {	{ 0xe159, 0x0001, 0x79fe, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" },	{ 0 }};MODULE_DEVICE_TABLE(pci,t1xxp_pci_tbl);static struct pci_driver t1xxp_driver = {	name: 	"t1xxp",	probe: 	t1xxp_init_one,#ifdef LINUX26	remove:	__devexit_p(t1xxp_remove_one),#else	remove:	t1xxp_remove_one,#endif	suspend: NULL,	resume:	NULL,	id_table: t1xxp_pci_tbl,};static int __init t1xxp_init(void){	int res;	res = pci_module_init(&t1xxp_driver);	if (res)		return -ENODEV;	return 0;}static void __exit t1xxp_cleanup(void){	pci_unregister_driver(&t1xxp_driver);}#ifdef LINUX26module_param(alarmdebounce, int, 0600);module_param(loopback, int, 0600);module_param(t1e1override, int, 0600);module_param(clockextra, int, 0600);module_param(debug, int, 0600);#elseMODULE_PARM(alarmdebounce, "i");MODULE_PARM(loopback, "i");MODULE_PARM(t1e1override, "i");MODULE_PARM(clockextra, "i");MODULE_PARM(debug, "i");#endifMODULE_DESCRIPTION("Wildcard T100P/E100P Zaptel Driver");MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifmodule_init(t1xxp_init);module_exit(t1xxp_cleanup);

⌨️ 快捷键说明

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