📄 base.c
字号:
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 + -