diff options
author | Noe Rubinstein <nrubinstein@proformatique.com> | 2010-08-13 19:00:50 +0200 |
---|---|---|
committer | Noe Rubinstein <nrubinstein@proformatique.com> | 2010-08-13 19:00:50 +0200 |
commit | 7826455cf4c352465a569967ac73638058b8bd0e (patch) | |
tree | 24c5cd8d69005fdd4d8edf5bfb20db71e1f6d411 /xhfc | |
parent | 8ed88c4d9d3840beaf4cc670e657a8d940c3ab93 (diff) |
change everything, add TODO
Diffstat (limited to 'xhfc')
-rw-r--r-- | xhfc/Makefile | 3 | ||||
-rw-r--r-- | xhfc/TODO | 18 | ||||
-rw-r--r-- | xhfc/xhfc.c | 834 | ||||
-rw-r--r-- | xhfc/xhfc.h | 34 | ||||
-rw-r--r-- | xhfc/xhfc_leb.h | 4 | ||||
-rw-r--r-- | xhfc/xhfc_timers_state.c | 169 |
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); } } |