📄 base.c
字号:
t4_framer_out(wc, unit, FRMR_RC0, 0x04); /* RC0: Just shy of 1023 */
t4_framer_out(wc, unit, FRMR_RC1, 0x04); /* RC1: The rest of RC0 */
}
/* Configure ports */
t4_framer_out(wc, unit, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */
t4_framer_out(wc, unit, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */
t4_framer_out(wc, unit, 0x82, 0x65); /* PC3: Some unused stuff */
t4_framer_out(wc, unit, 0x83, 0x35); /* PC4: Some more unused stuff */
t4_framer_out(wc, unit, 0x84, 0x01); /* PC5: XMFS active low, SCLKR is input, RCLK is output */
if (debug & DEBUG_MAIN)
printk("Successfully initialized serial bus for unit %d\n", unit);
}
static int syncsrc = 0;
static int syncnum = 0 /* -1 */;
static int syncspan = 0;
#ifdef DEFINE_SPINLOCK
static DEFINE_SPINLOCK(synclock);
#else
static spinlock_t synclock = SPIN_LOCK_UNLOCKED;
#endif
static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave)
{
unsigned int timing;
int x;
if (unit != wc->syncsrc) {
timing = 0x34; /* CMR1: RCLK unit, 8.192 Mhz TCLK, RCLK is 8.192 Mhz */
if ((unit > -1) && (unit < 4)) {
timing |= (unit << 6);
for (x=0;x<wc->numspans;x++) /* set all 4 receive reference clocks to unit */
__t4_framer_out(wc, x, 0x44, timing);
wc->dmactrl |= (1 << 29);
} else {
for (x=0;x<wc->numspans;x++) /* set each receive reference clock to itself */
__t4_framer_out(wc, x, 0x44, timing | (x << 6));
wc->dmactrl &= ~(1 << 29);
}
if (slave)
wc->dmactrl |= (1 << 25);
elset
wc->dmactrl &= ~(1 << 25);
if (master)
wc->dmactrl |= (1 << 24);
else
wc->dmactrl &= ~(1 << 24);
__t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
if (!master && !slave)
wc->syncsrc = unit;
if ((unit < 0) || (unit > 3))
unit = 0;
else
unit++;
if (!master && !slave) {
for (x=0;x<wc->numspans;x++)
wc->tspans[x]->span.syncsrc = unit;
}
} else {
if (debug & DEBUG_MAIN)
printk("TE%dXXP: Timing source already set to %d\n", wc->numspans, unit);
}
#if 0
printk("wct4xxp: Timing source set to %d\n",unit);
#endif
}
static inline void __t4_update_timing(struct t4 *wc)
{
int i;
/* update sync src info */
if (wc->syncsrc != syncsrc) {
printk("Swapping card %d from %d to %d\n", wc->num, wc->syncsrc, syncsrc);
wc->syncsrc = syncsrc;
/* Update sync sources */
for (i = 0; i < wc->numspans; i++) {
wc->tspans[i]->span.syncsrc = wc->syncsrc;
}
if (syncnum == wc->num) {
__t4_set_timing_source(wc, syncspan-1, 1, 0);
if (debug) printk("Card %d, using sync span %d, master\n", wc->num, syncspan);
} else {
__t4_set_timing_source(wc, syncspan-1, 0, 1);
if (debug) printk("Card %d, using Timing Bus, NOT master\n", wc->num);
}
}
}
static int __t4_findsync(struct t4 *wc)
{
int i;
int x;
unsigned long flags;
int p;
int nonzero;
int newsyncsrc = 0; /* Zaptel span number */
int newsyncnum = 0; /* wct4xxp card number */
int newsyncspan = 0; /* span on given wct4xxp card */
spin_lock_irqsave(&synclock, flags);
#if 1
if (!wc->num) {
/* If we're the first card, go through all the motions, up to 8 levels
of sync source */
p = 1;
while (p < 8) {
nonzero = 0;
for (x=0;cards[x];x++) {
for (i = 0; i < wc->numspans; i++) {
if (cards[x]->tspans[i]->syncpos) {
nonzero = 1;
if ((cards[x]->tspans[i]->syncpos == p) &&
!(cards[x]->tspans[i]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) &&
(cards[x]->tspans[i]->span.flags & ZT_FLAG_RUNNING)) {
/* This makes a good sync source */
newsyncsrc = cards[x]->tspans[i]->span.spanno;
newsyncnum = x;
newsyncspan = i + 1;
/* Jump out */
goto found;
}
}
}
}
if (nonzero)
p++;
else
break;
}
found:
if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) {
if (debug) printk("New syncnum: %d (was %d), syncsrc: %d (was %d), syncspan: %d (was %d)\n", newsyncnum, syncnum, newsyncsrc, syncsrc, newsyncspan, syncspan);
syncnum = newsyncnum;
syncsrc = newsyncsrc;
syncspan = newsyncspan;
for (x=0;cards[x];x++) {
__t4_update_timing(cards[x]);
}
}
} else
set_bit(T4_CHECK_TIMING, &cards[0]->checkflag);
#endif
spin_unlock_irqrestore(&synclock, flags);
return 0;
}
static void __t4_set_timing_source_auto(struct t4 *wc)
{
int x;
printk("timing source auto card %d!\n", wc->num);
clear_bit(T4_CHECK_TIMING, &wc->checkflag);
if (timingcable) {
__t4_findsync(wc);
} else {
for (x=0;x<wc->numspans;x++) {
if (wc->tspans[x]->sync) {
if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & ZT_FLAG_RUNNING) &&
!(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE) )) {
/* Valid timing source */
__t4_set_timing_source(wc, wc->tspans[x]->psync - 1, 0, 0);
return;
}
}
}
__t4_set_timing_source(wc, 4, 0, 0);
}
}
static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlevel)
{
unsigned int fmr4, fmr2, fmr1, fmr0, lim2;
char *framing, *line;
int mytxlevel;
if ((txlevel > 7) || (txlevel < 4))
mytxlevel = 0;
else
mytxlevel = txlevel - 4;
fmr1 = 0x9c; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */
fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */
if (loopback)
fmr2 |= 0x4;
fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */
lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */
lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */
__t4_framer_out(wc, unit, 0x1d, fmr1);
__t4_framer_out(wc, unit, 0x1e, fmr2);
/* Configure line interface */
if (lineconfig & ZT_CONFIG_AMI) {
line = "AMI";
fmr0 = 0xa0;
} else {
line = "B8ZS";
fmr0 = 0xf0;
}
if (lineconfig & ZT_CONFIG_D4) {
framing = "D4";
} else {
framing = "ESF";
fmr4 |= 0x2;
fmr2 |= 0xc0;
}
__t4_framer_out(wc, unit, 0x1c, fmr0);
__t4_framer_out(wc, unit, 0x20, fmr4);
__t4_framer_out(wc, unit, 0x21, 0x40); /* FMR5: Enable RBS mode */
__t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */
__t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */
__t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */
__t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */
__t4_framer_out(wc, unit, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */
__t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */
__t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */
/* Generate pulse mask for T1 */
switch(mytxlevel) {
case 3:
__t4_framer_out(wc, unit, 0x26, 0x07); /* XPM0 */
__t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */
__t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
break;
case 2:
__t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */
__t4_framer_out(wc, unit, 0x27, 0x11); /* XPM1 */
__t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */
break;
case 1:
__t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */
__t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */
__t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
break;
case 0:
default:
__t4_framer_out(wc, unit, 0x26, 0xd7); /* XPM0 */
__t4_framer_out(wc, unit, 0x27, 0x22); /* XPM1 */
__t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */
break;
}
/* Don't mask framer interrupts if hardware HDLC is in use */
__t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CAS changes, etc */
__t4_framer_out(wc, unit, FRMR_IMR1, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about nothing */
__t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */
__t4_framer_out(wc, unit, 0x17, 0xf4); /* IMR3: We care about AIS and friends */
__t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */
printk("TE%dXXP: Span %d configured for %s/%s\n", wc->numspans, unit + 1, framing, line);
}
static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
{
unsigned int fmr2, fmr1, fmr0;
unsigned int cas = 0;
unsigned int imr3extra=0;
char *crc4 = "";
char *framing, *line;
fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */
fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */
if (loopback)
fmr2 |= 0x4;
if (lineconfig & ZT_CONFIG_CRC4) {
fmr1 |= 0x08; /* CRC4 transmit */
fmr2 |= 0xc0; /* CRC4 receive */
crc4 = "/CRC4";
}
__t4_framer_out(wc, unit, 0x1d, fmr1);
__t4_framer_out(wc, unit, 0x1e, fmr2);
/* Configure line interface */
if (lineconfig & ZT_CONFIG_AMI) {
line = "AMI";
fmr0 = 0xa0;
} else {
line = "HDB3";
fmr0 = 0xf0;
}
if (lineconfig & ZT_CONFIG_CCS) {
framing = "CCS";
imr3extra = 0x28;
} else {
framing = "CAS";
cas = 0x40;
}
__t4_framer_out(wc, unit, 0x1c, fmr0);
__t4_framer_out(wc, unit, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */
__t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */
__t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */
__t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */
/* Condition receive line interface for E1 after reset */
__t4_framer_out(wc, unit, 0xbb, 0x17);
__t4_framer_out(wc, unit, 0xbc, 0x55);
__t4_framer_out(wc, unit, 0xbb, 0x97);
__t4_framer_out(wc, unit, 0xbb, 0x11);
__t4_framer_out(wc, unit, 0xbc, 0xaa);
__t4_framer_out(wc, unit, 0xbb, 0x91);
__t4_framer_out(wc, unit, 0xbb, 0x12);
__t4_framer_out(wc, unit, 0xbc, 0x55);
__t4_framer_out(wc, unit, 0xbb, 0x92);
__t4_framer_out(wc, unit, 0xbb, 0x0c);
__t4_framer_out(wc, unit, 0xbb, 0x00);
__t4_framer_out(wc, unit, 0xbb, 0x8c);
__t4_framer_out(wc, unit, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */
__t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */
__t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */
__t4_framer_out(wc, unit, 0x20, 0x9f); /* XSW: Spare bits all to 1 */
__t4_framer_out(wc, unit, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */
/* Generate pulse mask for E1 */
__t4_framer_out(wc, unit, 0x26, 0x54); /* XPM0 */
__t4_framer_out(wc, unit, 0x27, 0x02); /* XPM1 */
__t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
/* Don't mask framer interrupts if hardware HDLC is in use */
__t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CRC errors, CAS changes, etc */
__t4_framer_out(wc, unit, FRMR_IMR1, 0x3f & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about loopup / loopdown */
__t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */
__t4_framer_out(wc, unit, 0x17, 0xc4 | imr3extra); /* IMR3: We care about AIS and friends */
__t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */
printk("TE%dXXP: Span %d configured for %s/%s%s\n", wc->numspans, unit + 1, framing, line, crc4);
}
static int t4_startup(struct zt_span *span)
{
#ifdef SUPPORT_GEN1
int i;
#endif
int tspan;
unsigned long flags;
int alreadyrunning;
struct t4_span *ts = span->pvt;
struct t4 *wc = ts->owner;
printk("About to enter startup!\n");
tspan = span->offset + 1;
if (tspan < 0) {
printk("TE%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno);
return -1;
}
spin_lock_irqsave(&wc->reglock, flags);
alreadyrunning = span->flags & ZT_FLAG_RUNNING;
#ifdef SUPPORT_GEN1
/* initialize the start value for the entire chunk of last ec buffer */
for(i = 0; i < span->channels; i++)
{
memset(ts->ec_chunk1[i],
ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE);
memset(ts->ec_chunk2[i],
ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE);
}
#endif
/* Force re-evaluation fo timing source */
if (timingcable)
wc->syncsrc = -1;
if (ts->spantype == TYPE_E1) { /* if this is an E1 card */
__t4_configure_e1(wc, span->offset, span->lineconfig);
} else { /* is a T1 card */
__t4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel);
}
/* Note clear channel status */
wc->tspans[span->offset]->notclear = 0;
__set_clear(wc, span->offset);
if (!alreadyrunning) {
span->flags |= ZT_FLAG_RUNNING;
wc->spansstarted++;
/* enable interrupts */
/* Start DMA, enabling DMA interrupts on read only */
wc->dmactrl = 1 << 29;
#if 0
/* Enable framer only interrupts */
wc->dmactrl |= 1 << 27;
#endif
wc->dmactrl |= (ts->spanflags & FLAG_2NDGEN) ? 0xc0000000 : 0xc0000003;
#ifdef VPM_SUPPORT
wc->dmactrl |= wc->vpm;
#endif
/* Seed interrupt register */
__t4_pci_out(wc, WC_INTR, 0x0c);
if (noburst && !(ts->spanflags & FLAG_BURST))
wc->dmactrl |= (1 << 26);
__t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
/* Startup HDLC controller too */
}
if (ts->sigchan) {
struct zt_chan *sigchan = ts->sigchan;
spin_unlock_irqrestore(&wc->reglock, flags);
if (hdlc_start(wc, span->offset, sigchan, ts->sigmode)) {
printk("Error initializing signalling controller\n");
return -1;
}
spin_lock_irqsave(&wc->reglock, flags);
}
spin_unlock_irqrestore(&wc->reglock, flags);
t4_check_alarms(wc, span->offset);
t4_check_sigbits(wc, span->offset);
if (wc->tspans[0]->sync == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno);
if (wc->tspans[1]->sync == span->spanno) printk("SP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -