From a75acc622c798c29b4f4a62ea200c248043b2d7a Mon Sep 17 00:00:00 2001 From: mattf Date: Tue, 10 Jan 2006 22:08:10 +0000 Subject: Add experimental support for Hardware HDLC for D-channels (#5313) git-svn-id: http://svn.digium.com/svn/zaptel/trunk@888 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- wct4xxp.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 380 insertions(+), 76 deletions(-) (limited to 'wct4xxp.c') diff --git a/wct4xxp.c b/wct4xxp.c index 7ce1e19..92e45c4 100644 --- a/wct4xxp.c +++ b/wct4xxp.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #ifdef STANDALONE_ZAPATA #include "zaptel.h" #else @@ -170,6 +172,7 @@ static int timingcable; static int highestorder; static int t1e1override = -1; static int j1mode = 0; +static int sigmode = FRMR_MODE_NO_ADDR_CMP; static int loopback = 0; static int alarmdebounce = 0; #ifdef VPM_SUPPORT @@ -252,6 +255,14 @@ struct t4_span { unsigned char ec_chunk2[31][ZT_CHUNKSIZE]; /* second EC chunk buffer */ #endif int irqmisses; + + /* HDLC controller fields */ + struct zt_chan *sigchan; + unsigned char sigmode; + int sigactive; + int frames_out; + int frames_in; + #ifdef VPM_SUPPORT unsigned int dtmfactive; unsigned int dtmfmask; @@ -335,6 +346,7 @@ static int t4_maint(struct zt_span *span, int cmd); #ifdef SUPPORT_GEN1 static int t4_reset_dma(struct t4 *wc); #endif +static void t4_hdlc_hard_xmit(struct zt_chan *chan); static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data); static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan); static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan); @@ -350,11 +362,12 @@ static void __t4_check_sigbits(struct t4 *wc, int span); /* #define WC_GPIO 5 */ #define WC_VERSION 6 #define WC_LEDS 7 -#define WC_ACTIVATE (1 << 12) #define WC_GPIOCTL 8 #define WC_GPIO 9 #define WC_LADDR 10 #define WC_LDATA 11 +#define WC_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ +#define WC_ACTIVATE (1 << 12) #define WC_LREAD (1 << 15) #define WC_LWRITE (1 << 16) @@ -375,23 +388,24 @@ static struct t4 *cards[MAX_T4_CARDS]; #define MAX_TDM_CHAN 32 #define MAX_DTMF_DET 16 +static inline unsigned int __t4_pci_in(struct t4 *wc, const unsigned int addr) +{ + unsigned int res = le32_to_cpu(wc->membase[addr]); + return res; +} + static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) { unsigned int tmp; wc->membase[addr] = cpu_to_le32(value); #if 1 - tmp = le32_to_cpu(wc->membase[addr]); + tmp = __t4_pci_in(wc, addr); if ((value != tmp) && (addr != WC_LEDS) && (addr != WC_LDATA) && (addr != WC_GPIO) && (addr != WC_INTR)) printk("Tried to load %08x into %08x, but got %08x instead\n", value, addr, tmp); #endif } -static inline unsigned int __t4_pci_in(struct t4 *wc, const unsigned int addr) -{ - return le32_to_cpu(wc->membase[addr]); -} - static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) { unsigned long flags; @@ -431,9 +445,9 @@ static inline unsigned int __t4_framer_in(struct t4 *wc, int unit, const unsigne unsigned int ret; unit &= 0x3; __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | ( 1 << 10) | WC_LREAD); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LREAD); ret = __t4_pci_in(wc, WC_LDATA); - __t4_pci_out(wc, WC_LADDR, 0); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); return ret & 0xff; } @@ -455,15 +469,13 @@ static inline void __t4_framer_out(struct t4 *wc, int unit, const unsigned int a printk("Writing %02x to address %02x of unit %d\n", value, addr, unit); __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); __t4_pci_out(wc, WC_LDATA, value); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10)); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10) | WC_LWRITE); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10)); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LWRITE); __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t4_pci_out(wc, WC_LADDR, 0); if (debug & DEBUG_REGS) printk("Write complete\n"); #if 0 + if ((addr != FRMR_TXFIFO) && (addr != FRMR_CMDR) && (addr != 0xbc)) { unsigned int tmp; - tmp = t4_framer_in(wc, unit, addr); + tmp = __t4_framer_in(wc, unit, addr); if (tmp != value) { printk("Expected %d from unit %d register %d but got %d instead\n", value, unit, addr, tmp); } } @@ -643,6 +655,112 @@ static void __t4_check_vpm(struct t4 *wc, unsigned int newio) } #endif +static void __hdlc_stop(struct t4 *wc, unsigned int span) +{ + struct t4_span *t = wc->tspans[span]; + unsigned char imr0, imr1, mode; + int i = 0; + + /* Clear receive and transmit timeslots */ + for (i = 0; i < 4; i++) { + __t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00); + __t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00); + } + + imr0 = __t4_framer_in(wc, span, FRMR_IMR0); + imr1 = __t4_framer_in(wc, span, FRMR_IMR1); + + /* Disable HDLC interrupts */ + imr0 |= FRMR_IMR0_RME | FRMR_IMR0_RPF; + __t4_framer_out(wc, span, FRMR_IMR0, imr0); + +#if 0 + imr1 |= FRMR_IMR1_ALLS | FRMR_IMR1_XDU | FRMR_IMR1_XPR; +#endif + imr1 |= FRMR_IMR1_XDU | FRMR_IMR1_XPR; + __t4_framer_out(wc, span, FRMR_IMR1, imr1); + + mode = __t4_framer_in(wc, span, FRMR_MODE); + mode &= ~FRMR_MODE_HRAC; + __t4_framer_out(wc, span, FRMR_MODE, mode); + + t->sigchan = NULL; + t->sigactive = 0; +} + +static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd) +{ + __t4_framer_out(wc, span, FRMR_CMDR, cmd); +} + +static inline void __t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd) +{ + int sis; + int loops = 0; + + /* XXX could be time consuming XXX */ + for (;;) { + sis = __t4_framer_in(wc, span, FRMR_SIS); + if (!(sis & 0x04)) + break; + if (!loops++) { + printk("!!!SIS Waiting before cmd %02x\n", cmd); + } + } + if (loops) + printk("!!!SIS waited %d loops\n", loops); + + __t4_framer_out(wc, span, FRMR_CMDR, cmd); +} + +static int __hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan, unsigned char mode) +{ + struct t4_span *t = wc->tspans[span]; + unsigned char imr0, imr1; + int offset = chan->chanpos; + + if (debug & DEBUG_FRAMER) printk("Initializing signalling controller for channel %d span %d\n", chan->chanpos, chan->span->offset); + + if (mode != FRMR_MODE_NO_ADDR_CMP) + return -1; + + mode |= FRMR_MODE_HRAC; + + /* Make sure we're in the right mode */ + __t4_framer_out(wc, span, FRMR_MODE, mode); + __t4_framer_out(wc, span, FRMR_TSEO, 0x00); + __t4_framer_out(wc, span, FRMR_TSBS1, 0xff); + + /* Set the interframe gaps, etc */ + __t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS); + + __t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC); + + /* Set up the time slot that we want to tx/rx on */ + __t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8))); + __t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8))); + + imr0 = __t4_framer_in(wc, span, FRMR_IMR0); + imr1 = __t4_framer_in(wc, span, FRMR_IMR1); + + /* Enable our interrupts again */ + imr0 &= ~(FRMR_IMR0_RME | FRMR_IMR0_RPF); + __t4_framer_out(wc, span, FRMR_IMR0, imr0); + +#if 0 + imr1 &= ~(FRMR_IMR1_ALLS | FRMR_IMR1_XDU | FRMR_IMR1_XPR); +#endif + imr1 &= ~(FRMR_IMR1_XDU | FRMR_IMR1_XPR); + __t4_framer_out(wc, span, FRMR_IMR1, imr1); + + /* Reset the signaling controller */ + __t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); + + t->sigchan = chan; + t->sigactive = 0; + + return 0; +} static void __set_clear(struct t4 *wc, int span) { @@ -827,6 +945,58 @@ static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) return 0; } +static void inline __t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts) +{ + int res, i, size = 32; + unsigned char buf[32]; + + res = zt_hdlc_getbuf(ts->sigchan, buf, &size); + if (debug & DEBUG_FRAMER) printk("Got buffer sized %d and res %d for %d\n", size, res, span); + if (size > 0) { + ts->sigactive = 1; + + if (debug & DEBUG_FRAMER) { + printk("TX("); + for (i = 0; i < size; i++) + printk((i ? " %02x" : "%02x"), buf[i]); + printk(")\n"); + } + + for (i = 0; i < size; i++) + __t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]); + + if (res) /* End of message */ { + if (debug & DEBUG_FRAMER) printk("transmiting XHF|XME\n"); + __t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME); +#if 0 + ts->sigactive = (__t4_framer_in(wc, span, FRMR_SIS) & FRMR_SIS_XFW) ? 0 : 1; +#endif + ++ts->frames_out; + if ((debug & DEBUG_FRAMER) && !(ts->frames_out & 0x0f)) + printk("Transmitted %d frames on span %d\n", ts->frames_out, span); + } else { /* Still more to transmit */ + if (debug & DEBUG_FRAMER) printk("transmiting XHF\n"); + __t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF); + } + } + else if (res < 0) + ts->sigactive = 0; +} + +static void t4_hdlc_hard_xmit(struct zt_chan *chan) +{ + struct t4 *wc = chan->pvt; + int span = chan->span->offset; + struct t4_span *ts = wc->tspans[span]; + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit, sigactive=%d\n", ts->sigactive); + if ((ts->sigchan == chan) && !ts->sigactive) + __t4_hdlc_xmit_fifo(wc, span, ts); + spin_unlock_irqrestore(&wc->reglock, flags); +} + static int t4_maint(struct zt_span *span, int cmd) { struct t4_span *ts = span->pvt; @@ -958,6 +1128,11 @@ static int t4_shutdown(struct zt_span *span) span->flags &= ~ZT_FLAG_RUNNING; if (wasrunning) wc->spansstarted--; + + /* Stop HDLC controller if runned */ + if (ts->sigchan) + __hdlc_stop(wc, ts->sigchan->span->offset); + __t4_set_led(wc, span->offset, WC_OFF); if (((wc->numspans == 4) && (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && @@ -1014,6 +1189,15 @@ static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) wc->tspans[lc->sync - 1]->psync = span->offset + 1; } wc->checktiming = 1; + /* HDLC controller part */ + if (ts->sigchan) { + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + __hdlc_stop(wc, ts->sigchan->span->offset); + spin_unlock_irqrestore(&wc->reglock, flags); + } + /* If we're already running, then go ahead and apply the changes */ if (span->flags & ZT_FLAG_RUNNING) return t4_startup(span); @@ -1026,17 +1210,36 @@ 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 = wc->tspans[chan->span->offset]->span.flags & ZT_FLAG_RUNNING; + 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); + + if ((sigtype == ZT_SIG_HARDHDLC) && (ts->sigchan != chan)) { + if (alreadyrunning) { + if (ts->sigchan) + __hdlc_stop(wc, ts->sigchan->span->offset); + if (__hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) { + printk("Error initializing signalling controller\n"); + spin_unlock_irqrestore(&wc->reglock, flags); + return -1; + } + } + else { + ts->sigchan = chan; + ts->sigactive = 0; + } + } spin_unlock_irqrestore(&wc->reglock, flags); return 0; } @@ -1085,6 +1288,12 @@ static void init_spans(struct t4 *wc) 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; @@ -1096,6 +1305,7 @@ static void init_spans(struct t4 *wc) ts->span.flags = ZT_FLAG_RBS; ts->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; ts->span.ioctl = t4_ioctl; + ts->span.hdlc_hard_xmit = t4_hdlc_hard_xmit; if (gen2) { #ifdef VPM_SUPPORT ts->span.echocan = t4_echocan; @@ -1111,7 +1321,7 @@ static void init_spans(struct t4 *wc) for (y=0;ytspans[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 | + mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_HARDHDLC | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_EM_E1 | ZT_SIG_DACS_RBS; c = (x * ts->span.channels) + y; mychans->pvt = wc; @@ -1144,26 +1354,26 @@ static void t4_serial_setup(struct t4 *wc, int unit) } /* Configure interrupts */ - t4_framer_out(wc, unit, 0x46, 0x00); /* GCR: Interrupt on Activation/Deactivation of each */ + t4_framer_out(wc, unit, FRMR_GCR, 0x00); /* GCR: Interrupt on Activation/Deactivation of each */ /* Configure system interface */ - t4_framer_out(wc, unit, 0x3e, 0xc2); /* SIC1: 8.192 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ - t4_framer_out(wc, unit, 0x3f, 0x20 | (unit << 1)); /* SIC2: No FFS, no center receive eliastic buffer, phase */ - t4_framer_out(wc, unit, 0x40, 0x04); /* SIC3: Edges for capture */ - t4_framer_out(wc, unit, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ + 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, 0x22, 0x03); /* XC0: Normal operation of Sa-bits */ - t4_framer_out(wc, unit, 0x23, 0x84); /* XC1: 0 offset */ + 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, 0x24, 0x83); /* RC0: Just shy of 1023 */ + t4_framer_out(wc, unit, FRMR_RC0, 0x83); /* RC0: Just shy of 1023 */ else - t4_framer_out(wc, unit, 0x24, 0x03); /* RC0: Just shy of 1023 */ - t4_framer_out(wc, unit, 0x25, 0x84); /* RC1: The rest of RC0 */ + 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, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ - t4_framer_out(wc, unit, 0x23, 0x04); /* XC1: 0 offset */ - t4_framer_out(wc, unit, 0x24, 0x04); /* RC0: Just shy of 1023 */ - t4_framer_out(wc, unit, 0x25, 0x04); /* RC1: The rest of RC0 */ + 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 */ + 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 */ @@ -1470,6 +1680,16 @@ static int t4_startup(struct zt_span *span) __t4_check_alarms(wc, span->offset); __t4_check_sigbits(wc, span->offset); } + /* Startup HDLC controller too */ + if (ts->sigchan) { + printk("Starting HDLC controller for channel %d span %d\n", ts->sigchan->channo, ts->sigchan->span->offset); + if (__hdlc_start(wc, ts->sigchan->span->offset, ts->sigchan, ts->sigmode)) { + printk("Error initializing signalling controller\n"); + /* XXX Should de-initialize span XXX */ + spin_unlock_irqrestore(&wc->reglock, flags); + return -1; + } + } } spin_unlock_irqrestore(&wc->reglock, flags); @@ -1996,6 +2216,8 @@ static inline void __handle_leds(struct t4 *wc) #endif } +static inline void __t4_framer_interrupt(struct t4 *wc, int span); + #ifdef SUPPORT_GEN1 #ifdef LINUX26 static irqreturn_t t4_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -2008,9 +2230,7 @@ static void t4_interrupt(int irq, void *dev_id, struct pt_regs *regs) int x; unsigned int status; -#if 0 unsigned int status2; -#endif #if 0 if (wc->intcount < 20) @@ -2022,6 +2242,17 @@ static void t4_interrupt(int irq, void *dev_id, struct pt_regs *regs) status = t4_pci_in(wc, WC_INTR); t4_pci_out(wc, WC_INTR, 0); + /* Process framer interrupts */ + status2 = t4_framer_in(wc, 0, FRMR_CIS); + if (status2 & 0x0f) { + spin_lock_irqsave(&wc->reglock, flags); + for (x = 0; x < wc->numspans; ++x) { + if (status2 & (1 << x)) + __t4_framer_interrupt(wc, x); + } + spin_unlock_irqrestore(&wc->reglock, flags); + } + /* Ignore if it's not for us */ if (!status) #ifdef LINUX26 @@ -2052,10 +2283,10 @@ static void t4_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if 0 if ((wc->intcount < 10) || !(wc->intcount % 1000)) { - status2 = t4_framer_in(wc, 0, 0x6f); + status2 = t4_framer_in(wc, 0, FRMR_CIS); printk("Status2: %04x\n", status2); for (x = 0;x<4;x++) { - status2 = t4_framer_in(wc, x, 0x4c); + status2 = t4_framer_in(wc, x, FRMR_FRS0); printk("FRS0/%d: %04x\n", x, status2); } } @@ -2094,64 +2325,135 @@ static void t4_interrupt(int irq, void *dev_id, struct pt_regs *regs) static inline void __t4_framer_interrupt(struct t4 *wc, int span) { /* Check interrupts for a given span */ - unsigned char gis, isr0=0, isr1=0, isr2=0, isr3=0, isr4; - struct t4_span *ts; + unsigned char gis, isr0, isr1, isr2, isr3, isr4; + int readsize = -1; + struct t4_span *ts = wc->tspans[span]; if (debug & DEBUG_FRAMER) printk("framer interrupt span %d:%d!\n", wc->num, span + 1); - ts = wc->tspans[span]; - gis = __t4_framer_in(wc, span, 0x6e); - + /* 1st gen cards isn't used interrupts */ + gis = __t4_framer_in(wc, span, FRMR_GIS); + isr0 = (gis & FRMR_GIS_ISR0) ? __t4_framer_in(wc, span, FRMR_ISR0) : 0; + isr1 = (gis & FRMR_GIS_ISR1) ? __t4_framer_in(wc, span, FRMR_ISR1) : 0; + isr2 = (gis & FRMR_GIS_ISR2) ? __t4_framer_in(wc, span, FRMR_ISR2) : 0; + isr3 = (gis & FRMR_GIS_ISR3) ? __t4_framer_in(wc, span, FRMR_ISR3) : 0; + isr4 = (gis & FRMR_GIS_ISR4) ? __t4_framer_in(wc, span, FRMR_ISR4) : 0; + + if (debug & DEBUG_FRAMER) + printk("gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x, isr4: %02x\n", gis, isr0, isr1, isr2, isr3, isr4); + + if (isr0) + __t4_check_sigbits(wc, span); + if (ts->spantype == TYPE_E1) { /* E1 checks */ - if (gis & 0x1) - isr0 = __t4_framer_in(wc, span, 0x68); - if (gis & 0x2) - isr1 = __t4_framer_in(wc, span, 0x69); - if (gis & 0x4) - isr2 = __t4_framer_in(wc, span, 0x6a); - if (gis & 0x8) - isr3 = __t4_framer_in(wc, span, 0x6b); - - - if (isr0) - __t4_check_sigbits(wc, span); - if ((isr3 & 0x38) || isr2 || isr1) __t4_check_alarms(wc, span); - if (debug & DEBUG_FRAMER) - printk("gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x\n", gis, isr0, isr1, isr2, isr3); } else { /* T1 checks */ - if (gis & 0x1) - isr0 = __t4_framer_in(wc, span, 0x68); - if (gis & 0x4) - isr2 = __t4_framer_in(wc, span, 0x6a); - if (gis & 0x8) - isr3 = __t4_framer_in(wc, span, 0x6b); - - if (isr0) - __t4_check_sigbits(wc, span); if (isr2 || (isr3 & 0x08)) __t4_check_alarms(wc, span); - if (debug & DEBUG_FRAMER) - printk("gis: %02x, isr0: %02x, isr1: %02x, irs2: %02x, isr3: %02x\n", gis, isr0, isr1, isr2, isr3); } if (debugslips && !ts->span.alarms) { if (isr3 & 0x02) printk("TE%d10P: RECEIVE slip NEGATIVE on span %d\n", wc->numspans, span + 1); if (isr3 & 0x01) printk("TE%d10P: RECEIVE slip POSITIVE on span %d\n", wc->numspans, span + 1); - if (gis & 0x10) - isr4 = __t4_framer_in(wc, span, 0x6c); - else - isr4 = 0; if (isr4 & 0x80) printk("TE%dXXP: TRANSMIT slip POSITIVE on span %d\n", wc->numspans, span + 1); if (isr4 & 0x40) printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1); } + + /* HDLC controller checks - receive side */ + if (!wc->tspans[span]->sigchan) + return; + + if (isr0 & FRMR_ISR0_RME) { + readsize = (__t4_framer_in(wc, span, FRMR_RBCH) << 8) | __t4_framer_in(wc, span, FRMR_RBCL); + if (debug & DEBUG_FRAMER) printk("Received data length is %d (%d)\n", readsize, readsize & FRMR_RBCL_MAX_SIZE); + /* RPF isn't set on last part of frame */ + if ((readsize > 0) && ((readsize &= FRMR_RBCL_MAX_SIZE) == 0)) + readsize = 32; + } else if (isr0 & FRMR_ISR0_RPF) + readsize = 32; + + if (readsize > 0) { + struct zt_chan *sigchan = ts->sigchan; + int i; + unsigned char readbuf[FRMR_RBCL_MAX_SIZE]; + + if (debug & DEBUG_FRAMER) printk("Framer %d: Got RPF/RME! readsize is %d\n", sigchan->span->offset, readsize); + + for (i = 0; i < readsize; i++) + readbuf[i] = __t4_framer_in(wc, span, FRMR_RXFIFO); + + /* Tell the framer to clear the RFIFO */ + __t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC); + + if (debug & DEBUG_FRAMER) { + printk("RX("); + for (i = 0; i < readsize; i++) + printk((i ? " %02x" : "%02x"), readbuf[i]); + printk(")\n"); + } + + if (isr0 & FRMR_ISR0_RME) { + /* Do checks for HDLC problems */ + unsigned char rsis = readbuf[readsize-1]; + unsigned int olddebug = debug; + unsigned char rsis_reg = __t4_framer_in(wc, span, FRMR_RSIS); + +#if 0 + if ((rsis != 0xA2) || (rsis != rsis_reg)) + debug |= DEBUG_FRAMER; +#endif + + ++ts->frames_in; + if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f)) + printk("Received %d frames on span %d\n", ts->frames_in, span); + if (debug & DEBUG_FRAMER) printk("Received HDLC frame %d. RSIS = 0x%x (%x)\n", ts->frames_in, rsis, rsis_reg); + if (!(rsis & FRMR_RSIS_CRC16)) { + if (debug & DEBUG_FRAMER) printk("CRC check failed %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_BADFCS); + } else if (rsis & FRMR_RSIS_RAB) { + if (debug & DEBUG_FRAMER) printk("ABORT of current frame due to overflow %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_ABORT); + } else if (rsis & FRMR_RSIS_RDO) { + if (debug & DEBUG_FRAMER) printk("HDLC overflow occured %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_OVERRUN); + } else if (!(rsis & FRMR_RSIS_VFR)) { + if (debug & DEBUG_FRAMER) printk("Valid Frame check failed on span %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_ABORT); + } else { + zt_hdlc_putbuf(sigchan, readbuf, readsize - 1); + zt_hdlc_finish(sigchan); + if (debug & DEBUG_FRAMER) printk("Received valid HDLC frame on span %d\n", span); + } + debug = olddebug; + } else if (isr0 & FRMR_ISR0_RPF) + zt_hdlc_putbuf(sigchan, readbuf, readsize); + } + + /* Transmit side */ + if (isr1 & FRMR_ISR1_XDU) { + if (debug & DEBUG_FRAMER) printk("XDU: Resetting signal controler!\n"); + __t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); + } else if (isr1 & FRMR_ISR1_XPR) { + struct zt_chan *sigchan = ts->sigchan; + + if (debug & DEBUG_FRAMER) + printk("Sigchan %d is %p\n", sigchan->chanpos, sigchan); + + if (debug & DEBUG_FRAMER) printk("Framer %d: Got XPR!\n", sigchan->span->offset); + __t4_hdlc_xmit_fifo(wc, span, ts); + } + + if (isr1 & FRMR_ISR1_ALLS) { + if (debug & DEBUG_FRAMER) printk("ALLS received\n"); + } + } #ifdef LINUX26 @@ -2202,7 +2504,7 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) wc->intcount++; #if 1 if (wc->intcount < 20) - printk("2G: Got interrupt, status = %08x, GIS = %04x\n", status, __t4_framer_in(wc, 0, 0x6f)); + printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, __t4_framer_in(wc, 0, FRMR_CIS)); #endif if (status & 0x2) { @@ -2254,14 +2556,14 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) break; } } else if (status & 0x1) { - cis = __t4_framer_in(wc, 0, 0x6f); - if (cis & 0x1) + cis = __t4_framer_in(wc, 0, FRMR_CIS); + if (cis & FRMR_CIS_GIS1) __t4_framer_interrupt(wc, 0); - if (cis & 0x2) + if (cis & FRMR_CIS_GIS2) __t4_framer_interrupt(wc, 1); - if (cis & 0x4) + if (cis & FRMR_CIS_GIS3) __t4_framer_interrupt(wc, 2); - if (cis & 0x8) + if (cis & FRMR_CIS_GIS4) __t4_framer_interrupt(wc, 3); } #ifdef VPM_SUPPORT @@ -3024,6 +3326,7 @@ module_param(timingcable, int, 0600); module_param(t1e1override, int, 0600); module_param(alarmdebounce, int, 0600); module_param(j1mode, int, 0600); +module_param(sigmode, int, 0600); #ifdef VPM_SUPPORT module_param(vpmsupport, int, 0600); module_param(vpmdtmfsupport, int, 0600); @@ -3040,6 +3343,7 @@ MODULE_PARM(timingcable, "i"); MODULE_PARM(t1e1override, "i"); MODULE_PARM(alarmdebounce, "i"); MODULE_PARM(j1mode, "i"); +MODULE_PARM(sigmode, "i"); #ifdef VPM_SUPPORT MODULE_PARM(vpmsupport, "i"); MODULE_PARM(vpmdtmfsupport, "i"); -- cgit v1.2.3