summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xhfc/Makefile3
-rw-r--r--xhfc/TODO18
-rw-r--r--xhfc/xhfc.c834
-rw-r--r--xhfc/xhfc.h34
-rw-r--r--xhfc/xhfc_leb.h4
-rw-r--r--xhfc/xhfc_timers_state.c169
6 files changed, 535 insertions, 527 deletions
diff --git a/xhfc/Makefile b/xhfc/Makefile
index 7ef7dad..1fcbd69 100644
--- a/xhfc/Makefile
+++ b/xhfc/Makefile
@@ -5,7 +5,8 @@ DAHDI_INCLUDE ?= /bad__dahdi_include__not_set
CFLAGS_MODULE += -I$(DAHDI_INCLUDE)
-obj-m := xhfc.o xhfc_leb.o
+obj-m := xhfcdm.o
+xhfcdm-objs := xhfc.o xhfc_leb.o xhfc_timers_state.o
modules:
modules modules_install clean:
diff --git a/xhfc/TODO b/xhfc/TODO
new file mode 100644
index 0000000..4e48397
--- /dev/null
+++ b/xhfc/TODO
@@ -0,0 +1,18 @@
+- the code is a bloody mess, clean it up
+ - end-of-line comments are used as a way to say that they should not
+ remain. Remove them.
+ - remove every XXX
+ - remove any commented-out code
+ - keep better track of where everything is allocated and initialized
+ - is the deinit correct? prolly not!
+ - harmonize traces
+- verify the alarm code. the alarm should be initialized to DAHDI_ALARM_RED
+ when initializing the ST interfaces.
+- the B chan and PCM stuff is not implemented at all
+- shouldn't part of what is done in the interrupt handler be done later in a
+ tasklet?
+- the drivers from which this one was adapted assumed that the D chan was the
+ last one in the span. For simplicity regarding the configuration of the XHFC,
+ this driver takes the third chan (which index is therefore 2) of the span as
+ the D chan. Verify that there is no part of the current code that contradicts
+ this, and that DAHDI itself doesn't make such assumptions.
diff --git a/xhfc/xhfc.c b/xhfc/xhfc.c
index 1ca102c..c64b5df 100644
--- a/xhfc/xhfc.c
+++ b/xhfc/xhfc.c
@@ -17,6 +17,9 @@ MODULE_LICENSE("GPL");
uint debug = 0;
uint dbg_spanfilter = 0xFFFFFFFF;
+
+uint ntte = 0x3;
+
//static uint port = 3;
//static int nt = 0;
//static int pcm = 0;
@@ -41,20 +44,23 @@ int softconf = 0;
module_param(debug, uint, S_IRUGO | S_IWUSR);
module_param(dbg_spanfilter, uint, S_IRUGO | S_IWUSR);
module_param(softconf, bool, S_IRUGO);
+module_param(ntte, uint, S_IRUGO);
+
//module_param(lineterm_gpio, uint, S_IRUGO);
//module_param(ntte_gpio, uint, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug bitfield:\n"
- "\t0: general\n"
- "\t1: (not used, DTMF)\n"
- "\t2: verbose register access, only if DEBUG is defined\n"
- "\t3: file operations\n"
- "\t4: (not used, echo canceller)\n"
- "\t5: (not used, ST state)\n"
- "\t6: HDLC\n"
- "\t7: (not used, alarms)\n"
- "\t8: (not used, timing)\n");
+ "\t0: general\n"
+ "\t1: (not used, DTMF)\n"
+ "\t2: verbose register access, only if DEBUG is defined\n"
+ "\t3: file operations\n"
+ "\t4: (not used, echo canceller)\n"
+ "\t5: (not used, ST state)\n"
+ "\t6: HDLC\n"
+ "\t7: (not used, alarms)\n"
+ "\t8: (not used, timing)\n");
MODULE_PARM_DESC(dbg_spanfilter, "bitfield, filter debug info by span.");
+MODULE_PARM_DESC(ntte, "bitfield, configuration of the physical ports. ex: 0x3 = 0 NT, 1 NT, 2 TE, 3 TE.");
//MODULE_PARM_DESC(pcm, "Use the PCM bus instead of the S/T interface.");
@@ -67,15 +73,13 @@ MODULE_PARM_DESC(nt, "(Only for S/T) 1 if the interface is NT, 0 if it is TE");
uint trigger = 0;
-void
-xhfc_waitbusy(struct xhfc * xhfc)
+void xhfc_waitbusy(struct xhfc *xhfc)
{
while (read_xhfc(xhfc, R_STATUS) & M_BUSY)
cpu_relax();
}
-void
-xhfc_selfifo(struct xhfc * xhfc, int fifo, int receive)
+void xhfc_selfifo(struct xhfc *xhfc, int fifo, int receive)
{
u8 r_fifo = 0x00;
SET_V_FIFO_NUM(r_fifo, fifo);
@@ -84,30 +88,27 @@ xhfc_selfifo(struct xhfc * xhfc, int fifo, int receive)
xhfc_waitbusy(xhfc);
}
-void
-xhfc_inc_f(struct xhfc * xhfc)
+void xhfc_inc_f(struct xhfc *xhfc)
{
write_xhfc(xhfc, A_INC_RES_FIFO, M_INC_F);
xhfc_waitbusy(xhfc);
}
-static inline void
-xhfc_resetfifo(struct xhfc * xhfc)
+static inline void xhfc_resetfifo(struct xhfc *xhfc)
{
write_xhfc(xhfc, A_INC_RES_FIFO, M_RES_FIFO | M_RES_FIFO_ERR);
xhfc_waitbusy(xhfc);
}
-int
-xhfc_reset(struct xhfc * xhfc)
+int xhfc_reset(struct xhfc *xhfc)
{
int timeout = 0x2000;
- /* software reset to enable R_FIFO_MD setting */
+/* software reset to enable R_FIFO_MD setting */
write_xhfc(xhfc, R_CIRM, M_SRES);
udelay(5);
write_xhfc(xhfc, R_CIRM, 0);
-
+
while ((read_xhfc(xhfc, R_STATUS) & (M_BUSY | M_PCM_INIT))
&& (timeout))
timeout--;
@@ -119,21 +120,20 @@ xhfc_reset(struct xhfc * xhfc)
return (-ENODEV);
}
- return(0);
+ return (0);
}
-void
-xhfc_config_st(struct xhfc* x, int port, int nt)
+void xhfc_config_st(struct xhfc *x, int port, int nt)
{
u8 r_su_sel, a_su_ctrl0, a_su_ctrl1, a_su_wr_sta, a_su_clk_dly;
r_su_sel = a_su_ctrl0 = a_su_ctrl1 = a_su_wr_sta = a_su_clk_dly = 0x00;
SET_V_SU_SEL(r_su_sel, port);
- SET_V_SU_MD(a_su_ctrl0, !!nt); // NT mode
+ SET_V_SU_MD(a_su_ctrl0, !!nt); // NT mode
SET_V_ST_E_IGNO(a_su_ctrl1, nt ? 1 : 0);
SET_V_G2_G3_EN(a_su_ctrl1, 1);
- SET_V_SU_ACT(a_su_wr_sta, 3); // activation
- SET_V_SU_CLK_DLY(a_su_clk_dly, nt || softconf ? 0xC : 0xE); // mode normal operation
- SET_V_ST_SMPL(a_su_clk_dly, nt ? 0x6 : 0x0); // default value
+ SET_V_SU_ACT(a_su_wr_sta, 3); // activation
+ SET_V_SU_CLK_DLY(a_su_clk_dly, nt || softconf ? 0xC : 0xE); // mode normal operation
+ SET_V_ST_SMPL(a_su_clk_dly, nt ? 0x6 : 0x0); // default value
write_xhfc(x, R_SU_SEL, r_su_sel);
xhfc_waitbusy(x);
@@ -145,9 +145,8 @@ xhfc_config_st(struct xhfc* x, int port, int nt)
}
/* configures PCM master mode
- */
-int
-xhfc_config_pcm(struct xhfc * xhfc, int master_or_slave)
+*/
+int xhfc_config_pcm(struct xhfc *xhfc, int master_or_slave)
{
static char msg[1000];
@@ -156,191 +155,198 @@ xhfc_config_pcm(struct xhfc * xhfc, int master_or_slave)
SET_V_F0_LEN(xhfc->r_pcm_md0, 1);
write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0x9));
- // use slow PCM clock adjust speed
+// use slow PCM clock adjust speed
write_xhfc(xhfc, R_PCM_MD1, M_PLL_ADJ | M_PCM_OD);
write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0xC));
- // define frame sync shape0 low byte
+// define frame sync shape0 low byte
write_xhfc(xhfc, R_SH0L, 0);
write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0xD));
- // define frame sync shape0 high byte
+// define frame sync shape0 high byte
write_xhfc(xhfc, R_SH0H, 0x0f);
write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0x0));
- // enable frame signal with shape0 timing
- // for F1_0 pin on time slot 0 for 2MBit PCM
+// enable frame signal with shape0 timing
+// for F1_0 pin on time slot 0 for 2MBit PCM
write_xhfc(xhfc, R_SL_SEL0, 0x1f);
if (master_or_slave == XHFC_PCM_MASTER) {
- write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0xA));
+ write_xhfc(xhfc, R_PCM_MD0,
+ SET_V_PCM_IDX(xhfc->r_pcm_md0, 0xA));
// enable PCM bit clk for C2O pin
write_xhfc(xhfc, R_PCM_MD2, M_C2O_EN);
} else {
- write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0xA));
- write_xhfc(xhfc, R_PCM_MD2, M_C2I_EN );
+ write_xhfc(xhfc, R_PCM_MD0,
+ SET_V_PCM_IDX(xhfc->r_pcm_md0, 0xA));
+ write_xhfc(xhfc, R_PCM_MD2, M_C2I_EN);
}
write_xhfc(xhfc, R_PCM_MD0, SET_V_PCM_IDX(xhfc->r_pcm_md0, 0x0));
- // port 0 as sysnc source for PCM
- // with port 0 in NT mode or as deactivated TE
- // PCM clock becomes free running
+// port 0 as sysnc source for PCM
+// with port 0 in NT mode or as deactivated TE
+// PCM clock becomes free running
write_xhfc(xhfc, R_SU_SYNC, 0x8);
- return(0);
+ return (0);
}
/* NOTE: assumes fifo lock is held */
#define debug_fz(b4, fifo, prefix, buf) \
do { \
- sprintf(buf, "%s: (fifo %d): flen=%d, " \
- "zlen=%d\n", prefix, fifo, flen, \
- zlen); \
+sprintf(buf, "%s: (fifo %d): flen=%d, " \
+ "zlen=%d\n", prefix, fifo, flen, \
+ zlen); \
} while (0)
-#define DEFINE_GET_LEN(F_or_Z) \
-static inline int \
-get_ ## F_or_Z ## len(struct xhfc* x) { \
- u8 _1, _2; \
- int len; \
- \
- _1 = read_xhfc(x, A_ ## F_or_Z ## 1); \
- _2 = read_xhfc(x, A_ ## F_or_Z ## 2); \
- len = _1 - _2; \
- \
- if(len < 0) \
- len += \
- (XHFC_ ## F_or_Z ## MAX - \
- XHFC_ ## F_or_Z ## MIN) + 1; \
- \
- return len; \
+#define DEFINE_GET_LEN(F_or_Z) \
+static inline int \
+get_ ## F_or_Z ## len(struct xhfc* x) { \
+u8 _1, _2; \
+int len; \
+ \
+_1 = read_xhfc(x, A_ ## F_or_Z ## 1); \
+_2 = read_xhfc(x, A_ ## F_or_Z ## 2); \
+len = _1 - _2; \
+ \
+if(len < 0) \
+ len += \
+ (XHFC_ ## F_or_Z ## MAX - \
+ XHFC_ ## F_or_Z ## MIN) + 1; \
+ \
+return len; \
}
DEFINE_GET_LEN(F)
DEFINE_GET_LEN(Z)
-
-#define WRITE_TO_REGS() \
- do { \
- write_xhfc(x, R_FIFO, r_fifo); \
- xhfc_waitbusy(x); \
- write_xhfc(x, A_CON_HDLC, a_con_hdlc); \
- write_xhfc(x, A_CHANNEL, a_channel); \
- write_xhfc(x, A_SUBCH_CFG, a_subch_cfg); \
- write_xhfc(x, A_INC_RES_FIFO, a_inc_res_fifo); \
- xhfc_waitbusy(x); \
- } while(0)
-void
-xhfc_config_d_chan_on_fifo(struct xhfc_span* xhfc_span)
+
+#define WRITE_TO_REGS() \
+do { \
+ write_xhfc(x, R_FIFO, r_fifo); \
+ xhfc_waitbusy(x); \
+ write_xhfc(x, A_CON_HDLC, a_con_hdlc); \
+ write_xhfc(x, A_CHANNEL, a_channel); \
+ write_xhfc(x, A_SUBCH_CFG, a_subch_cfg); \
+ write_xhfc(x, A_INC_RES_FIFO, a_inc_res_fifo); \
+ xhfc_waitbusy(x); \
+} while(0)
+void xhfc_config_d_chan_on_fifo(struct xhfc_span *xhfc_span)
{
- struct xhfc* x = xhfc_span->xhfc;
+ struct xhfc *x = xhfc_span->xhfc;
u8 r_fifo, a_con_hdlc, a_channel, a_subch_cfg, a_inc_res_fifo;
+ printk(KERN_DEBUG "%s: entering.\n", __func__);
+
r_fifo = a_con_hdlc = a_channel = a_subch_cfg = a_inc_res_fifo = 0x00;
+ printk(KERN_DEBUG "Configure the XHFC for HDLC on the D channel of span %s (chan %d)\n", xhfc_span->span.name, dchan_fifo(xhfc_span));
+
SET_V_FIFO_NUM(r_fifo, dchan_fifo(xhfc_span));
- SET_V_IFF(a_con_hdlc, 1); /* inter frame fill with 1s */
- SET_V_HDLC_TRP(a_con_hdlc, 0); /* HDLC mode */
- SET_V_FIFO_IRQ(a_con_hdlc, 7); /* FIFO & IRQ enabled */
- SET_V_CH_FNUM(a_channel, dchan_fifo(xhfc_span)); /* chan number */
- SET_V_BIT_CNT(a_subch_cfg, 2); /* only two bytes read or written */
- SET_V_RES_FIFO(a_inc_res_fifo, 1); /* reset FIFO */
- SET_V_RES_LOST(a_inc_res_fifo, 1); /* reset FIFO */
- SET_V_RES_FIFO_ERR(a_inc_res_fifo, 1); /* reset FIFO */
-
- SET_V_DATA_FLOW(a_con_hdlc, 0); /* FIFO -> ST/Up */
+ SET_V_IFF(a_con_hdlc, 1); /* inter frame fill with 1s */
+ SET_V_HDLC_TRP(a_con_hdlc, 0); /* HDLC mode */
+ SET_V_FIFO_IRQ(a_con_hdlc, 7); /* FIFO & IRQ enabled */
+ SET_V_CH_FNUM(a_channel, dchan_fifo(xhfc_span)); /* chan number */
+ SET_V_BIT_CNT(a_subch_cfg, 2); /* only two bytes read or written */
+ SET_V_RES_FIFO(a_inc_res_fifo, 1); /* reset FIFO */
+ SET_V_RES_LOST(a_inc_res_fifo, 1); /* reset FIFO */
+ SET_V_RES_FIFO_ERR(a_inc_res_fifo, 1); /* reset FIFO */
+
+ SET_V_DATA_FLOW(a_con_hdlc, 0); /* FIFO -> ST/Up */
- SET_V_FIFO_DIR(r_fifo, 0); /* transmit */
- SET_V_CH_FDIR(a_channel, 0); /* transmit */
+ SET_V_FIFO_DIR(r_fifo, 0); /* transmit */
+ SET_V_CH_FDIR(a_channel, 0); /* transmit */
WRITE_TO_REGS();
- SET_V_FIFO_DIR(r_fifo, 1); /* receive */
- SET_V_CH_FDIR(a_channel, 1); /* receive */
+ SET_V_FIFO_DIR(r_fifo, 1); /* receive */
+ SET_V_CH_FDIR(a_channel, 1); /* receive */
WRITE_TO_REGS();
}
#undef WRITE_TO_REGS
#if 0
-#define WRITE_TO_REGS() \
- do { \
- write_xhfc(x, R_FIFO, r_fifo); \
- xhfc_waitbusy(x); \
- write_xhfc(x, A_CON_HDLC, a_con_hdlc); \
- write_xhfc(x, A_INC_RES_FIFO, a_inc_res_fifo); \
- xhfc_waitbusy(x); \
- } while(0)
-void
-xhfc_config_b_chan_on_fifo(struct xhfc* x)
+#define WRITE_TO_REGS() \
+do { \
+ write_xhfc(x, R_FIFO, r_fifo); \
+ xhfc_waitbusy(x); \
+ write_xhfc(x, A_CON_HDLC, a_con_hdlc); \
+ write_xhfc(x, A_INC_RES_FIFO, a_inc_res_fifo); \
+ xhfc_waitbusy(x); \
+} while(0)
+void xhfc_config_b_chan_on_fifo(struct xhfc *x)
{
u8 r_fifo, a_con_hdlc, a_inc_res_fifo;
r_fifo = a_con_hdlc = a_inc_res_fifo = 0x00;
- SET_V_IFF(a_con_hdlc, 1); /* inter frame fill with 1s */
- SET_V_HDLC_TRP(a_con_hdlc, 1); /* transparent mode */
- SET_V_FIFO_IRQ(a_con_hdlc, 7); /* FIFO & IRQ enabled */
- SET_V_DATA_FLOW(a_con_hdlc, 0); /* FIFO -> ST/Up */
+ SET_V_IFF(a_con_hdlc, 1); /* inter frame fill with 1s */
+ SET_V_HDLC_TRP(a_con_hdlc, 1); /* transparent mode */
+ SET_V_FIFO_IRQ(a_con_hdlc, 7); /* FIFO & IRQ enabled */
+ SET_V_DATA_FLOW(a_con_hdlc, 0); /* FIFO -> ST/Up */
- SET_V_RES_FIFO(a_inc_res_fifo, 1); /* reset FIFO */
- SET_V_RES_LOST(a_inc_res_fifo, 1); /* reset FIFO */
- SET_V_RES_FIFO_ERR(a_inc_res_fifo, 1); /* reset FIFO */
+ SET_V_RES_FIFO(a_inc_res_fifo, 1); /* reset FIFO */
+ SET_V_RES_LOST(a_inc_res_fifo, 1); /* reset FIFO */
+ SET_V_RES_FIFO_ERR(a_inc_res_fifo, 1); /* reset FIFO */
SET_V_FIFO_NUM(r_fifo, x->testdata->b1);
- SET_V_FIFO_DIR(r_fifo, 0); /* transmit */
+ SET_V_FIFO_DIR(r_fifo, 0); /* transmit */
WRITE_TO_REGS();
- SET_V_FIFO_DIR(r_fifo, 1); /* receive */
+ SET_V_FIFO_DIR(r_fifo, 1); /* receive */
WRITE_TO_REGS();
SET_V_FIFO_NUM(r_fifo, x->testdata->b2);
- SET_V_FIFO_DIR(r_fifo, 0); /* transmit */
+ SET_V_FIFO_DIR(r_fifo, 0); /* transmit */
WRITE_TO_REGS();
- SET_V_FIFO_DIR(r_fifo, 1); /* receive */
+ SET_V_FIFO_DIR(r_fifo, 1); /* receive */
WRITE_TO_REGS();
}
+
#undef WRITE_TO_REGS
#endif
/**
- * hdlc_signal_complete() - Signal dahdi that we have a complete frame.
- *
- * @xhfc_span: The span which received the frame.
- * @stat: The frame status byte from the XHFC controller.
- *
- */
+* hdlc_signal_complete() - Signal dahdi that we have a complete frame.
+*
+* @xhfc_span: The span which received the frame.
+* @stat: The frame status byte from the XHFC controller.
+*
+*/
static void hdlc_signal_complete(struct xhfc_span *xhfc_span, u8 stat)
{
struct xhfc *xhfc = xhfc_span->xhfc;
- /* if STAT != 0, indicates bad frame */
+/* if STAT != 0, indicates bad frame */
if (stat != 0x00) {
if (DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(xhfc, "(span %d) STAT=0x%02x indicates " \
- "frame problem: %s\n", xhfc_span->port + 1, stat,
- (0xff == stat) ? "HDLC Abort" : "Bad FCS");
+ xhfc_info(xhfc, "(span %d) STAT=0x%02x indicates "
+ "frame problem: %s\n", xhfc_span->port + 1,
+ stat,
+ (0xff == stat) ? "HDLC Abort" : "Bad FCS");
}
dahdi_hdlc_abort(xhfc_span->sigchan, (0xff == stat) ?
DAHDI_EVENT_ABORT : DAHDI_EVENT_BADFCS);
- /* STAT == 0, means frame was OK */
+/* STAT == 0, means frame was OK */
} else {
if (DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(xhfc, "(span %d) Frame "/*"%d"*/" is good!\n",
- xhfc_span->port + 1/*, xhfc_span->frames_in*/);
+ xhfc_info(xhfc,
+ "(span %d) Frame " /*"%d" */ " is good!\n",
+ xhfc_span->port +
+ 1 /*, xhfc_span->frames_in */ );
}
dahdi_hdlc_finish(xhfc_span->sigchan);
}
}
-
/*
- * Inner loop for D-channel receive function. Retrieves HDLC data from the
- * hardware. If the hardware indicates that the frame is complete, we check
- * the HDLC engine's STAT byte and update DAHDI as needed.
- *
- * Returns the number of HDLC frames left in the FIFO, or -1 if we couldn't
- * get the lock.
- */
+* Inner loop for D-channel receive function. Retrieves HDLC data from the
+* hardware. If the hardware indicates that the frame is complete, we check
+* the HDLC engine's STAT byte and update DAHDI as needed.
+*
+* Returns the number of HDLC frames left in the FIFO, or -1 if we couldn't
+* get the lock.
+*/
static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
{
int fifo, i, j, k, zleft;
@@ -349,29 +355,29 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
char debugbuf[256];
struct xhfc *x = xhfc_span->xhfc;
- fifo = dchan_fifo( xhfc_span );
+ fifo = dchan_fifo(xhfc_span);
if (DBG_HDLC && DBG_SPANFILTER)
xhfc_info(x, "hdlc_rx_frame fifo %d: start\n", fifo);
- if (down_trylock(&x->fifosem) && DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(x, "rx_frame: fifo %d 1: couldn't get lock\n",
- fifo);
- return -1;
- }
+// if (down_trylock(&x->fifosem) && DBG_HDLC && DBG_SPANFILTER) {
+// xhfc_info(x, "rx_frame: fifo %d 1: couldn't get lock\n", fifo);
+// return -1;
+// }
xhfc_selfifo(x, fifo, RECEIVE);
flen = get_Flen(x);
zlen = get_Zlen(x);
debug_fz(x, fifo, "hdlc_rx_frame", debugbuf);
- up(&x->fifosem);
+
+// up(&x->fifosem);
if (DBG_HDLC && DBG_SPANFILTER)
pr_info("%s", debugbuf);
- /* if we have at least one complete frame, increment zleft to include
- * status byte */
+/* if we have at least one complete frame, increment zleft to include
+ * status byte */
zleft = zlen;
if (flen)
zleft++;
@@ -382,18 +388,18 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
else
j = zleft;
- if (down_trylock(&x->fifosem) && DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(x,
- "rx_frame fifo %d 2: couldn't get lock\n",
- fifo);
- return -1;
- }
+// if (down_trylock(&x->fifosem) && DBG_HDLC && DBG_SPANFILTER) {
+// xhfc_info(x,
+// "rx_frame fifo %d 2: couldn't get lock\n",
+// fifo);
+// return -1;
+// }
xhfc_selfifo(x, fifo, RECEIVE);
for (i = 0; i < j; i++)
buf[i] = read_xhfc(x, A_FIFO_DATA);
- up(&x->fifosem);
+// up(&x->fifosem);
/* don't send STAT byte to DAHDI */
k = j;
@@ -407,31 +413,30 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
zleft -= j;
if (DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(x, "transmitted %d bytes to dahdi, " \
- "zleft=%d\n", k, zleft);
+ xhfc_info(x, "transmitted %d bytes to dahdi, "
+ "zleft=%d\n", k, zleft);
}
if (DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(x, "hdlc_rx_frame(span %d): " \
- "zlen=%d, zleft=%d\n",
- xhfc_span->port + 1, zlen, zleft);
+ xhfc_info(x, "hdlc_rx_frame(span %d): "
+ "zlen=%d, zleft=%d\n",
+ xhfc_span->port + 1, zlen, zleft);
for (i = 0; i < j; i++) {
xhfc_info(x, "%02x%c", buf[i],
- (i < (j - 1)) ? ' ' : '\n');
+ (i < (j - 1)) ? ' ' : '\n');
}
}
} while (zleft > 0);
- /* Frame received, increment F2 and get an updated count of frames
- * left */
- if (down_trylock(&x->fifosem) && DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(x, "rx_frame fifo %d 3: couldn't get lock\n",
- fifo);
- return 0;
- }
+/* Frame received, increment F2 and get an updated count of frames
+ * left */
+// if (down_trylock(&x->fifosem) && DBG_HDLC && DBG_SPANFILTER) {
+// xhfc_info(x, "rx_frame fifo %d 3: couldn't get lock\n", fifo);
+// return 0;
+// }
- /* go get the F count again, just in case another frame snuck in while
- * we weren't looking. */
+/* go get the F count again, just in case another frame snuck in while
+ * we weren't looking. */
if (flen) {
xhfc_resetfifo(x);
//++xhfc_span->frames_in; //LOLCACA
@@ -439,14 +444,14 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
} else
new_flen = flen;
- up(&x->fifosem);
+// up(&x->fifosem);
- /* If this channel is not configured with a signalling span we don't
- * need to notify the rest of dahdi about this frame. */
+/* If this channel is not configured with a signalling span we don't
+ * need to notify the rest of dahdi about this frame. */
if (!xhfc_span->sigchan) {
if (DBG_HDLC && DBG_SPANFILTER) {
- xhfc_info(x, "hdlc_rx_frame fifo %d: " \
- "new_flen %d, early end.\n", fifo, new_flen);
+ xhfc_info(x, "hdlc_rx_frame fifo %d: "
+ "new_flen %d, early end.\n", fifo, new_flen);
}
return new_flen;
}
@@ -454,7 +459,7 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
if (flen) {
/* disable < 3 check for now */
#if 0
- if(zlen < 3) {
+ if (zlen < 3) {
if (DBG_HDLC && DBG_SPANFILTER)
xhfc_info(x, "odd, zlen less then 3?\n");
dahdi_hdlc_abort(xhfc_span->sigchan, DAHDI_EVENT_ABORT);
@@ -465,7 +470,7 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
if (DBG_HDLC && DBG_SPANFILTER) {
xhfc_info(x, "hdlc_rx_frame fifo %d: new_flen=%d end.\n",
- fifo, new_flen);
+ fifo, new_flen);
}
return new_flen;
@@ -473,11 +478,11 @@ static int hdlc_rx_frame(struct xhfc_span *xhfc_span)
static uint frames_out;
/*
- * Takes one blob of data from DAHDI and shoots it out to the hardware. The
- * blob may or may not be a complete HDLC frame. If it isn't, the D-channel
- * FIFO interrupt handler will take care of pulling the rest. Returns nonzero
- * if there is still data to send in the current HDLC frame.
- */
+* Takes one blob of data from DAHDI and shoots it out to the hardware. The
+* blob may or may not be a complete HDLC frame. If it isn't, the D-channel
+* FIFO interrupt handler will take care of pulling the rest. Returns nonzero
+* if there is still data to send in the current HDLC frame.
+*/
static int hdlc_tx_frame(struct xhfc_span *xhfc_span)
{
struct xhfc *x = xhfc_span->xhfc;
@@ -488,10 +493,10 @@ static int hdlc_tx_frame(struct xhfc_span *xhfc_span)
unsigned int size = ARRAY_SIZE(buf);
char debugbuf[256];
- //XXX
+//XXX
#if 0
- /* if we're ignoring TE red alarms and we are in alarm, restart the
- * S/T state machine */
+/* if we're ignoring TE red alarms and we are in alarm, restart the
+ * S/T state machine */
if (!span->nt && (bspan->newalarm != 0)) {
hfc_start_st(bspan);
}
@@ -500,18 +505,15 @@ static int hdlc_tx_frame(struct xhfc_span *xhfc_span)
fifo = dchan_fifo(xhfc_span);
res = dahdi_hdlc_getbuf(xhfc_span->sigchan, buf, &size);
- //XXX LOLCACA
- if (down_interruptible(&x->fifosem)) {
- static int arg;
- xhfc_info(x, "xhfc: arg (%d), grabbed data from DAHDI " \
- "but couldn't grab the lock!\n", ++arg);
- /* TODO: Inform DAHDI that we have grabbed data and can't use
- * it */
- dahdi_hdlc_abort(xhfc_span->sigchan, DAHDI_EVENT_OVERRUN);
- return 1; /* return 1 so we keep trying */
- }
-
-
+// if (down_interruptible(&x->fifosem)) {
+// static int arg;
+// xhfc_info(x, "xhfc: arg (%d), grabbed data from DAHDI "
+// "but couldn't grab the lock!\n", ++arg);
+// /* TODO: Inform DAHDI that we have grabbed data and can't use
+// * it */
+// dahdi_hdlc_abort(xhfc_span->sigchan, DAHDI_EVENT_OVERRUN);
+// return 1; /* return 1 so we keep trying */
+// }
xhfc_selfifo(x, fifo, TRANSMIT);
@@ -519,10 +521,10 @@ static int hdlc_tx_frame(struct xhfc_span *xhfc_span)
debug_fz(x, fifo, __func__, debugbuf);
/* TODO: check zlen, etc. */
- if ((XHFC_ZMAX-zlen) < size) {
+ if ((XHFC_ZMAX - zlen) < size) {
static int arg;
- xhfc_info(x, "xhfc: arg (%d), zlen (%d) < what we " \
- "grabbed from DAHDI (%d)!\n", ++arg, zlen, size);
+ xhfc_info(x, "xhfc: arg (%d), zlen (%d) < what we "
+ "grabbed from DAHDI (%d)!\n", ++arg, zlen, size);
size = zlen;
dahdi_hdlc_abort(xhfc_span->sigchan, DAHDI_EVENT_OVERRUN);
}
@@ -549,19 +551,20 @@ static int hdlc_tx_frame(struct xhfc_span *xhfc_span)
}
}
- up(&x->fifosem);
+// up(&x->fifosem);
if (0 && DBG_HDLC && DBG_SPANFILTER) {
xhfc_info(xhfc_span->xhfc, "%s", debugbuf);
- xhfc_info(xhfc_span->xhfc, "hdlc_tx_frame(span %d): DAHDI gave %d "
- "bytes for FIFO %d (res = %d)\n",
- xhfc_span->port + 1, size, fifo, res);
+ xhfc_info(xhfc_span->xhfc,
+ "hdlc_tx_frame(span %d): DAHDI gave %d "
+ "bytes for FIFO %d (res = %d)\n", xhfc_span->port + 1,
+ size, fifo, res);
for (i = 0; i < size; i++)
xhfc_info(xhfc_span->xhfc,
- "%02x%c\n", buf[i],
- (i < (size - 1)) ? ' ' : '\n');
+ "%02x%c\n", buf[i],
+ (i < (size - 1)) ? ' ' : '\n');
if (size && res != 0) {
pr_info("Transmitted frame %d on span %d\n",
@@ -612,7 +615,7 @@ xhfc_hdlc_init(struct xhfc* x)
#if 0 // LOLCACA
int
-xhfc_hdlc_init_test_st(struct xhfc* x, int port, int nt)
+xhfc_hdlc_init_xst_st(struct xhfc* x, int port, int nt)
{
x->testdata->pcm = 0;
@@ -661,201 +664,27 @@ xhfc_flush_fifo(struct xhfc* x, int fifo)
}
#endif
-int
-xhfc_st_ready(struct xhfc* x, int port, int nt)
-{
- u8 r_su_sel = 0x00, a_su_rd_sta;
- write_xhfc(x, R_SU_SEL, SET_V_SU_SEL(r_su_sel, port));
- a_su_rd_sta = read_xhfc(x, A_SU_RD_STA);
-
- return (nt && GET_V_SU_STA(a_su_rd_sta) == 3) ||
- GET_V_SU_STA(a_su_rd_sta) == 7;
-}
+/*****************************************************************************
+ * Interrupt handler, does all sort of stuff, some of which should prolly be *
+ * scheduled in a tasklet instead *
+ *****************************************************************************/
-#if USE_FIFO_IRQ
-int
-xhfc_fifo_irq(struct xhfc* x, int fifo, int receive)
-{
- u8 reg, mask;
- int bit;
-
- reg = ( fifo / 4 == 0 ? R_FIFO_BL0_IRQ :
- fifo / 4 == 1 ? R_FIFO_BL1_IRQ :
- fifo / 4 == 2 ? R_FIFO_BL2_IRQ :
- R_FIFO_BL3_IRQ);
- bit = (fifo % 4) * 2 + !!receive;
- mask = 1u << bit;
-
- return read_xhfc(x, reg) & mask;
-}
-#endif
-
-#if 0
-static u8 cnt = 0;
-/* write in the FIFO while it's not full, and continuously reads */
-int
-xhfc_hdlc_interrupt(struct xhfc* x)
-{
- int zlen, flen, i, res, len, msglen, chan;
- char msg[100];
-
- u8 buf[] = TEST_BUFFER;
- u8 rcv[2 * ARRAY_SIZE(buf)]; // longer than expected for testing
-
-// if(x->irq_cnt < 50) return 1; // 5Oms wait
-
- if(!x->testdata->pcm)
- if(!xhfc_st_ready(x, x->testdata->port, x->testdata->nt)) {
- printk(KERN_INFO "Waiting for the S/T interface to "
- "activate.\n");
- return 1;
- }
-
- msglen = 0;
- msg[0] = '\0';
-
- //trigger=1;
-
-
- chan = x->testdata->dchan;
-
-#if USE_FIFO_IRQ
- if(xhfc_fifo_irq(x, chan, 0)) {
-#endif
-
- xhfc_selfifo(x, chan, 0);
-
- while ( zlen = get_Zlen(x),
- flen = get_Flen(x),
- XHFC_ZMAX - zlen >= ARRAY_SIZE(buf) && flen < XHFC_FMAX) {
-
- buf[ARRAY_SIZE(buf) - 1] = cnt++;
-
- xhfc_hdlc_write_buf(x, chan, buf, ARRAY_SIZE(buf));
- xhfc_inc_f(x);
- }
-#if USE_FIFO_IRQ
- }
-
- if(xhfc_fifo_irq(x, chan, 1)) {
-#endif
-
- len = ARRAY_SIZE(rcv);
- res = xhfc_hdlc_read_buf(x, chan, rcv, &len);
-
- if(CORRUPTED_FRAME == res) {
- x->testdata->crpt++;
- }
- if(len) {
- /* The case in which the frame is too long for the
- * buffer is ignored in this test.
- */
- x->testdata->rcv++;
- if(len < 2) {
- msglen = sprintf(msg, "Received (shorter than 2 bytes): ");
- for(i = 0; i < len; i++)
- msglen += sprintf(msg+msglen, "%02x", rcv[i]);
- } else {
- msglen = sprintf(msg, "Received values: ");
- for(i = 0; i < len - 2; i++)
- msglen += sprintf(msg+msglen, "%02x", rcv[i]);
-
- msglen += sprintf(msg+msglen, ", CRC=");
- for(i = len - 2; i < len; i++)
- msglen += sprintf(msg+msglen, "%02x", rcv[i]);
- }
- printk(KERN_INFO "%s\n", msg);
- }
-#if USE_FIFO_IRQ
- }
-#endif
-
- return 1; //XXX
-}
-
-#endif
-
-
-#if 0
-void
-xhfc_hdlc_write_buf(struct xhfc* x, int fifo, u8* buf, int len)
-{
- int i;
-
- xhfc_selfifo(x, fifo, 0);
-
- for(i = 0; i < len; i++)
- write_xhfc(x, A_FIFO_DATA, buf[i]);
-}
-
-
-/* Read a frame, or *buflen bytes if the frame is longer than *buflen bytes.
- * Sets *buflen to the number of bytes read.
- * Returns the number of bytes remaining to read in the current frame, or
- * CORRUPTED_FRAME if the frame was corrupted.
- */
-int
-xhfc_hdlc_read_buf(struct xhfc* x, int fifo, u8* buf, int *buflen)
-{
- u8 stat;
- int i, zlen, flen;
-
- xhfc_selfifo(x, fifo, 1);
-
- flen = get_Flen(x);
- zlen = get_Zlen(x);
-
- if(flen == 0 || zlen == 0) {
- *buflen = 0;
- return 0;
- }
-
- *buflen = zlen < *buflen ? zlen : *buflen;
-
- for(i = 0; i < *buflen; i++)
- buf[i] = read_xhfc(x, A_FIFO_DATA);
-
- if (zlen <= *buflen) {
- /* (the end of) A whole frame has been read */
- stat = read_xhfc(x, A_FIFO_DATA);
- xhfc_inc_f(x);
-
- if(stat) {
- printk(KERN_INFO "Dropped corrupted frame (STAT:"
- " %02x) ", stat);
- // dahdi_hdlc_abort will be called here.
- return CORRUPTED_FRAME;
- }
-
- return 0;
- }
-
- return zlen - *buflen;
-}
-#endif
-
-/*******************************************/
-/* Interrupt handler, just handle TimerIRQ */
-/******************************************/
-
-irqreturn_t
-xhfc_interrupt(int irq, void *dev_id, struct pt_regs* ptregs)
+irqreturn_t xhfc_interrupt(int irq, void *dev_id, struct pt_regs* ptregs)
{
/* (void) ptregs; */
struct xhfc_pi *pi = dev_id;
struct xhfc *xhfc;
+
+ int fifo;
+ u8 b;
+
u8 misc_irq;
xhfc = &pi->xhfc;
/* ommit IRQs for other HW with shared IRQ */
if (!(read_xhfc(xhfc, R_IRQ_OVIEW))) {
- /*
- printk(KERN_INFO
- "%s %s NOT M_GLOB_IRQ_EN or R_IRQ_OVIEW \n",
- xhfc->name, __FUNCTION__);
- */
return IRQ_NONE;
}
@@ -864,9 +693,95 @@ xhfc_interrupt(int irq, void *dev_id, struct pt_regs* ptregs)
/* check for Timer IRQ */
if (misc_irq & M_TI_IRQMSK)
- xhfc->irq_cnt++;
+ xhfc->ticks++;
+
+//#warning xhfc_hdlc_interrupt(xhfc);
-#warning xhfc_hdlc_interrupt(xhfc);
+
+// if (xhfc->shutdown /*XXX || !b4->wc->initialized */)
+// return IRQ_HANDLED;
+
+ //b4->fifo_fill = b400m_getreg(b4, R_FILL_BL0);
+
+ //if (b4->irq_oview & V_FIFO_BL0_IRQ) {
+ // b4->fifo_irqstatus |= b400m_getreg(b4, R_FIFO_BL0_IRQ);
+ // b4->irq_oview &= ~V_FIFO_BL0_IRQ;
+ //}
+
+ ///* only look at BL0, we put all D channel FIFOs in the first block. */
+ //b = b2 = b4->fifo_irqstatus;
+
+ for (fifo = 0; fifo < 4; fifo++) {
+
+ if(xhfc->spans[fifo].sigchan)
+ //if (b & V_FIFOx_RX_IRQ) {
+ // if (fifo < 4) { /* d-channel FIFO */
+
+ // /*
+ // * I have to loop here until hdlc_rx_frame
+ // * says there are no more frames waiting. for
+ // * whatever reason, the HFC will not generate
+ // * another interrupt if there are still HDLC
+ // * frames waiting to be received. i.e. I get
+ // * an int when F1 changes, not when F1 != F2.
+ // *
+ // */
+ // do {
+ /*k =*/ hdlc_rx_frame(&xhfc->spans[fifo]);
+ // } while (k);
+ // }
+ //}
+
+ //b >>= 2;
+ }
+
+ ///* zero the bits we just processed */
+ //b4->fifo_irqstatus &= ~b2;
+ //b4->fifo_fill &= ~b2;
+
+ ///* All four D channel FIFOs are in BL0. */
+ //b = b2 = b4->fifo_fill;
+
+ for (fifo = 0; fifo < 4; fifo++) {
+ //if (b4->spans[fifo].sigactive && (b & V_FIFOx_TX_IRQ))
+ if(xhfc->spans[fifo].sigchan)
+ hdlc_tx_frame(&xhfc->spans[fifo]);
+
+ //if (b & V_FIFOx_RX_IRQ)
+ // hdlc_rx_frame(&b4->spans[fifo]);
+
+ //b >>= 2;
+ }
+
+ ///* Check for outgoing HDLC frame requests The HFC does not generate TX
+ // * interrupts when there is room to send, so I use an atomic counter
+ // * that is incremented every time DAHDI wants to send a frame, and
+ // * decremented every time I send a frame. It'd be better if I could
+ // * just use the interrupt handler, but the HFC seems to trigger a FIFO
+ // * TX IRQ only when it has finished sending a frame, not when one can
+ // * be sent.
+ // */
+ //for (i = 0; i < ARRAY_SIZE(b4->spans); i++) {
+ // struct b400m_span *bspan = &b4->spans[i];
+
+ // if (atomic_read(&bspan->hdlc_pending)) {
+ // do {
+ // k = hdlc_tx_frame(bspan);
+ // } while (k);
+ // }
+ //}
+
+ b = read_xhfc(xhfc, R_SU_IRQ);
+ if(b || 2 == xhfc->ticks % 100) { //XXX
+ int port;
+ for (port = 0; port < ARRAY_SIZE(xhfc->spans); port++) {
+
+ if(b&(1<<port)||2==xhfc->ticks%100)
+ hfc_handle_state(&xhfc->spans[port]);
+ }
+ }
+
+ hfc_update_st_timers(xhfc);
return IRQ_HANDLED;
}
@@ -875,8 +790,7 @@ xhfc_interrupt(int irq, void *dev_id, struct pt_regs* ptregs)
/*****************************************************/
/* disable all interrupts by disabling M_GLOB_IRQ_EN */
/*****************************************************/
-static void
-disable_interrupts(struct xhfc * xhfc)
+static void disable_interrupts(struct xhfc * xhfc)
{
printk(KERN_INFO "%s %s\n", xhfc->name, __FUNCTION__);
xhfc->running = 0;
@@ -887,8 +801,7 @@ disable_interrupts(struct xhfc * xhfc)
/******************************************/
/* start interrupt and set interrupt mask */
/******************************************/
-static void
-enable_interrupts(struct xhfc * xhfc)
+static void enable_interrupts(struct xhfc * xhfc)
{
printk(KERN_INFO "%s %s\n", xhfc->name, __FUNCTION__);
@@ -918,46 +831,22 @@ enable_interrupts(struct xhfc * xhfc)
/* initialise the XHFC ISDN Chip */
/* return 0 on success. */
/***********************************/
-int
-xhfc_collect_chip_id(struct xhfc * xhfc)
+int xhfc_collect_chip_id(struct xhfc * xhfc)
{
- int err = 0;
- __u8 chip_id;
-
- chip_id = read_xhfc(xhfc, R_CHIP_ID);
- switch (chip_id) {
+ u8 chip_id = read_xhfc(xhfc, R_CHIP_ID);
+ switch(chip_id) {
case CHIP_ID_1SU:
- xhfc->num_ports = 1;
- xhfc->max_fifo = 4;
- xhfc->max_z = 0xFF;
- break;
-
case CHIP_ID_2SU:
- xhfc->num_ports = 2;
- xhfc->max_fifo = 8;
- xhfc->max_z = 0x7F;
- break;
-
case CHIP_ID_2S4U:
case CHIP_ID_4SU:
- xhfc->num_ports = 4;
- xhfc->max_fifo = 16;
- xhfc->max_z = 0x3F;
- break;
- default:
- err = -ENODEV;
- }
-
- if (err) {
- printk(KERN_ERR "%s %s: unkown Chip ID 0x%x\n",
- xhfc->name, __FUNCTION__, chip_id);
- return (err);
- } else {
- printk(KERN_INFO "%s ChipID: 0x%x\n",
- xhfc->name, chip_id);
+ printk(KERN_INFO "%s ChipID: 0x%x\n",
+ xhfc->name, chip_id);
+ return 0;
}
- return 0;
+ printk(KERN_ERR "%s %s: unkown Chip ID 0x%x\n",
+ xhfc->name, __FUNCTION__, chip_id);
+ return -ENODEV;
}
void xhfc_hard_reset(void)
@@ -1017,7 +906,7 @@ int xhfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
{
struct xhfc_span *xhfc_span;
struct xhfc *xhfc;
- int te_mode, term;
+ int term;
int pos;
xhfc_span = span->pvt;
@@ -1025,19 +914,20 @@ int xhfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
// xhfc_disable_workqueues(xhfc->wc); //XXX
- te_mode = (lc->lineconfig & DAHDI_CONFIG_NTTE) ? 0 : 1;
+ xhfc_span->nt = (lc->lineconfig & DAHDI_CONFIG_NTTE) ? 1 : 0; /* xref2 */
term = (lc->lineconfig & DAHDI_CONFIG_TERM) ? 1 : 0;
xhfc_info(xhfc, "xhfc: Configuring port %d span %d in %s " \
"mode with termination resistance %s\n", xhfc_span->port,
- span->spanno, (te_mode) ? "TE" : "NT",
- (term) ? "ENABLED" : "DISABLED");
+ span->spanno, xhfc_span->nt ? "NT" : "TE",
+ term ? "ENABLED" : "DISABLED");
#warning xhfc_set_ntte(xhfc_span, te_mode, term);
+
xhfc_info(xhfc, "WARNING: This driver can't configure the ports yet, "
"expect problems if port %d isn't configured in %s "
- "mode.\n", xhfc_span->port, te_mode ? "TE" : "NT");
+ "mode.\n", xhfc_span->port, xhfc_span->nt ? "NT" : "TE");
if (lc->sync < 0) {
xhfc_info(xhfc, "Span %d has invalid sync priority (%d), " \
@@ -1059,7 +949,7 @@ int xhfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
pos = span->offset; // I guess
#endif
- if (!te_mode && lc->sync) {
+ if (xhfc_span->nt && lc->sync) {
xhfc_info(xhfc, "NT Spans cannot be timing sources. " \
"Span %d requested to be timing source of " \
"priority %d. Changing priority to 0\n", pos,
@@ -1111,6 +1001,7 @@ int xhfc_chanconfig(struct dahdi_chan *chan, int sigtype)
switch (sigtype) {
case DAHDI_SIG_HARDHDLC:
+ /* xref1 */
if (DBG_FOPS) {
xhfc_info(b4, "%sonfiguring hardware HDLC on %s\n",
((sigtype == DAHDI_SIG_HARDHDLC) ? "C" :
@@ -1122,10 +1013,15 @@ int xhfc_chanconfig(struct dahdi_chan *chan, int sigtype)
res = 0;
break;
case DAHDI_SIG_HDLCFCS:
+ xhfc_info(b4, "HDLCFCS not supported\n");
+ res = -EINVAL;
+ break;
case DAHDI_SIG_HDLCNET:
+ xhfc_info(b4, "HDLCNET not supported\n");
+ res = -EINVAL;
+ break;
case DAHDI_SIG_HDLCRAW:
- /* Only HARDHDLC is supported for the signalling channel on BRI
- * spans. */
+ xhfc_info(b4, "HDLCRAW not supported\n");
res = -EINVAL;
break;
default:
@@ -1162,6 +1058,9 @@ static int xhfc_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long d
return 0;
}
+/************************************************************************
+ * Responsible for initializing the xhfc_span and dahdi_span structures *
+ ************************************************************************/
void init_spans(struct xhfc* x)
{
int i, j;
@@ -1170,8 +1069,36 @@ void init_spans(struct xhfc* x)
/* for each span on the card */
for (i=0; i < SPANS_PER_CHIP; i++) {
+
xhfc_span = &x->spans[i];
+ /* xhfc_span */
+
+ xhfc_span->xhfc = x;
+ xhfc_span->port = i;
+
+ xhfc_span->sigchan = NULL; /* conf'd in chanconfig (xref1) */
+ xhfc_span->sigactive = 0; // XXX nanikore
+ xhfc_span->ts = 0; // XXX PCM stuff
+ xhfc_span->nt = !!(ntte && (1 << i)); /* reconf'd in spanconfig
+ (xref2) so there's two
+ different places in
+ which this is
+ configured. Should
+ this not be like that?
+ */
+
+ xhfc_span->shutdown = 0;
+ xhfc_span->newalarm = DAHDI_ALARM_RED; /* XXX should prolly be
+ initialized in the ST
+ reset instead */
+
+ /* All the timer stuff is treated in the timer and state
+ * functions, not here. */
+
+ /* dahdi_span */
+ xhfc_span->span.chans = xhfc_span->chans;
+
xhfc_span->span.irq = x->pi->pci_dev->irq;
xhfc_span->span.pvt = xhfc_span;
xhfc_span->span.spantype = xhfc_span->nt ? "NT" : "TE";
@@ -1180,12 +1107,9 @@ void init_spans(struct xhfc* x)
xhfc_span->span.flags = 0;
xhfc_span->span.deflaw = DAHDI_LAW_ALAW;
- /* For simplicty, we'll accept all line modes since BRI
- * ignores this setting anyway.*/ // XXX XXX
- xhfc_span->span.linecompat = DAHDI_CONFIG_AMI |
- DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 |
- DAHDI_CONFIG_ESF | DAHDI_CONFIG_HDB3 |
- DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
+ xhfc_span->span.linecompat =
+ DAHDI_CONFIG_TERM | DAHDI_CONFIG_NTTE |
+ DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS ;
sprintf(xhfc_span->span.name, "XHFC/%d", i+1);
sprintf(xhfc_span->span.desc, "XHFC Span %d", i+1);
@@ -1205,28 +1129,24 @@ void init_spans(struct xhfc* x)
//xhfc_span->span.close = b4xxp_close; // XXX nor this one
xhfc_span->span.ioctl = xhfc_ioctl;
xhfc_span->span.hdlc_hard_xmit = xhfc_hdlc_hard_xmit;
+
/* T'ES FOU C'EST TROP BIEN L'ECHO
- if (vpmsupport && CARD_HAS_EC(b4)) //XXX LOLCACACACA
+ if (vpmsupport && CARD_HAS_EC(b4)) //XXX
xhfc_span->span.echocan_create = echocan_create;
*/
-/* HDLC stuff */
- xhfc_span->sigchan = NULL;
- xhfc_span->sigactive = 0; // XXX nanikore
-
- xhfc_span->span.chans = xhfc_span->chans;
+ /* HDLC stuff */
+ init_waitqueue_head(&xhfc_span->span.maintq); //XXX NANIKORE
- //init_waitqueue_head(&xhfc_span->span.maintq);
-
-/* now initialize each channel in the span */
+ /* now initialize each channel in the span */
for (j=0; j < CHANS_PER_SPAN; j++) {
xhfc_span->chans[j] = &xhfc_span->_chans[j];
chan = xhfc_span->chans[j];
chan->pvt = x;
sprintf(chan->name, "XHFC/%d/%d", i + 1, j + 1);
- /* The last channel in the span is the D-channel */
- if (j == CHANS_PER_SPAN - 1) {
+ /* The second chan in the span is the D-channel */
+ if (j == 2) {
chan->sigcap = DAHDI_SIG_HARDHDLC;
} else {
chan->sigcap = DAHDI_SIG_CLEAR | DAHDI_SIG_DACS;
@@ -1238,8 +1158,7 @@ void init_spans(struct xhfc* x)
}
}
-void
-release_card_irq(struct xhfc_pi * pi)
+void release_card_irq(struct xhfc_pi * pi)
{
disable_interrupts(&pi->xhfc);
free_irq(pi->irq, pi);
@@ -1283,8 +1202,6 @@ int __devinit xhfc_init_one(struct pci_dev *pdev,
if (pi == NULL)
goto err_alloc;
- memset(pi, 0, sizeof(struct xhfc_pi));
-
sprintf(pi->name, "%s", DRIVER_NAME); /* ? */
printk(KERN_INFO "%s %s: adapter '%s' found on PCI bus %02x dev %02x\n",
@@ -1356,7 +1273,7 @@ int __devinit xhfc_init_one(struct pci_dev *pdev,
pi->xhfc.r_pcm_md0 = 0;
- init_MUTEX(&pi->xhfc.fifosem);
+ //init_MUTEX(&pi->xhfc.fifosem); // deinit where
/********
@@ -1381,13 +1298,14 @@ int __devinit xhfc_init_one(struct pci_dev *pdev,
goto err_request_irq;
}
- xhfc_init_and_configure(&pi->xhfc);
-
init_spans(&pi->xhfc);
+
+ xhfc_init_and_configure(&pi->xhfc);
for(span = 0; span < SPANS_PER_CHIP; span++)
if(dahdi_register(&pi->xhfc.spans[span].span, /*prefmaster*/ 0)) {
- rc = -EINVAL; // XXX doesn't make too much sense
+ printk(KERN_WARNING "%s %s: couldn't register spans.\n", pi->name, __FUNCTION__);
+ rc = -EINVAL;
goto err_dahdi_register;
}
// don't care/know about prefmaster I think?
@@ -1458,8 +1376,7 @@ void xhfc_shutdown(struct pci_dev *pdev)
/***************/
/* Module init */
/***************/
-static int __init
-xhfc_init(void)
+static int __init xhfc_init(void)
{
int err;
@@ -1487,8 +1404,7 @@ xhfc_init(void)
return (err);
}
-static void __exit
-xhfc_cleanup(void)
+static void __exit xhfc_cleanup(void)
{
pci_unregister_driver(&xhfc_driver);
diff --git a/xhfc/xhfc.h b/xhfc/xhfc.h
index 410fa73..9d777bf 100644
--- a/xhfc/xhfc.h
+++ b/xhfc/xhfc.h
@@ -22,7 +22,7 @@
#endif
#define SPANS_PER_CHIP 4
-#define CHANS_PER_SPAN 4
+#define CHANS_PER_SPAN 3
#define XHFC_ZMIN 0x00
#define XHFC_ZMAX 0x3F /*for V_FIFO_MD = 00*/
@@ -96,16 +96,14 @@ struct xhfc_span {
// Same as in DAHDI's for sameness reasons
struct dahdi_span span;
-
int ts; /* PCM timeslot */
-
atomic_t hdlc_pending;
int port; /* (physical) S/T port number */
int nt; /* 1 if the port is nt, 0 if it's TE */
- int rcv; /* number of received frames */
- int crpt; /* number of corrupted reveived frames */
+// int rcv; /* number of received frames */
+// int crpt; /* number of corrupted reveived frames */
int shutdown;
@@ -113,9 +111,10 @@ struct xhfc_span {
int oldstate;
int newalarm;
unsigned long alarmtimer;
- int hfc_timer_on[CHANS_PER_SPAN]; /* 1=timer active */
struct dahdi_chan* sigchan;
int sigactive;
+ unsigned long hfc_timers[CHANS_PER_SPAN+1]; /* T1, T2, T3 */ //XXX WTF with this length?
+ int hfc_timer_on[CHANS_PER_SPAN+1]; /* 1=timer active */
};
struct xhfc {
@@ -123,21 +122,17 @@ struct xhfc {
__u8 chipidx; /* index in pi->xhfcs[NUM_XHFCS] */
struct xhfc_pi *pi; /* backpointer to xhfc_pi */
- spinlock_t lock;
-
- int num_ports; /* number of S and U interfaces */
- int max_fifo; /* always 4 fifos per port */
- int max_z;
- int irq_cnt;
-
- struct xhfc_test* testdata;
struct xhfc_span spans[SPANS_PER_CHIP];
- struct semaphore fifosem;
+ //struct semaphore fifosem;
- int running;
-
u8 r_pcm_md0;
+
+ /* from DAHDI */
+ int running;
+ unsigned long ticks;
+ int setsyncspan; /* Span reported from HFC for sync on this card */
+ int reportedsyncspan; /* Span reported from HFC for sync on this card */
};
struct xhfc_pi {
@@ -168,9 +163,14 @@ int xhfc_reset(struct xhfc * xhfc);
int xhfc_chipid(struct xhfc * xhfc);
int xhfc_cfg_pcm(struct xhfc * xhfc, __u8 pcm);
+void hfc_handle_state(struct xhfc_span *s);
+void hfc_update_st_timers(struct xhfc *x);
+
int __devinit xhfc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
void __devexit xhfc_remove_one(struct pci_dev *pdev);
void xhfc_shutdown(struct pci_dev *pdev);
+extern uint debug;
+extern uint dbg_spanfilter;
#endif // __XHFC_HWTD_H__
diff --git a/xhfc/xhfc_leb.h b/xhfc/xhfc_leb.h
index ac56ee2..472bc3d 100644
--- a/xhfc/xhfc_leb.h
+++ b/xhfc/xhfc_leb.h
@@ -36,7 +36,7 @@
#define IRQ_TLP_GPIO_30 31
extern uint trigger;
-extern uint debug;
+//extern uint debug;
void leb_init(struct xhfc_pi *leb);
@@ -54,6 +54,7 @@ static inline void write_xhfc(struct xhfc * xhfc, u8 reg_addr, u8 value)
writeb(value, &cs_n0[(trigger << 8) + reg_addr]);
}
+#if 0
#ifdef DEBUG
#define read_xhfc(x, reg) ({ \
u8 _res = read_xhfc(x, reg); \
@@ -66,6 +67,7 @@ static inline void write_xhfc(struct xhfc * xhfc, u8 reg_addr, u8 value)
write_xhfc(x, reg, val); \
})
#endif
+#endif
struct tlp_leb_regs {
u32 timing_cs[8];
diff --git a/xhfc/xhfc_timers_state.c b/xhfc/xhfc_timers_state.c
index bba7985..46f35b9 100644
--- a/xhfc/xhfc_timers_state.c
+++ b/xhfc/xhfc_timers_state.c
@@ -2,12 +2,27 @@
#include <linux/timer.h>
#include "xhfc.h"
+#include "xhfc_leb.h"
+
+extern uint debug;
/*****************************
* Timers and state handling *
* (from DAHDI) *
*****************************/
+#define bri_persistentlayer1 1 /* XXX No idea what this is and it's supposed
+ to do.
+ DAHDI says: Set to 0 for disabling
+ automatic layer 1 reactivation (when other
+ end deactivates it) */
+#define bri_teignorered 1 /* 1=ignore (do not inform DAHDI) if a red
+ alarm exists in TE mode */
+#define bri_alarmdebounce 0 /* msec to wait before set/clear alarm
+ condition */
+
+#define TIMER_3_MS 3
+
/*
* allocates memory and pretty-prints a given S/T state engine state to it.
* calling routine is responsible for freeing the pointer returned! Performs
@@ -16,7 +31,7 @@
* current state.
*/
static char *hfc_decode_st_state(struct xhfc *x, struct xhfc_span *span,
- unsigned char state, int full)
+ int state, int full)
{
int nt, sta;
char s[128], *str;
@@ -33,7 +48,7 @@ static char *hfc_decode_st_state(struct xhfc *x, struct xhfc_span *span,
str = kmalloc(256, GFP_KERNEL);
if (!str) {
- dev_warn(&b4->wc->vb.pdev->dev,
+ dev_warn(&x->pi->pci_dev->dev,
"could not allocate mem for ST state decode " \
"string!\n");
return NULL;
@@ -48,14 +63,14 @@ static char *hfc_decode_st_state(struct xhfc *x, struct xhfc_span *span,
if (full) {
sprintf(s, " SYNC: %s, RX INFO0: %s",
- ((state & V_SU_FR_SYNC) ? "yes" : "no"),
- ((state & V_SU_INFO0) ? "yes" : "no"));
+ (GET_V_SU_FR_SYNC(state) ? "yes" : "no"),
+ (GET_V_SU_INFO0(state) ? "yes" : "no"));
strcat(str, s);
if (nt) {
sprintf(s, ", T2 %s, auto G2->G3: %s",
- ((state & V_SU_T2_EXP) ? "expired" : "OK"),
- ((state & V_G2_G3) ? "yes" : "no"));
+ (GET_V_SU_T2_EXP(state) ? "expired" : "OK"),
+ (GET_V_G2_G3(state) ? "yes" : "no"));
strcat(str, s);
}
}
@@ -63,28 +78,84 @@ static char *hfc_decode_st_state(struct xhfc *x, struct xhfc_span *span,
return str;
}
+static void hfc_stop_all_timers(struct xhfc_span *s);
+#define V_SU_ACT_DEACTIVATE 2
+#define V_SU_ACT_ACTIVATE 3
+static void hfc_stop_st(struct xhfc_span *s)
+{
+ u8 a_su_wr_sta = 0x00;
+ struct xhfc *xhfc = s->xhfc;
+
+ hfc_stop_all_timers(s);
+
+ write_xhfc(xhfc, R_SU_SEL, s->port);
+ write_xhfc(xhfc, A_SU_WR_STA,
+ SET_V_SU_ACT(a_su_wr_sta, V_SU_ACT_DEACTIVATE));
+}
+
+static void hfc_start_st(struct xhfc_span *s)
+{
+ u8 a_su_wr_sta = 0x00;
+ struct xhfc *xhfc = s->xhfc;
+
+ write_xhfc(xhfc, R_SU_SEL, s->port);
+ write_xhfc(xhfc, A_SU_WR_STA,
+ SET_V_SU_ACT(a_su_wr_sta, V_SU_ACT_ACTIVATE));
+
+ /* start T1 if in NT mode, T3 if in TE mode */
+ if (s->nt) {
+ static const int TIMER_1_MS = 2;
+ s->hfc_timers[XHFC_T1] = xhfc->ticks + TIMER_1_MS;
+ s->hfc_timer_on[XHFC_T1] = 1;
+ s->hfc_timer_on[XHFC_T3] = 0;
+ if (DBG_ST) {
+ xhfc_info(xhfc, "setting port %d t1 timer to %lu\n",
+ s->port + 1, s->hfc_timers[XHFC_T1]);
+ }
+ } else {
+ /* 500ms wait first time, TIMER_3_MS afterward. */
+ s->hfc_timers[XHFC_T3] = xhfc->ticks + TIMER_3_MS;
+ s->hfc_timer_on[XHFC_T3] = 1;
+ s->hfc_timer_on[XHFC_T1] = 0;
+
+ s->hfc_timers[XHFC_T4] = xhfc->ticks + 1000;
+ s->hfc_timer_on[XHFC_T4] = 1;
+
+ if (DBG_ST) {
+ xhfc_info(xhfc, "setting port %d t3 timer to %lu\n",
+ s->port + 1, s->hfc_timers[XHFC_T3]);
+ }
+ }
+}
+
/*
* sets an S/T port state machine to a given state.
* if 'auto' is nonzero, will put the state machine back in auto mode after setting the state.
*/
-static void hfc_handle_state(struct xhfc_span *s);
+void hfc_handle_state(struct xhfc_span *s);
-static void hfc_force_st_state(struct xhfc *x, struct b400m_span *s,
+static void hfc_force_st_state(struct xhfc *x, struct xhfc_span *s,
int state, int resume_auto)
{
- xhfc_setreg_ra(x, R_SU_SEL, s->port, A_SU_WR_STA,
- state | V_SU_LD_STA);
+ u8 r_su_sel = 0x00, a_su_wr_sta = 0x00;
+ write_xhfc(x, R_SU_SEL, SET_V_SU_SEL(r_su_sel, s->port));
+
+ SET_V_SU_LD_STA(a_su_wr_sta, 1);
+ SET_V_SU_SET_STA(a_su_wr_sta, state);
+ write_xhfc(x, A_SU_WR_STA, a_su_wr_sta);
- if (resume_auto)
- xhfc_setreg_ra(x, R_SU_SEL, s->port, A_SU_WR_STA, state);
+ if (resume_auto) {
+ write_xhfc(x, R_SU_SEL, r_su_sel);
+ write_xhfc(x, A_SU_WR_STA, SET_V_SU_LD_STA(a_su_wr_sta, 0));
+ }
- if (DBG_ST && ((1 << s->port) & bri_spanfilter)) {
- char *x;
+ if (DBG_ST && ((1 << s->port) & dbg_spanfilter)) {
+ char *str;
- x = hfc_decode_st_state(x, s, state, 1);
- x_info(b4, "forced port %d to state %d (auto: %d), "
+ str = hfc_decode_st_state(x, s, state, 1);
+ xhfc_info(x, "forced port %d to state %d (auto: %d), "
"new decode: %s\n", s->port + 1, state,
- resume_auto, x);
+ resume_auto, str);
kfree(x);
}
@@ -98,8 +169,8 @@ static void hfc_timer_expire(struct xhfc_span *s, int t_no)
{
struct xhfc *x = s->xhfc;
- if (DBG_ST && ((1 << s->port) & bri_spanfilter)) {
- x_info(b4, "%lu: hfc_timer_expire, Port %d T%d "
+ if (DBG_ST && ((1 << s->port) & dbg_spanfilter)) {
+ xhfc_info(x, "%lu: hfc_timer_expire, Port %d T%d "
"expired (value=%lu ena=%d)\n", x->ticks,
s->port + 1, t_no + 1, s->hfc_timers[t_no],
s->hfc_timer_on[t_no]);
@@ -140,9 +211,9 @@ static void hfc_timer_expire(struct xhfc_span *s, int t_no)
break;
default:
if (printk_ratelimit()) {
- dev_warn(&x->wc->vb.pdev->dev,
- "hfc_timer_expire found an unknown expired "
- "timer (%d)??\n", t_no);
+ dev_warn(&x->pi->pci_dev->dev,
+ "hfc_timer_expire found an unknown expired "
+ "timer (%d)??\n", t_no);
}
}
}
@@ -151,7 +222,7 @@ static void hfc_timer_expire(struct xhfc_span *s, int t_no)
* Run through the active timers on a card and deal with any expiries.
* Also see if the alarm debounce time has expired and if it has, tell DAHDI.
*/
-static void hfc_update_st_timers(struct xhfc *x)
+void hfc_update_st_timers(struct xhfc *x)
{
int i, j;
struct xhfc_span *s;
@@ -171,27 +242,27 @@ static void hfc_update_st_timers(struct xhfc *x)
hfc_timer_expire(s, j);
}
- if (s->span && s->newalarm != s->span->alarms &&
+ if (/*s->span && XXX*/ s->newalarm != s->span.alarms &&
time_after_eq(x->ticks, s->alarmtimer)) {
- s->span->alarms = s->newalarm;
+ s->span.alarms = s->newalarm;
if ((!s->newalarm && bri_teignorered) || (!bri_teignorered))
- dahdi_alarm_notify(s->span);
+ dahdi_alarm_notify(&s->span);
if (DBG_ALARM) {
- dev_info(&x->wc->vb.pdev->dev, "span %d: alarm " \
+ dev_info(&x->pi->pci_dev->dev, "span %d: alarm " \
"%d debounced\n", i + 1,
s->newalarm);
}
- set_bit(WCTDM_CHECK_TIMING, &x->wc->checkflag);
+ // set_bit(WCTDM_CHECK_TIMING, &x->wc->checkflag); NANIKORE
}
}
- if (test_and_clear_bit(WCTDM_CHECK_TIMING, &x->wc->checkflag))
- xhfc_set_sync_src(x, xhfc_find_sync(b4));
+ //if (test_and_clear_bit(WCTDM_CHECK_TIMING, &x->wc->checkflag))
+ // xhfc_set_sync_src(x, xhfc_find_sync(b4));
}
/* this is the driver-level state machine for an S/T port */
-static void hfc_handle_state(struct xhfc_span *s)
+void hfc_handle_state(struct xhfc_span *s)
{
struct xhfc *x;
unsigned char state, sta;
@@ -201,17 +272,18 @@ static void hfc_handle_state(struct xhfc_span *s)
x = s->xhfc;
nt = s->nt;
- state = xhfc_getreg_ra(x, R_SU_SEL, s->port, A_SU_RD_STA);
- sta = (state & V_SU_STA_MASK);
+ write_xhfc(x, R_SU_SEL, s->port);
+ state = read_xhfc(x, A_SU_RD_STA);
+ sta = GET_V_SU_STA(state);
- if (DBG_ST && ((1 << s->port) & bri_spanfilter)) {
- char *x;
+ if (DBG_ST && ((1 << s->port) & dbg_spanfilter) /*&& s->oldstate != state*/) {
+ char *str;
- x = hfc_decode_st_state(x, s, state, 1);
- x_info(b4, "port %d A_SU_RD_STA old=0x%02x "
+ str = hfc_decode_st_state(x, s, state, 1);
+ xhfc_info(x, "port %d A_SU_RD_STA old=0x%02x "
"now=0x%02x, decoded: %s\n", s->port + 1,
- s->oldstate, state, x);
- kfree(x);
+ s->oldstate, state, str);
+ kfree(str);
}
oldalarm = s->newalarm;
@@ -258,25 +330,25 @@ static void hfc_handle_state(struct xhfc_span *s)
s->alarmtimer = x->ticks + bri_alarmdebounce;
s->oldstate = state;
- if (DBG_ALARM) {
- x_info(b4, "span %d: old alarm %d expires %ld, "
+ if (DBG_ALARM && ((1 << s->port) & dbg_spanfilter) /*&& oldalarm != s->newalarm */) {
+ xhfc_info(x, "span %d: old alarm %d expires %ld, "
"new alarm %d expires %ld\n", s->port + 1, oldalarm,
oldtimer, s->newalarm, s->alarmtimer);
}
/* we only care about T2 expiry in G4. */
- if (nt && (sta == 4) && (state & V_SU_T2_EXP)) {
+ if (nt && (sta == 4) && GET_V_SU_T2_EXP(state)) {
if (s->hfc_timer_on[XHFC_T2])
hfc_timer_expire(s, XHFC_T2); /* handle T2 expiry */
}
/* If we're in F3 and receiving INFO0, start T3 and jump to F4 */
- if (!nt && (sta == 3) && (state & V_SU_INFO0)) {
+ if (!nt && (sta == 3) && GET_V_SU_INFO0(state)) {
if (bri_persistentlayer1) {
s->hfc_timers[XHFC_T3] = x->ticks + TIMER_3_MS;
s->hfc_timer_on[XHFC_T3] = 1;
if (DBG_ST) {
- x_info(b4, "port %d: receiving "
+ xhfc_info(x, "port %d: receiving "
"INFO0 in state 3, setting T3 and "
"jumping to F4\n", s->port + 1);
}
@@ -285,15 +357,14 @@ static void hfc_handle_state(struct xhfc_span *s)
}
/* read in R_BERT_STA to determine where our current sync source is */
- newsync = xhfc_getreg(x, R_BERT_STA) & 0x07;
+ newsync = GET_V_RD_SYNC_SRC(read_xhfc(x, R_BERT_STA));
if (newsync != x->reportedsyncspan) {
if (DBG_TIMING) {
if (newsync == 5) {
- x_info(b4, "new card sync source: SYNC_I\n");
+ xhfc_info(x, "new card sync source: SYNC_I\n");
} else {
- x_info(b4, "Card position %d: new "
- "sync source: port %d\n",
- x->position, newsync);
+ xhfc_info(x, "new sync source: port %d\n",
+ newsync);
}
}