[zaptel-commits] kpfleming: trunk r1361 - in /trunk: ./ include/
wct4xxp/
zaptel-commits at lists.digium.com
zaptel-commits at lists.digium.com
Sat Aug 26 19:18:51 MST 2006
Author: kpfleming
Date: Sat Aug 26 21:18:50 2006
New Revision: 1361
URL: http://svn.digium.com/view/zaptel?rev=1361&view=rev
Log:
Merged revisions 1359 via svnmerge from
https://origsvn.digium.com/svn/zaptel/branches/1.2
........
r1359 | kpfleming | 2006-08-26 21:02:42 -0500 (Sat, 26 Aug 2006) | 2 lines
merge in new, cleaner Octasic API integration
........
Added:
trunk/wct4xxp/ (props changed)
- copied from r1359, branches/1.2/wct4xxp/
trunk/wct4xxp/Kbuild
- copied unchanged from r1359, branches/1.2/wct4xxp/Kbuild
trunk/wct4xxp/Makefile
- copied unchanged from r1359, branches/1.2/wct4xxp/Makefile
trunk/wct4xxp/OCT6114-128D.ima
- copied unchanged from r1359, branches/1.2/wct4xxp/OCT6114-128D.ima
trunk/wct4xxp/base.c
- copied, changed from r1359, branches/1.2/wct4xxp/base.c
trunk/wct4xxp/fw2h.c
- copied unchanged from r1359, branches/1.2/wct4xxp/fw2h.c
trunk/wct4xxp/vpm450m.c
- copied unchanged from r1359, branches/1.2/wct4xxp/vpm450m.c
trunk/wct4xxp/vpm450m.h
- copied unchanged from r1359, branches/1.2/wct4xxp/vpm450m.h
trunk/wct4xxp/wct4xxp-diag.c
- copied unchanged from r1359, branches/1.2/wct4xxp/wct4xxp-diag.c
trunk/wct4xxp/wct4xxp.h
- copied, changed from r1359, branches/1.2/wct4xxp/wct4xxp.h
Removed:
trunk/OCT6114-128D.ima
trunk/fw2h.c
trunk/include/
trunk/octapi_bt0_private.h
trunk/octapi_llman_private.h
trunk/octvpm.h
trunk/vpm450m.c
trunk/vpm450m.h
trunk/wct4xxp-diag.c
trunk/wct4xxp.h
trunk/wct4xxp_base.c
Modified:
trunk/ (props changed)
trunk/Makefile
trunk/wcte11xp.c
Propchange: trunk/
------------------------------------------------------------------------------
--- branch-1.2-merged (original)
+++ branch-1.2-merged Sat Aug 26 21:18:50 2006
@@ -1,1 +1,1 @@
-/branches/1.2:1-916,918-936,938-949,958,962,970,990,1004,1011,1017,1031,1033,1060,1062,1064-1066,1069,1071,1076,1079,1081,1097,1101,1151,1185,1187,1205,1233,1235-1236,1243,1248,1259,1262,1298,1300,1304,1306,1311,1313,1315,1317,1327
+/branches/1.2:1-916,918-936,938-949,958,962,970,990,1004,1011,1017,1031,1033,1060,1062,1064-1066,1069,1071,1076,1079,1081,1097,1101,1151,1185,1187,1205,1233,1235-1236,1243,1248,1259,1262,1298,1300,1304,1306,1311,1313,1315,1317,1327,1359
Propchange: trunk/
------------------------------------------------------------------------------
--- svn:externals (original)
+++ svn:externals Sat Aug 26 21:18:50 2006
@@ -1,1 +1,2 @@
menuselect http://svn.digium.com/svn/menuselect/branches/1.0
+oct612x http://svn.digium.com/svn/octasic_api/oct612x/tags/PR43-00/software
Modified: trunk/Makefile
URL: http://svn.digium.com/view/zaptel/trunk/Makefile?rev=1361&r1=1360&r2=1361&view=diff
==============================================================================
--- trunk/Makefile (original)
+++ trunk/Makefile Sat Aug 26 21:18:50 2006
@@ -33,7 +33,7 @@
KVERS_MAJ:=$(shell echo $(KVERS) | cut -d. -f1-2)
KINCLUDES:=$(KSRC)/include
-CFLAGS+=-I. -Iinclude -O4 -g -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER
+CFLAGS+=-I. -O4 -g -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER
ifneq (,$(findstring ppc,$(UNAME_M)))
CFLAGS_PPC:=-fsigned-char
endif
@@ -135,7 +135,7 @@
ifeq ($(findstring xpp_usb,$(MENUSELECT_MODULES)),)
BUILD_XPP:=yes
endif
-MODULES:=pciradio tor2 torisa wcfxo wct1xxp wct4xxp wctdm wctdm24xxp wcte11xp wcusb zaptel ztd-eth ztd-loc ztdummy ztdynamic zttranscode
+MODULES:=pciradio tor2 torisa wcfxo wct1xxp wctdm wctdm24xxp wcte11xp wcusb zaptel ztd-eth ztd-loc ztdummy ztdynamic zttranscode
MODULES:=$(filter-out $(MENUSELECT_MODULES),$(MODULES))
MODULESO:=$(MODULES:%=%.o)
@@ -154,9 +154,10 @@
MOD_DESTDIR:=zaptel
-EXTRA_CFLAGS:=-I$(SUBDIRS)/include -I$(SUBDIRS)/include/oct6100api
obj-m:=$(MODULESO)
-wct4xxp-objs:=wct4xxp_base.o vpm450m.o
+ifeq ($(findstring wct4xxp,$(MENUSELECT_MODULES)),)
+obj-m+=wct4xxp/
+endif
# Set this to override hotplug firmware loading and revert to classic header
#HOTPLUG_FIRMWARE=no
@@ -191,17 +192,13 @@
modules: $(BUILDVER)
-linux24: prereq vpm450m_fw.h $(MODULESO)
+linux24: prereq vpm450m_fw.h $(MODULESO) wct4xxp/wct4xxp.o
linux26: prereq vpm450m_fw.h
@if [ -z "$(KSRC)" -o ! -d "$(KSRC)" ]; then echo "You do not appear to have the sources for the $(KVERS) kernel installed."; exit 1 ; fi
- $(KMAKE) modules
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules
xpp: linux26
-
-#ifneq ($(TOPDIR),)
-#include $(TOPDIR)/Rules.make
-#endif
version.h:
@ZAPTELVERSION="${ZAPTELVERSION}" build_tools/make_version_h > $@.tmp
@@ -210,6 +207,9 @@
fi
@rm -f $@.tmp
+wct4xxp/wct4xxp.o:
+ $(MAKE) -C wct4xxp KFLAGS="$(KFLAGS) -I.." CFLAGS="$(CFLAGS) -I.."
+
devel: tor2ee
tests: patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify timertest
@@ -230,14 +230,8 @@
ztdummy.o: ztdummy.h
-$(filter-out wct4xxp.o,$(MODULESO)) wct4xxp_base.o: %.o: %.c zaptel.h
+$(MODULESO): %.o: %.c zaptel.h
$(CC) $(KFLAGS) -o $@ -c $<
-
-vpm450m.o: vpm450m.c zaptel.h
- $(CC) $(KFLAGS) -I$(PWD)/include -I$(PWD)/include/oct6100api -I$(SUBDIRS)/include -I$(SUBDIRS)/include/oct6100api -o $@ -c $<
-
-wct4xxp.o: wct4xxp_base.o vpm450m.o
- $(LD) -r -o $@ wct4xxp_base.o vpm450m.o
tor2ee.o: tor2-hw.h
@@ -265,11 +259,6 @@
gendigits: LDLIBS+=-lm
gendigits: CFLAGS=
-
-fw2h: CFLAGS=
-
-vpm450m_fw.h: OCT6114-128D.ima fw2h
- ./fw2h $< $@
zaptel.c: tones.h
@@ -501,7 +490,9 @@
rm -f *.o ztcfg tzdriver sethdlc sethdlc-new
rm -f $(LTZ_SO) $(LTZ_A) *.lo
ifeq ($(BUILDVER),linux26)
- $(KMAKE) clean
+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) clean
+else
+ $(MAKE) -C wct4xxp clean
$(MAKE) -C datamods clean
endif
rm -f xpp/*.ko xpp/*.mod.c xpp/.*o.cmd
@@ -515,7 +506,6 @@
rm -f ztcfg-shared fxstest
rm -rf misdn*
rm -rf mISDNuser*
- rm -f fw2h vpm450m_fw.h
distclean: dist-clean
Propchange: trunk/wct4xxp/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sat Aug 26 21:18:50 2006
@@ -1,0 +1,5 @@
+*.mod.c
+*.cmd
+*.ko
+vpm450m_fw.h
+fw2h
Copied: trunk/wct4xxp/base.c (from r1359, branches/1.2/wct4xxp/base.c)
URL: http://svn.digium.com/view/zaptel/trunk/wct4xxp/base.c?p2=trunk/wct4xxp/base.c&p1=branches/1.2/wct4xxp/base.c&r1=1359&r2=1361&rev=1361&view=diff
==============================================================================
--- branches/1.2/wct4xxp/base.c (original)
+++ trunk/wct4xxp/base.c Sat Aug 26 21:18:50 2006
@@ -33,10 +33,12 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
#ifdef STANDALONE_ZAPATA
#include "zaptel.h"
#else
-#include <linux/zaptel.h>
+#include <zaptel/zaptel.h>
#endif
#ifdef LINUX26
#include <linux/moduleparam.h>
@@ -176,10 +178,11 @@
#endif
static int debug=0;
-static int timingcable;
+static int timingcable = 0;
static int highestorder;
-static int t1e1override = -1;
+static int t1e1override = -1; //0xFF; // -1 = jumper; 0xFF = E1
static int j1mode = 0;
+static int sigmode = FRMR_MODE_NO_ADDR_CMP;
static int loopback = 0;
static int alarmdebounce = 0;
#ifdef VPM_SUPPORT
@@ -268,6 +271,14 @@
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;
@@ -356,10 +367,11 @@
#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);
-static void __t4_set_timing_source(struct t4 *wc, int unit);
+static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave);
static void __t4_check_alarms(struct t4 *wc, int span);
static void __t4_check_sigbits(struct t4 *wc, int span);
@@ -371,14 +383,15 @@
/* #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_LCS (1 << 11)
#define WC_LCS2 (1 << 12)
-#define WC_LALE (1 << 13)
+#define WC_LALE (1 << 13)
+#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)
@@ -399,24 +412,32 @@
#define MAX_TDM_CHAN 32
#define MAX_DTMF_DET 16
+#define HDLC_IMR0_MASK (FRMR_IMR0_RME | FRMR_IMR0_RPF)
+#if 0
+#define HDLC_IMR1_MASK (FRMR_IMR1_ALLS | FRMR_IMR1_XDU | FRMR_IMR1_XPR)
+#else
+#define HDLC_IMR1_MASK (FRMR_IMR1_XDU | FRMR_IMR1_XPR)
+#endif
+
+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);
- tmp = le32_to_cpu(wc->membase[WC_VERSION]);
+ tmp = __t4_pci_in(wc, WC_VERSION);
if ((tmp & 0xffff0000) != 0xc01a0000)
printk("TE4XXP: Version Synchronization Error!\n");
#if 0
- 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_gpio_set(struct t4 *wc, unsigned bits, unsigned int val)
@@ -496,10 +517,10 @@
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);
__t4_pci_out(wc, WC_VERSION, 0);
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;
}
@@ -521,15 +542,13 @@
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);
} }
@@ -566,7 +585,7 @@
static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value)
{
int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT;
- if (!octopt)
+ if (!octopt)
__t4_gpio_set(wc, 0xff, (addr >> 8));
__t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff));
if (!octopt)
@@ -717,14 +736,17 @@
while(vpm450m_getdtmf(wc->vpm450m, &channel, &tone, &start)) {
span = channel & 0x3;
channel >>= 2;
- if (!wc->t1e1)channel -= 5;
+ if (!wc->t1e1)
+ channel -= 5;
else
channel -= 1;
if (debug)
- printk("Got tone %s of '%c' on channel %d of span %d\n",(start ? "START" : "STOP"), tone, channel, span + 1);
+ printk("Got tone %s of '%c' on channel %d of span %d\n",
+ (start ? "START" : "STOP"), tone, channel, span + 1);
if ((wc->tspans[span]->dtmfmask & (1 << channel)) && (tone != 'u')) {
if (start) {
- /* The octasic is supposed to mute us, but... Yah, you guessed it. */
+ /* The octasic is supposed to mute us, but... Yah, you
+ guessed it. */
if (wc->tspans[span]->dtmfmutemask & (1 << channel)) {
unsigned long flags;
struct zt_chan *chan = &wc->tspans[span]->span.chans[channel];
@@ -848,6 +870,107 @@
}
#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;
+
+ if (debug & DEBUG_FRAMER) printk("Stopping HDLC controller on span %d\n", span+1);
+
+ /* 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 |= HDLC_IMR0_MASK;
+ __t4_framer_out(wc, span, FRMR_IMR0, imr0);
+
+ imr1 |= HDLC_IMR1_MASK;
+ __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->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("Starting HDLC controller for channel %d span %d\n", offset, span+1);
+
+ 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 &= ~HDLC_IMR0_MASK;
+ __t4_framer_out(wc, span, FRMR_IMR0, imr0);
+
+ imr1 &= ~HDLC_IMR1_MASK;
+ __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)
{
@@ -883,12 +1006,12 @@
}
if (ts->notclear != oldnotclear) {
unsigned char reg;
- reg = __t4_framer_in(wc, span, 0x14);
+ reg = __t4_framer_in(wc, span, FRMR_IMR0);
if (ts->notclear)
reg &= ~0x08;
else
reg |= 0x08;
- __t4_framer_out(wc, span, 0x14, reg);
+ __t4_framer_out(wc, span, FRMR_IMR0, reg);
}
}
@@ -972,7 +1095,7 @@
struct t4 *wc = chan->pvt;
int channel;
int unit;
-
+
if (!wc->vpm)
return -ENODEV;
@@ -987,19 +1110,21 @@
channel = channel << 2;
channel |= chan->span->offset;
if(debug & DEBUG_ECHOCAN)
- printk("echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n", wc->num, chan->chanpos, chan->span->offset, channel, eclen);
+ printk("echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n",
+ wc->num, chan->chanpos, chan->span->offset, channel, eclen);
vpm450m_setec(wc->vpm450m, channel, eclen);
- // Mark msleep(10);
- // // msleep(100); // longer test
- } else {
- unit = t4_vpm_unit(chan->span->offset, channel);
- if(debug & DEBUG_ECHOCAN)
- printk("echocan: Card is %d, Channel is %d, Span is %d, unit is %d, unit offset is %d length %d\n", wc->num, chan->chanpos, chan->span->offset, unit, channel, eclen);
- if (eclen)
- t4_vpm_out(wc,unit,channel,0x3e);
- else
- t4_vpm_out(wc,unit,channel,0x01);
- }
+// Mark msleep(10);
+// msleep(100); // longer test
+ } else {
+ unit = t4_vpm_unit(chan->span->offset, channel);
+ if(debug & DEBUG_ECHOCAN)
+ printk("echocan: Card is %d, Channel is %d, Span is %d, unit is %d, unit offset is %d length %d\n",
+ wc->num, chan->chanpos, chan->span->offset, unit, channel, eclen);
+ if (eclen)
+ t4_vpm_out(wc,unit,channel,0x3e);
+ else
+ t4_vpm_out(wc,unit,channel,0x01);
+ }
return 0;
}
#endif
@@ -1062,6 +1187,63 @@
return -ENOTTY;
}
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 (!ts->sigchan) {
+ printk("t4_hdlc_hard_xmit: Invalid (NULL) signalling channel\n");
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ return;
+ }
+ if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit on channel %s (sigchan %s), sigactive=%d\n", chan->name, ts->sigchan->name, 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)
@@ -1189,12 +1371,19 @@
return -1;
}
+ if (debug & DEBUG_MAIN) printk("Shutting down span %d (%s)\n", span->spanno, span->name);
+
spin_lock_irqsave(&wc->reglock, flags);
wasrunning = span->flags & ZT_FLAG_RUNNING;
span->flags &= ~ZT_FLAG_RUNNING;
if (wasrunning)
wc->spansstarted--;
+
+ /* Stop HDLC controller if runned */
+ if (ts->sigchan)
+ __hdlc_stop(wc, span->offset);
+
__t4_set_led(wc, span->offset, WC_OFF);
if (((wc->numspans == 4) &&
(!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) &&
@@ -1247,6 +1436,7 @@
wc->tspans[lc->sync - 1]->psync = span->offset + 1;
}
wc->checktiming = 1;
+
/* If we're already running, then go ahead and apply the changes */
if (span->flags & ZT_FLAG_RUNNING)
return t4_startup(span);
@@ -1259,17 +1449,44 @@
int alreadyrunning;
unsigned long flags;
struct t4 *wc = chan->pvt;
-
- alreadyrunning = wc->tspans[chan->span->offset]->span.flags & ZT_FLAG_RUNNING;
+ 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);
+
+ /* (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");
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ return -1;
+ }
+ }
+ else
+ ts->sigchan = NULL;
+
+ }
+ else {
+ ts->sigchan = (sigtype == ZT_SIG_HARDHDLC) ? chan : NULL;
+ ts->sigactive = 0;
+ }
+ }
spin_unlock_irqrestore(&wc->reglock, flags);
return 0;
}
@@ -1318,6 +1535,12 @@
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;
@@ -1329,6 +1552,7 @@
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;
@@ -1344,7 +1568,7 @@
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 |
+ 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;
@@ -1377,26 +1601,26 @@
}
/* 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 */
@@ -1409,7 +1633,16 @@
printk("Successfully initialized serial bus for unit %d\n", unit);
}
-static void __t4_set_timing_source(struct t4 *wc, int 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;
@@ -1420,20 +1653,30 @@
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);
- __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
} 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);
- __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
- }
- wc->syncsrc = unit;
+ }
+ if (slave)
+ wc->dmactrl |= (1 << 25);
+ else
+ 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++;
- for (x=0;x<wc->numspans;x++)
- wc->tspans[x]->span.syncsrc = 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);
@@ -1443,21 +1686,104 @@
#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
+ cards[0]->checktiming = 1;
+#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);
wc->checktiming = 0;
- 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);
- return;
- }
- }
- }
- __t4_set_timing_source(wc, 4);
+ 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)
@@ -1533,8 +1859,9 @@
break;
}
- __t4_framer_out(wc, unit, 0x14, 0xff); /* IMR0: We care about CAS changes, etc */
- __t4_framer_out(wc, unit, 0x15, 0xff); /* IMR1: We care about nothing */
+ /* 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! */
if (debugslips) {
__t4_framer_out(wc, unit, 0x17, 0xf4); /* IMR3: We care about AIS and friends */
@@ -1621,8 +1948,9 @@
__t4_framer_out(wc, unit, 0x27, 0x02); /* XPM1 */
__t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */
- __t4_framer_out(wc, unit, 0x14, 0xff); /* IMR0: We care about CRC errors, CAS changes, etc */
- __t4_framer_out(wc, unit, 0x15, 0x3f); /* IMR1: We care about loopup / loopdown */
+ /* 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! */
if (debugslips) {
__t4_framer_out(wc, unit, 0x17, 0xc4 | imr3extra); /* IMR3: We care about AIS and friends */
@@ -1702,6 +2030,15 @@
if (!polling) {
__t4_check_alarms(wc, span->offset);
__t4_check_sigbits(wc, span->offset);
+ }
+ /* Startup HDLC controller too */
+ if (ts->sigchan) {
+ if (__hdlc_start(wc, 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;
+ }
}
}
@@ -1847,10 +2184,11 @@
unsigned int merged;
merged = ts->dtmfactive & ts->dtmfmutemask;
if (merged) {
- for (y=0;y<ts->span.channels;y++) {
+ for (y=0;y<ts->span.channels;y++) {
/* Mute any DTMFs which are supposed to be muted */
- if (merged & (1 << y)) {
- memset(ts->span.chans[y].readchunk, ZT_XLAW(0, (ts->span.chans + y)), ZT_CHUNKSIZE); }
+ if (merged & (1 << y)) {
+ memset(ts->span.chans[y].readchunk, ZT_XLAW(0, (ts->span.chans + y)), ZT_CHUNKSIZE);
+ }
}
}
#endif
@@ -2240,6 +2578,140 @@
#endif
}
+static inline void __t4_framer_interrupt(struct t4 *wc, int span)
+{
+ /* Check interrupts for a given span */
+ 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);
+
+ /* 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 ((isr3 & 0x38) || isr2 || isr1)
+ __t4_check_alarms(wc, span);
+ } else {
+ /* T1 checks */
+ if (isr2 || (isr3 & 0x08))
+ __t4_check_alarms(wc, span);
+ }
+ 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 (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 (!ts->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 SUPPORT_GEN1
#ifdef LINUX26
static irqreturn_t t4_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -2252,9 +2724,7 @@
int x;
unsigned int status;
-#if 0
unsigned int status2;
-#endif
#if 0
if (wc->intcount < 20)
@@ -2265,6 +2735,17 @@
/* Make sure it's really for us */
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)
@@ -2296,10 +2777,10 @@
#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);
}
}
@@ -2335,68 +2816,6 @@
}
#endif
-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;
-
- 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);
-
- 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)
[... 307 lines stripped ...]
More information about the zaptel-commits
mailing list