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

📄 base.c

📁 PCI base driver source code
💻 C
📖 第 1 页 / 共 5 页
字号:
		t4_hdlc_xmit_fifo(wc, span, ts);
}

static int t4_maint(struct zt_span *span, int cmd)
{
	struct t4_span *ts = span->pvt;
	struct t4 *wc = ts->owner;

	if (ts->spantype == TYPE_E1) {
		switch(cmd) {
		case ZT_MAINT_NONE:
			printk("XXX Turn off local and remote loops E1 XXX\n");
			break;
		case ZT_MAINT_LOCALLOOP:
			printk("XXX Turn on local loopback E1 XXX\n");
			break;
		case ZT_MAINT_REMOTELOOP:
			printk("XXX Turn on remote loopback E1 XXX\n");
			break;
		case ZT_MAINT_LOOPUP:
			printk("XXX Send loopup code E1 XXX\n");
			break;
		case ZT_MAINT_LOOPDOWN:
			printk("XXX Send loopdown code E1 XXX\n");
			break;
		case ZT_MAINT_LOOPSTOP:
			printk("XXX Stop sending loop codes E1 XXX\n");
			break;
		default:
			printk("TE%dXXP: Unknown E1 maint command: %d\n", wc->numspans, cmd);
			break;
		}
	} else {
		switch(cmd) {
	    case ZT_MAINT_NONE:
			printk("XXX Turn off local and remote loops T1 XXX\n");
			break;
	    case ZT_MAINT_LOCALLOOP:
			printk("XXX Turn on local loop and no remote loop XXX\n");
			break;
	    case ZT_MAINT_REMOTELOOP:
			printk("XXX Turn on remote loopup XXX\n");
			break;
	    case ZT_MAINT_LOOPUP:
			t4_framer_out(wc, span->offset, 0x21, 0x50);	/* FMR5: Nothing but RBS mode */
			break;
	    case ZT_MAINT_LOOPDOWN:
			t4_framer_out(wc, span->offset, 0x21, 0x60);	/* FMR5: Nothing but RBS mode */
			break;
	    case ZT_MAINT_LOOPSTOP:
			t4_framer_out(wc, span->offset, 0x21, 0x40);	/* FMR5: Nothing but RBS mode */
			break;
	    default:
			printk("TE%dXXP: Unknown T1 maint command: %d\n", wc->numspans, cmd);
			break;
	   }
    }
	return 0;
}

static int t4_rbsbits(struct zt_chan *chan, int bits)
{
	u_char m,c;
	int k,n,b;
	struct t4 *wc = chan->pvt;
	struct t4_span *ts = wc->tspans[chan->span->offset];
	unsigned long flags;
	
	if(debug & DEBUG_RBS) printk("Setting bits to %d on channel %s\n", bits, chan->name);
	spin_lock_irqsave(&wc->reglock, flags);	
	k = chan->span->offset;
	if (ts->spantype == TYPE_E1) { /* do it E1 way */
		if (chan->chanpos == 16) {
			spin_unlock_irqrestore(&wc->reglock, flags);
			return 0;
		}
		n = chan->chanpos - 1;
		if (chan->chanpos > 15) n--;
		b = (n % 15);
		c = ts->txsigs[b];
		m = (n / 15) << 2; /* nibble selector */
		c &= (0xf << m); /* keep the other nibble */
		c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
		ts->txsigs[b] = c;
		  /* output them to the chip */
		__t4_framer_out(wc,k,0x71 + b,c); 
	} else if (ts->span.lineconfig & ZT_CONFIG_D4) {
		n = chan->chanpos - 1;
		b = (n/4);
		c = ts->txsigs[b];
		m = ((3 - (n % 4)) << 1); /* nibble selector */
		c &= ~(0x3 << m); /* keep the other nibble */
		c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */
		ts->txsigs[b] = c;
		  /* output them to the chip */
		__t4_framer_out(wc,k,0x70 + b,c); 
		__t4_framer_out(wc,k,0x70 + b + 6,c); 
	} else if (ts->span.lineconfig & ZT_CONFIG_ESF) {
		n = chan->chanpos - 1;
		b = (n/2);
		c = ts->txsigs[b];
		m = ((n % 2) << 2); /* nibble selector */
		c &= (0xf << m); /* keep the other nibble */
		c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
		ts->txsigs[b] = c;
		  /* output them to the chip */
		__t4_framer_out(wc,k,0x70 + b,c); 
	} 
	spin_unlock_irqrestore(&wc->reglock, flags);
	if (debug & DEBUG_RBS)
		printk("Finished setting RBS bits\n");
	return 0;
}

static int t4_shutdown(struct zt_span *span)
{
	int tspan;
	int wasrunning;
	unsigned long flags;
	struct t4_span *ts = span->pvt;
	struct t4 *wc = ts->owner;

	tspan = span->offset + 1;
	if (tspan < 0) {
		printk("T%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno);
		return -1;
	}

	if (debug & DEBUG_MAIN) printk("Shutting down span %d (%s)\n", span->spanno, span->name);

	/* Stop HDLC controller if runned */
	if (ts->sigchan)
		hdlc_stop(wc, span->offset);
	
	spin_lock_irqsave(&wc->reglock, flags);
	wasrunning = span->flags & ZT_FLAG_RUNNING;

	span->flags &= ~ZT_FLAG_RUNNING;
	__t4_set_led(wc, span->offset, WC_OFF);
	if (((wc->numspans == 4) && 
	    (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) &&
	    (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)) &&
	    (!(wc->tspans[2]->span.flags & ZT_FLAG_RUNNING)) &&
	    (!(wc->tspans[3]->span.flags & ZT_FLAG_RUNNING)))
	    			|| 
	    ((wc->numspans == 2) && 
	    (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) &&
	    (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)))) {
		/* No longer in use, disable interrupts */
		printk("TE%dXXP: Disabling interrupts since there are no active spans\n", wc->numspans);
		set_bit(T4_STOP_DMA, &wc->checkflag);
	} else
		set_bit(T4_CHECK_TIMING, &wc->checkflag);

	spin_unlock_irqrestore(&wc->reglock, flags);

	/* Wait for interrupt routine to shut itself down */
	msleep(10);
	if (wasrunning)
		wc->spansstarted--;

	if (debug & DEBUG_MAIN)
		printk("Span %d (%s) shutdown\n", span->spanno, span->name);
	return 0;
}

static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
{
	int i;
	struct t4_span *ts = span->pvt;
	struct t4 *wc = ts->owner;

	printk("About to enter spanconfig!\n");
	if (debug & DEBUG_MAIN)
		printk("TE%dXXP: Configuring span %d\n", wc->numspans, span->spanno);

	if (lc->sync < 0)
		lc->sync = 0;
	if (lc->sync > 4)
		lc->sync = 0;
	
	/* remove this span number from the current sync sources, if there */
	for(i = 0; i < wc->numspans; i++) {
		if (wc->tspans[i]->sync == span->spanno) {
			wc->tspans[i]->sync = 0;
			wc->tspans[i]->psync = 0;
		}
	}
	wc->tspans[span->offset]->syncpos = lc->sync;
	/* if a sync src, put it in proper place */
	if (lc->sync) {
		wc->tspans[lc->sync - 1]->sync = span->spanno;
		wc->tspans[lc->sync - 1]->psync = span->offset + 1;
	}
	set_bit(T4_CHECK_TIMING, &wc->checkflag);

	/* Make sure this is clear in case of multiple startup and shutdown
	 * iterations */
	clear_bit(T4_STOP_DMA, &wc->checkflag);
	
	/* If we're already running, then go ahead and apply the changes */
	if (span->flags & ZT_FLAG_RUNNING)
		return t4_startup(span);
	printk("Done with spanconfig!\n");
	return 0;
}

static int t4_chanconfig(struct zt_chan *chan, int sigtype)
{
	int alreadyrunning;
	unsigned long flags;
	struct t4 *wc = chan->pvt;
	struct t4_span *ts = wc->tspans[chan->span->offset];

	alreadyrunning = ts->span.flags & ZT_FLAG_RUNNING;
	if (debug & DEBUG_MAIN) {
		if (alreadyrunning)
			printk("TE%dXXP: Reconfigured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype);
		else
			printk("TE%dXXP: Configured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype);
	}

	spin_lock_irqsave(&wc->reglock, flags);	

	if (alreadyrunning)
		__set_clear(wc, chan->span->offset);

	spin_unlock_irqrestore(&wc->reglock, flags);	

	/* (re)configure signalling channel */
	if ((sigtype == ZT_SIG_HARDHDLC) || (ts->sigchan == chan)) {
		if (debug & DEBUG_FRAMER)
				printk("%sonfiguring hardware HDLC on %s\n", ((sigtype == ZT_SIG_HARDHDLC) ? "C" : "Unc"), chan->name);
		if (alreadyrunning) {
			if (ts->sigchan)
				hdlc_stop(wc, ts->sigchan->span->offset);
			if (sigtype == ZT_SIG_HARDHDLC) {
				if (hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) {
					printk("Error initializing signalling controller\n");
					return -1;
				}
			} else {
				spin_lock_irqsave(&wc->reglock, flags);
				ts->sigchan = NULL;
				spin_unlock_irqrestore(&wc->reglock, flags);
			}
		
		}
		else {
			spin_lock_irqsave(&wc->reglock, flags);
			ts->sigchan = (sigtype == ZT_SIG_HARDHDLC) ? chan : NULL;
			spin_unlock_irqrestore(&wc->reglock, flags);
			ts->sigactive = 0;
		}
	}
	return 0;
}

static int t4_open(struct zt_chan *chan)
{
#ifndef LINUX26
	MOD_INC_USE_COUNT;
#else
	try_module_get(THIS_MODULE);
#endif	

	return 0;
}

static int t4_close(struct zt_chan *chan)
{
#ifndef LINUX26
	MOD_DEC_USE_COUNT;
#else
	module_put(THIS_MODULE);
#endif
	return 0;
}

/* The number of cards we have seen with each
   possible 'order' switch setting.
*/
static unsigned int order_index[16];

static void init_spans(struct t4 *wc)
{
	int x,y;
	int gen2;
	int offset = 1;
	struct t4_span *ts;
	
	gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN);
	if (!wc->t1e1)
		offset += 4;
	for (x = 0; x < wc->numspans; x++) {
		ts = wc->tspans[x];
		sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1);
		snprintf(ts->span.desc, sizeof(ts->span.desc) - 1,
			 "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
		ts->span.manufacturer = "Digium";
		zap_copy_string(ts->span.devicetype, wc->variety, sizeof(ts->span.devicetype));
		if (wc->vpm == T4_VPM_PRESENT) {
			if (!wc->vpm450m)
				strncat(ts->span.devicetype, " with VPM400M", sizeof(ts->span.devicetype) - 1);
			else
				strncat(ts->span.devicetype, (wc->numspans > 2) ? " with VPMOCT128" : " with VPMOCT064",
					sizeof(ts->span.devicetype) - 1);
		}
		if (order_index[wc->order] == 1)
			snprintf(ts->span.location, sizeof(ts->span.location) - 1, "Board ID Switch %d", wc->order);
		else
			snprintf(ts->span.location, sizeof(ts->span.location) - 1,
				 "PCI%s Bus %02d Slot %02d", (ts->spanflags & FLAG_EXPRESS) ? " Express" : " ",
				 wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
		switch (ts->spantype) {
		case TYPE_T1:
			ts->span.spantype = "T1";
			break;
		case TYPE_E1:
			ts->span.spantype = "E1";
			break;
		case TYPE_J1:
			ts->span.spantype = "J1";
			break;
		}
		ts->span.spanconfig = t4_spanconfig;
		ts->span.chanconfig = t4_chanconfig;
		ts->span.irq = wc->dev->irq;
		ts->span.startup = t4_startup;
		ts->span.shutdown = t4_shutdown;
		ts->span.rbsbits = t4_rbsbits;
		ts->span.maint = t4_maint;
		ts->span.open = t4_open;
		ts->span.close  = t4_close;

		/* HDLC Specific init */
		ts->sigchan = NULL;
		ts->sigmode = sigmode;
		ts->sigactive = 0;
		
		if (ts->spantype == TYPE_T1 || ts->spantype == TYPE_J1) {
			ts->span.channels = 24;
			ts->span.deflaw = ZT_LAW_MULAW;
			ts->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
		} else {
			ts->span.channels = 31;
			ts->span.deflaw = ZT_LAW_ALAW;
			ts->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4;
		}
		ts->span.chans = ts->chans;
		ts->span.flags = ZT_FLAG_RBS;
		ts->span.ioctl = t4_ioctl;
		ts->span.hdlc_hard_xmit = t4_hdlc_hard_xmit;
		if (gen2) {
#ifdef VPM_SUPPORT
			ts->span.echocan = t4_echocan;
#endif			
			ts->span.dacs = t4_dacs;
		}
		ts->span.pvt = ts;
		ts->owner = wc;
		ts->span.offset = x;
		ts->writechunk = (void *)(wc->writechunk + x * 32 * 2);
		ts->readchunk = (void *)(wc->readchunk + x * 32 * 2);
		init_waitqueue_head(&ts->span.maintq);
		for (y=0;y<wc->tspans[x]->span.channels;y++) {
			struct zt_chan *mychans = ts->chans + y;
			sprintf(mychans->name, "TE%d/%d/%d/%d", wc->numspans, wc->num, x + 1, y + 1);
			mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_HARDHDLC | ZT_SIG_MTP2 |
									 ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_EM_E1 | ZT_SIG_DACS_RBS;
			mychans->pvt = wc;
			mychans->chanpos = y + 1;
			if (gen2) {
				mychans->writechunk = (void *)(wc->writechunk + (x * 32 + y + offset) * 2);
				mychans->readchunk = (void *)(wc->readchunk + (x * 32 + y + offset) * 2);
			}
		}
	}
}

static void t4_serial_setup(struct t4 *wc, int unit)
{
	if (!wc->globalconfig) {
		wc->globalconfig = 1;
		printk("TE%dXXP: Setting up global serial parameters\n", wc->numspans);
		t4_framer_out(wc, 0, 0x85, 0xe0);	/* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
		t4_framer_out(wc, 0, 0x08, 0x01);	/* IPC: Interrupt push/pull active low */
	
		/* Global clocks (8.192 Mhz CLK) */
		t4_framer_out(wc, 0, 0x92, 0x00);	
		t4_framer_out(wc, 0, 0x93, 0x18);
		t4_framer_out(wc, 0, 0x94, 0xfb);
		t4_framer_out(wc, 0, 0x95, 0x0b);
		t4_framer_out(wc, 0, 0x96, 0x00);
		t4_framer_out(wc, 0, 0x97, 0x0b);
		t4_framer_out(wc, 0, 0x98, 0xdb);
		t4_framer_out(wc, 0, 0x99, 0xdf);
	}

	/* Configure interrupts */	
	t4_framer_out(wc, unit, FRMR_GCR, 0x00);	/* GCR: Interrupt on Activation/Deactivation of each */

	/* Configure system interface */
	t4_framer_out(wc, unit, FRMR_SIC1, 0xc2);	/* SIC1: 8.192 Mhz clock/bus, double buffer receive / transmit, byte interleaved */
	t4_framer_out(wc, unit, FRMR_SIC2, 0x20 | (unit << 1)); /* SIC2: No FFS, no center receive eliastic buffer, phase */
	t4_framer_out(wc, unit, FRMR_SIC3, 0x04);	/* SIC3: Edges for capture */
	t4_framer_out(wc, unit, FRMR_CMR2, 0x00);	/* CMR2: We provide sync and clock for tx and rx. */
	if (!wc->t1e1) { /* T1 mode */
		t4_framer_out(wc, unit, FRMR_XC0, 0x03);	/* XC0: Normal operation of Sa-bits */
		t4_framer_out(wc, unit, FRMR_XC1, 0x84);	/* XC1: 0 offset */
		if (wc->tspans[unit]->spantype == TYPE_J1)
			t4_framer_out(wc, unit, FRMR_RC0, 0x83);	/* RC0: Just shy of 1023 */
		else
			t4_framer_out(wc, unit, FRMR_RC0, 0x03);	/* RC0: Just shy of 1023 */
		t4_framer_out(wc, unit, FRMR_RC1, 0x84);	/* RC1: The rest of RC0 */
	} else { /* E1 mode */
		t4_framer_out(wc, unit, FRMR_XC0, 0x00);	/* XC0: Normal operation of Sa-bits */
		t4_framer_out(wc, unit, FRMR_XC1, 0x04);	/* XC1: 0 offset */

⌨️ 快捷键说明

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