From 303b8aadf67449b6633bac29135e2e8134fb8a97 Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Wed, 4 Nov 2009 21:45:55 +0000 Subject: T1 CAS support in the xpp "pri" module Merged revisions 7244-7245,7266,7276,7457 via svnmerge from http://svn.digium.com/svn/dahdi/linux/trunk ........ r7244 | tzafrir | 2009-09-29 18:23:13 +0200 (Tue, 29 Sep 2009) | 5 lines xpp: make card_hooksig an optional card method. Done in preperation for T1 CAS support, as the PRI module will use RBS instead. ........ r7245 | tzafrir | 2009-09-29 18:45:15 +0200 (Tue, 29 Sep 2009) | 2 lines xpp: refactor pcm mask handling. ........ r7266 | tzafrir | 2009-09-30 00:43:05 +0200 (Wed, 30 Sep 2009) | 2 lines xpp: T1 CAS support ........ r7276 | tzafrir | 2009-09-30 15:49:48 +0200 (Wed, 30 Sep 2009) | 2 lines xpp: PRI PIC firmware: T1-CAS fixes ........ r7457 | tzafrir | 2009-11-03 22:24:13 +0200 (Tue, 03 Nov 2009) | 4 lines xpp: More E1/T1 CAS fixes. Mostly connect/disconnect xpp revs: mostly 7458, 7466 ........ git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.2@7485 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/xpp/card_bri.c | 11 +- drivers/dahdi/xpp/card_pri.c | 545 ++++++++++++++++++++++++----- drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex | 360 ++++++++++--------- drivers/dahdi/xpp/init_card_4_30 | 31 +- drivers/dahdi/xpp/xbus-pcm.c | 19 +- drivers/dahdi/xpp/xbus-pcm.h | 1 + drivers/dahdi/xpp/xpp_dahdi.c | 9 +- drivers/dahdi/xpp/xproto.c | 1 - 8 files changed, 696 insertions(+), 281 deletions(-) diff --git a/drivers/dahdi/xpp/card_bri.c b/drivers/dahdi/xpp/card_bri.c index a749f9d..280be6c 100644 --- a/drivers/dahdi/xpp/card_bri.c +++ b/drivers/dahdi/xpp/card_bri.c @@ -1279,6 +1279,7 @@ void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t dont_care) int i; int line_count; xpp_line_t pcm_mask; + uint pcm_len; xpd_t *main_xpd; unsigned long flags; @@ -1308,8 +1309,7 @@ void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t dont_care) } /* subunits have fake pcm_len and wanted_pcm_mask */ if(i > 0) { - sub_xpd->pcm_len = 0; - sub_xpd->wanted_pcm_mask = lines; + update_wanted_pcm_mask(sub_xpd, lines, 0); } } } @@ -1324,13 +1324,10 @@ void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t dont_care) /* * The main unit account for all subunits (pcm_len and wanted_pcm_mask). */ - main_xpd->pcm_len = (line_count) + pcm_len = (line_count) ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE : 0L; - main_xpd->wanted_pcm_mask = pcm_mask; - XPD_DBG(SIGNAL, main_xpd, "pcm_len=%d wanted_pcm_mask=0x%X (%s)\n", - main_xpd->pcm_len, main_xpd->wanted_pcm_mask, - xpd->xpdname); + update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len); spin_unlock_irqrestore(&main_xpd->lock_recompute_pcm, flags); } diff --git a/drivers/dahdi/xpp/card_pri.c b/drivers/dahdi/xpp/card_pri.c index 93b43b0..f83d472 100644 --- a/drivers/dahdi/xpp/card_pri.c +++ b/drivers/dahdi/xpp/card_pri.c @@ -40,23 +40,37 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before static DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); #define PRI_LINES_BITMASK BITMASK(31) -#define PRI_DCHAN_SIGCAP ( \ - DAHDI_SIG_EM | \ - DAHDI_SIG_CLEAR | \ - DAHDI_SIG_FXSLS | \ - DAHDI_SIG_FXSGS | \ - DAHDI_SIG_FXSKS | \ - DAHDI_SIG_FXOLS | \ - DAHDI_SIG_FXOGS | \ - DAHDI_SIG_FXOKS | \ - DAHDI_SIG_CAS | \ - DAHDI_SIG_DACS | \ - DAHDI_SIG_SF \ - ) -#define PRI_BCHAN_SIGCAP (DAHDI_SIG_CLEAR | DAHDI_SIG_DACS | DAHDI_SIG_CAS) +#define PRI_SIGCAP ( \ + DAHDI_SIG_EM | \ + DAHDI_SIG_CLEAR | \ + DAHDI_SIG_FXSLS | \ + DAHDI_SIG_FXSGS | \ + DAHDI_SIG_FXSKS | \ + DAHDI_SIG_HARDHDLC | \ + DAHDI_SIG_MTP2 | \ + DAHDI_SIG_FXOLS | \ + DAHDI_SIG_FXOGS | \ + DAHDI_SIG_FXOKS | \ + DAHDI_SIG_CAS | \ + DAHDI_SIG_EM_E1 | \ + DAHDI_SIG_DACS_RBS \ + ) + +static bool is_sigtype_dchan(int sigtype) +{ + if((sigtype & DAHDI_SIG_HDLCRAW) == DAHDI_SIG_HDLCRAW) + return 1; + if((sigtype & DAHDI_SIG_HDLCFCS) == DAHDI_SIG_HDLCFCS) + return 1; + if((sigtype & DAHDI_SIG_HARDHDLC) == DAHDI_SIG_HARDHDLC) + return 1; + return 0; +} + #define MAX_SLAVES 4 /* we have MUX of 4 clocks */ #define PRI_PORT(xpd) ((xpd)->addr.subunit) +#define CHAN_PER_REGS(p) (((p)->is_esf) ? 2 : 4) /*---------------- PRI Protocol Commands ----------------------------------*/ @@ -129,7 +143,7 @@ static int pri_linecompat(enum pri_protocol pri_protocol) DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3, [PRI_PROTO_T1] = /* coding */ - // DAHDI_CONFIG_D4 | + DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF | /* framing */ DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS, @@ -168,6 +182,8 @@ struct pri_leds { byte reserved:4; }; +#define REG_CCB1_T 0x2F /* Clear Channel Register 1 */ + #define REG_FRS0 0x4C /* Framer Receive Status Register 0 */ #define REG_FRS0_T1_FSR BIT(0) /* T1 - Frame Search Restart Flag */ #define REG_FRS0_LMFA BIT(1) /* Loss of Multiframe Alignment */ @@ -180,8 +196,7 @@ struct pri_leds { #define REG_FRS1 0x4D /* Framer Receive Status Register 1 */ #define REG_LIM0 0x36 -#define REG_LIM0_MAS BIT(0) /* Master Mode, DCO-R circuitry is frequency - synchronized to the clock supplied by SYNC */ +#define REG_LIM0_MAS BIT(0) /* Master Mode, DCO-R circuitry is frequency synchronized to the clock supplied by SYNC */ #define REG_LIM0_RTRS BIT(5) /* * Receive Termination Resistance Selection: * integrated resistor to create 75 Ohm termination (100 || 300 = 75) @@ -190,9 +205,6 @@ struct pri_leds { */ #define REG_LIM0_LL BIT(1) /* LL (Local Loopback) */ -#define REG_IMR0_E 0x14 /* Interrupt Mask Register 0 */ -#define REG_IMR0_E_CASC BIT(3) - #define REG_FMR0 0x1C #define REG_FMR0_E_RC0 BIT(4) /* Receive Code - LSB */ #define REG_FMR0_E_RC1 BIT(5) /* Receive Code - MSB */ @@ -251,6 +263,14 @@ struct pri_leds { #define REG_XSP_E_AXS BIT(3) /* Automatic Transmission of Submultiframe Status */ #define REG_XSP_E_EBP BIT(4) /* E-Bit Polarity, Si-bit position of every outgoing CRC multiframe */ #define REG_XSP_E_CASEN BIT(6) /* CAS: Channel Associated Signaling Enable */ +#define REG_FMR5_T_EIBR BIT(6) /* CAS: Enable Internal Bit Robbing Access */ + +#define REG_XC0_T 0x22 /* Transmit Control 0 */ +#define REG_XC0_BRIF BIT(5) /* Bit Robbing Idle Function */ + +#define REG_CMDR_E 0x02 /* Command Register */ +#define REG_CMDR_RRES BIT(6) /* Receiver reset */ +#define REG_CMDR_XRES BIT(4) /* Transmitter reset */ #define REG_RC0 0x24 #define REG_RC0_SJR BIT(7) /* T1 = 0, J1 = 1 */ @@ -286,7 +306,9 @@ struct pri_leds { #define VAL_PC_GPOH 0x0A /* General Purpose Output, high level */ #define VAL_PC_GPOL 0x0B /* General Purpose Output, low level */ -#define NUM_CAS_RS (REG_RS16_E - REG_RS2_E + 1) +#define NUM_CAS_RS (REG_RS16_E - REG_RS1_E + 1) +/* and of those, the ones used in T1: */ +#define NUM_CAS_RS_T (REG_RS12_E - REG_RS1_E + 1) struct PRI_priv_data { bool clock_source; @@ -294,13 +316,22 @@ struct PRI_priv_data { struct proc_dir_entry *pri_info; #endif enum pri_protocol pri_protocol; + xpp_line_t rbslines; int deflaw; unsigned int dchan_num; bool initialized; - bool is_cas; + int is_cas; + + unsigned int chanconfig_dchan; +#define NO_DCHAN (0) +#define DCHAN(p) ((p)->chanconfig_dchan) +#define VALID_DCHAN(p) (DCHAN(p) != NO_DCHAN) +#define SET_DCHAN(p,d) do { DCHAN(p) = (d); } while(0); + byte cas_rs_e[NUM_CAS_RS]; byte cas_ts_e[NUM_CAS_RS]; uint cas_replies; + bool is_esf; bool local_loopback; uint poll_noreplies; uint layer1_replies; @@ -452,15 +483,21 @@ static void pri_pcm_update(xpd_t *xpd) struct PRI_priv_data *priv; int channels = xpd->channels; xpp_line_t mask = BITMASK(xpd->channels); + uint pcm_len; + unsigned long flags; priv = xpd->priv; if(priv->is_cas) { - /* CAS: Don't send PCM to D-Channel */ - channels--; - mask &= ~BIT(PRI_DCHAN_IDX(priv)); + if(priv->pri_protocol == PRI_PROTO_E1) { + /* CAS: Don't send PCM to D-Channel */ + channels--; + mask &= ~BIT(PRI_DCHAN_IDX(priv)); + } } - xpd->pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + channels * DAHDI_CHUNKSIZE; - xpd->wanted_pcm_mask = mask; + pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + channels * DAHDI_CHUNKSIZE; + spin_lock_irqsave(&xpd->lock_recompute_pcm, flags); + update_wanted_pcm_mask(xpd, mask, pcm_len); + spin_unlock_irqrestore(&xpd->lock_recompute_pcm, flags); } /* @@ -497,7 +534,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto) case PRI_PROTO_E1: deflaw = DAHDI_LAW_ALAW; dchan_num = 16; - default_lineconfig = DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_HDB3; + default_lineconfig = DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_HDB3; break; case PRI_PROTO_T1: deflaw = DAHDI_LAW_MULAW; @@ -519,6 +556,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto) return -EINVAL; } priv->pri_protocol = set_proto; + priv->is_cas = -1; xpd->channels = pri_num_channels(set_proto); pri_pcm_update(xpd); priv->deflaw = deflaw; @@ -610,7 +648,7 @@ static void set_clocking(xpd_t *xpd) } /* Now set it */ if(best_xpd && ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) { - byte reg_pc_init[] = { VAL_PC_SYPR, VAL_PC_GPI, VAL_PC_GPI }; + byte reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI }; for(i = 0; i < ARRAY_SIZE(reg_pc_init); i++) { byte reg_pc = reg_pc_init[i]; @@ -703,7 +741,7 @@ static const struct { const int flags; } valid_spanconfigs[sizeof(unsigned int)*8] = { /* These apply to T1 */ -// VALID_CONFIG(4, DAHDI_CONFIG_D4, "D4"), FIXME: should support + VALID_CONFIG(4, DAHDI_CONFIG_D4, "D4"), VALID_CONFIG(5, DAHDI_CONFIG_ESF, "ESF"), VALID_CONFIG(6, DAHDI_CONFIG_AMI, "AMI"), VALID_CONFIG(7, DAHDI_CONFIG_B8ZS, "B8ZS"), @@ -713,6 +751,78 @@ static const struct { VALID_CONFIG(10, DAHDI_CONFIG_CRC4, "CRC4"), }; +/* + * Mark the lines as CLEAR or RBS signalling. + * With T1, we need to mark the CLEAR lines on the REG_CCB1_T registers + * Should be called only when we are registered to DAHDI + * The channo parameter: + * channo == 0: set lines for the whole span + * channo != 0: only set modified lines + */ +static void set_rbslines(xpd_t *xpd, int channo) +{ + struct PRI_priv_data *priv; + xpp_line_t new_rbslines = 0; + xpp_line_t modified_lines; + int i; + + priv = xpd->priv; + for_each_line(xpd, i) { + struct dahdi_chan *chan = XPD_CHAN(xpd, i); + + if(chan->flags & DAHDI_FLAG_CLEAR) + BIT_CLR(new_rbslines, i); + else + BIT_SET(new_rbslines, i); + } + new_rbslines &= BITMASK(xpd->channels); + modified_lines = priv->rbslines ^ new_rbslines; + XPD_DBG(DEVICES, xpd, "RBSLINES-%d(%s): 0x%X\n", + channo, pri_protocol_name(priv->pri_protocol), new_rbslines); + if((priv->pri_protocol == PRI_PROTO_T1) || (priv->pri_protocol == PRI_PROTO_J1)) { + byte clear_lines = 0; /* Mark clear lines */ + bool reg_changed = 0; + + for_each_line(xpd, i) { + int bytenum = i / 8; + int bitnum = i % 8; + + if(!IS_SET(new_rbslines, i)) { + BIT_SET(clear_lines, (7 - bitnum)); + } + if(IS_SET(modified_lines, i)) + reg_changed = 1; + if(bitnum == 7) { + if(channo == 0 || reg_changed) { + bytenum += REG_CCB1_T; + XPD_DBG(DEVICES, xpd, "RBS(%s): modified=0x%X rbslines=0x%X reg=0x%X clear_lines=0x%X\n", + pri_protocol_name(priv->pri_protocol), + modified_lines, new_rbslines, bytenum, clear_lines); + write_subunit(xpd, bytenum, clear_lines); + } + clear_lines = 0; + reg_changed = 0; + } + } + } + priv->rbslines = new_rbslines; +} + +static int set_mode_cas(xpd_t *xpd, bool want_cas) +{ + struct PRI_priv_data *priv; + + priv = xpd->priv; + XPD_INFO(xpd, "Setting TDM to %s\n", (want_cas) ? "CAS" : "PRI"); + if(want_cas) { + priv->is_cas = 1; + priv->dchan_alive = 0; + } else { + priv->is_cas = 0; + } + return 0; +} + static int pri_lineconfig(xpd_t *xpd, int lineconfig) { struct PRI_priv_data *priv; @@ -723,15 +833,14 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) byte rc0 = 0; /* FIXME: PCM offsets */ #endif byte fmr0 = 0; - byte fmr1 = - REG_FMR1_AFR | - REG_FMR1_ECM; + byte fmr1 = REG_FMR1_ECM; byte fmr2 = 0; byte fmr3 = 0; /* write only for CRC4 */ byte fmr4 = 0; - byte imr0 = 0; - byte xsp = 0; + byte cmdr = REG_CMDR_RRES | REG_CMDR_XRES; + byte xsp = 0; unsigned int bad_bits; + bool force_cas = 0; int i; BUG_ON(!xpd); @@ -767,6 +876,7 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) if(bad_bits) goto bad_lineconfig; if(priv->pri_protocol == PRI_PROTO_E1) { + fmr1 |= REG_FMR1_AFR; fmr2 = REG_FMR2_E_AXRA | REG_FMR2_E_ALMF; /* 0x03 */ fmr4 = 0x9F; /* E1.XSW: All spare bits = 1*/ xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; @@ -774,10 +884,13 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) fmr1 |= REG_FMR1_PMOD | REG_FMR1_T_CRC; fmr2 = REG_FMR2_T_SSP | REG_FMR2_T_AXRA; /* 0x22 */ fmr4 = 0x0C; - xsp |= REG_FMR5_T_XTM; + xsp &= ~REG_FMR5_T_XTM; + force_cas = 1; /* T1 - Chip always in CAS mode */ } else if(priv->pri_protocol == PRI_PROTO_J1) { fmr1 |= REG_FMR1_PMOD; fmr4 = 0x1C; + xsp &= ~REG_FMR5_T_XTM; + force_cas = 1; /* T1 - Chip always in CAS mode */ XPD_ERR(xpd, "J1 unsupported yet\n"); return -ENOSYS; } @@ -790,6 +903,22 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) } else if (lineconfig & DAHDI_CONFIG_AMI) { framingstr = "AMI"; fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_RC1; + /* + * From Infineon Errata Sheet: PEF 22554, Version 3.1 + * Problem: Incorrect CAS Receiption when + * using AMI receive line code + * Workaround: For E1, + * "...The receive line coding HDB3 is + * recommended instead." + * For T1, + * "...in T1 mode it is recommended to + * configure the Rx side to B8ZS coding" + * For both cases this is the same bit in FMR0 + */ + if(priv->pri_protocol == PRI_PROTO_J1) + XPD_NOTICE(xpd, "J1 is not supported yet\n"); + else + fmr0 |= REG_FMR0_E_RC0; } else if (lineconfig & DAHDI_CONFIG_HDB3) { framingstr = "HDB3"; fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0; @@ -798,23 +927,21 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) return -EINVAL; } /* then coding */ + priv->is_esf = 0; if (lineconfig & DAHDI_CONFIG_ESF) { codingstr = "ESF"; - priv->is_cas = 0; fmr4 |= REG_FMR4_FM1; fmr2 |= REG_FMR2_T_AXRA | REG_FMR2_T_MCSP | REG_FMR2_T_SSP; + priv->is_esf = 1; } else if (lineconfig & DAHDI_CONFIG_D4) { codingstr = "D4"; - priv->is_cas = 0; } else if (lineconfig & DAHDI_CONFIG_CCS) { codingstr = "CCS"; - priv->is_cas = 0; - /* do nothing */ - } else { /* CAS */ - codingstr = "CAS"; - imr0 |= REG_IMR0_E_CASC; - xsp |= REG_XSP_E_CASEN; - priv->is_cas = 1; + set_mode_cas(xpd, 0); /* In E1 we know right from the span statement. */ + } else { + codingstr = "CAS"; /* In E1 we know right from the span statement. */ + force_cas = 1; + set_mode_cas(xpd, 1); } pri_pcm_update(xpd); /* @@ -842,20 +969,23 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig) write_subunit(xpd, REG_FMR0, fmr0); XPD_DBG(GENERAL, xpd, "%s: fmr4(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR4, fmr4); write_subunit(xpd, REG_FMR4, fmr4); - XPD_DBG(GENERAL, xpd, "%s: xsp(0x%02X) = 0x%02X\n", __FUNCTION__, REG_XSP_E, xsp); - write_subunit(xpd, REG_XSP_E, xsp); if(fmr3) { XPD_DBG(GENERAL, xpd, "%s: fmr3(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR3, fmr3); write_subunit(xpd, REG_FMR3, fmr3); } + XPD_DBG(GENERAL, xpd, "%s: cmdr(0x%02X) = 0x%02X\n", __FUNCTION__, REG_CMDR_E, cmdr); + write_subunit(xpd, REG_CMDR_E, cmdr); #ifdef JAPANEZE_SUPPORT if(rc0) { XPD_DBG(GENERAL, xpd, "%s: rc0(0x%02X) = 0x%02X\n", __FUNCTION__, REG_RC0, rc0); write_subunit(xpd, REG_RC0, rc0); } #endif - XPD_DBG(GENERAL, xpd, "%s: imr0(0x%02X) = 0x%02X\n", __FUNCTION__, REG_IMR0_E, imr0); - write_subunit(xpd, REG_IMR0_E, imr0); + if(force_cas) { + xsp |= REG_XSP_E_CASEN; /* Same as REG_FMR5_T_EIBR for T1 */ + } + XPD_DBG(GENERAL, xpd, "%s: xsp(0x%02X) = 0x%02X\n", __FUNCTION__, REG_XSP_E, xsp); + write_subunit(xpd, REG_XSP_E, xsp); return 0; bad_lineconfig: XPD_ERR(xpd, "Bad lineconfig. Abort\n"); @@ -902,7 +1032,43 @@ static int pri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) */ static int pri_chanconfig(struct dahdi_chan *chan, int sigtype) { + xpd_t *xpd; + struct PRI_priv_data *priv; + + xpd = chan->span->pvt; + BUG_ON(!xpd); + priv = xpd->priv; DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype)); + /* + * Some bookkeeping to check if we have DChan defined or not + * FIXME: actually use this to prevent duplicate DChan definitions + * and prevent DChan definitions with CAS. + */ + if(is_sigtype_dchan(sigtype)) { + if(VALID_DCHAN(priv) && DCHAN(priv) != chan->channo) { + ERR("channel %d (%s) marked DChan but also channel %d.\n", + chan->channo, chan->name, DCHAN(priv)); + return -EINVAL; + } else { + XPD_DBG(GENERAL, xpd, "channel %d (%s) marked as DChan\n", chan->channo, chan->name); + SET_DCHAN(priv, chan->channo); + /* In T1, we don't know before-hand */ + if(priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0) + set_mode_cas(xpd, 0); + } + } else { + if(chan->channo == 1) { + XPD_DBG(GENERAL, xpd, "channel %d (%s) marked a not DChan\n", chan->channo, chan->name); + SET_DCHAN(priv, NO_DCHAN); + } + /* In T1, we don't know before-hand */ + if(priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 1) + set_mode_cas(xpd, 1); + } + if(xpd->span.flags & DAHDI_FLAG_RUNNING) { + XPD_DBG(DEVICES, xpd, "Span is RUNNING. Updating rbslines.\n"); + set_rbslines(xpd, chan->channo); + } // FIXME: sanity checks: // - should be supported (within the sigcap) // - should not replace fxs <->fxo ??? (covered by previous?) @@ -957,6 +1123,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) if(ret < 0) goto err; } + SET_DCHAN(priv, NO_DCHAN); /* * initialization script should have set correct * operating modes. @@ -968,7 +1135,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) xpd->type_name = type_name(priv->pri_protocol); xpd->direction = TO_PSTN; XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name); - xpd->timing_priority = 1; /* SLAVE */ + xpd->timing_priority = 1; /* High priority SLAVE */ set_master_mode(__FUNCTION__, xpd); for(ret = 0; ret < NUM_LEDS; ret++) { DO_LED(xpd, ret, PRI_LED_ON); @@ -1030,13 +1197,14 @@ static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on) xpd->type_name, xbus->num, xpd->addr.unit, xpd->addr.subunit, i); cur_chan->chanpos = i + 1; cur_chan->pvt = xpd; + cur_chan->sigcap = PRI_SIGCAP; if(is_dchan && !priv->is_cas) { /* D-CHAN */ - cur_chan->sigcap = PRI_DCHAN_SIGCAP; //FIXME: cur_chan->flags |= DAHDI_FLAG_PRIDCHAN; cur_chan->flags &= ~DAHDI_FLAG_HDLC; - } else - cur_chan->sigcap = PRI_BCHAN_SIGCAP; + } } + if(!priv->is_cas) + clear_bit(DAHDI_FLAGBIT_RBS, &xpd->span.flags); xpd->offhook_state = xpd->wanted_pcm_mask; xpd->span.spanconfig = pri_spanconfig; xpd->span.chanconfig = pri_chanconfig; @@ -1060,12 +1228,6 @@ static int PRI_card_dahdi_postregistration(xpd_t *xpd, bool on) return(0); } -static int PRI_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig txsig) -{ - LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); - return 0; -} - static void dchan_state(xpd_t *xpd, bool up) { struct PRI_priv_data *priv; @@ -1073,6 +1235,9 @@ static void dchan_state(xpd_t *xpd, bool up) BUG_ON(!xpd); priv = xpd->priv; BUG_ON(!priv); + if(priv->is_cas) { + return; + } if(priv->dchan_alive == up) return; if(!priv->layer1_up) /* No layer1, kill dchan */ @@ -1207,6 +1372,8 @@ static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a * call. Silently ignore it. */ LINE_DBG(SIGNAL, xpd, pos, "PRI: Starting a call\n"); + /* fall-through */ + case DAHDI_ONHOOKTRANSFER: return -ENOTTY; default: report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); @@ -1240,6 +1407,7 @@ static int pri_startup(struct dahdi_span *span) XPD_DBG(GENERAL, xpd, "STARTUP\n"); // Turn on all channels CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); + set_rbslines(xpd, 0); return 0; } @@ -1264,31 +1432,19 @@ static int pri_shutdown(struct dahdi_span *span) return 0; } -static int pri_rbsbits(struct dahdi_chan *chan, int bits) +static int encode_rbsbits_e1(xpd_t *xpd, int pos, int bits) { - xpd_t *xpd; struct PRI_priv_data *priv; - int pos; byte val; int reg_pos; int regnum; unsigned long flags; - xpd = chan->pvt; BUG_ON(!xpd); - pos = chan->chanpos - 1; priv = xpd->priv; BUG_ON(!priv); - if(!priv->layer1_up) { - XPD_DBG(SIGNAL, xpd, "RBS: TX: No layer1. Ignore.\n"); - return 0; - } - if(priv->pri_protocol != PRI_PROTO_E1) { - XPD_NOTICE(xpd, "%s: protocol %s is not supported yet with CAS\n", - __FUNCTION__, pri_protocol_name(priv->pri_protocol)); - return 0; - } + BUG_ON(priv->pri_protocol != PRI_PROTO_E1); if(pos == 15) return 0; /* Don't write dchan in CAS */ if(pos < 0 || pos > 31) { @@ -1307,7 +1463,6 @@ static int pri_rbsbits(struct dahdi_chan *chan, int bits) } regnum = REG_RS2_E + reg_pos; priv->cas_ts_e[reg_pos] = val; - priv->dchan_tx_counter++; spin_unlock_irqrestore(&xpd->lock, flags); LINE_DBG(SIGNAL, xpd, pos, "RBS: TX: bits=0x%X (reg=0x%X val=0x%02X)\n", bits, regnum, val); @@ -1315,6 +1470,94 @@ static int pri_rbsbits(struct dahdi_chan *chan, int bits) return 0; } +static int encode_rbsbits_t1(xpd_t *xpd, int pos, int bits) +{ + struct PRI_priv_data *priv; + int rsnum; + int chan_per_reg; + int offset; + int width; + uint tx_bits = bits; + uint mask; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + BUG_ON(priv->pri_protocol != PRI_PROTO_T1); + if(pos < 0 || pos >= xpd->channels) { + XPD_ERR(xpd, "%s: Bad pos=%d\n", __FUNCTION__, pos); + return 0; + } + chan_per_reg = CHAN_PER_REGS(priv); + width = 8 / chan_per_reg; + rsnum = pos / chan_per_reg; + offset = pos % chan_per_reg; + mask = BITMASK(width) << (chan_per_reg - offset - 1) * width; + if (!priv->is_esf) + tx_bits >>= 2; + tx_bits &= BITMASK(width); + tx_bits <<= (chan_per_reg - offset - 1) * width; + if((priv->cas_ts_e[rsnum] & mask) == tx_bits) { +#if 0 + LINE_DBG(SIGNAL, xpd, pos, "RBS: TX: RS%02d(0x%02X, 0x%02X): REPEAT 0x%02X\n", + rsnum+1, mask, tx_bits, bits); +#endif + return 0; + } + priv->cas_ts_e[rsnum] &= ~mask; + priv->cas_ts_e[rsnum] |= tx_bits; + LINE_DBG(SIGNAL, xpd, pos, + "bits=0x%02X RS%02d(%s) offset=%d tx_bits=0x%02X\n", + bits, rsnum+1, + (priv->is_esf) ? "esf" : "d4", + offset, tx_bits); + write_subunit(xpd, REG_RS1_E + rsnum , priv->cas_ts_e[rsnum]); + if (!priv->is_esf) { + /* same data should be copied to RS7..12 in D4 only */ + write_subunit(xpd, REG_RS7_E + rsnum , priv->cas_ts_e[rsnum]); + } + priv->dchan_tx_counter++; + return 0; +} + +static int pri_rbsbits(struct dahdi_chan *chan, int bits) +{ + xpd_t *xpd; + struct PRI_priv_data *priv; + int pos; + + xpd = chan->pvt; + BUG_ON(!xpd); + pos = chan->chanpos - 1; + priv = xpd->priv; + BUG_ON(!priv); + if(!priv->layer1_up) { + XPD_DBG(SIGNAL, xpd, "RBS: TX: No layer1. Ignore.\n"); + } + if(!priv->is_cas) { + XPD_NOTICE(xpd, "RBS: TX: not in CAS mode. Ignore.\n"); + return 0; + } + if (chan->sig == DAHDI_SIG_NONE) { + LINE_DBG(SIGNAL, xpd, pos, + "RBS: TX: sigtyp=%s. , bits=0x%X. Ignore.\n", + sig2str(chan->sig), bits); + return 0; + } + if(priv->pri_protocol == PRI_PROTO_E1) { + if(encode_rbsbits_e1(xpd, pos, bits) < 0) + return -EINVAL; + } else if(priv->pri_protocol == PRI_PROTO_T1) { + if(encode_rbsbits_t1(xpd, pos, bits) < 0) + return -EINVAL; + } else { + XPD_NOTICE(xpd, "%s: protocol %s is not supported yet with CAS\n", + __FUNCTION__, pri_protocol_name(priv->pri_protocol)); + return -EINVAL; + } + return 0; +} + /*! Copy PCM chunks from the buffers of the xpd to a new packet * \param xbus xbus of source xpd. * \param xpd source xpd. @@ -1491,6 +1734,7 @@ static void layer1_state(xpd_t *xpd, byte data_low) { struct PRI_priv_data *priv; int alarms = 0; + int layer1_up_prev; BUG_ON(!xpd); priv = xpd->priv; @@ -1502,6 +1746,7 @@ static void layer1_state(xpd_t *xpd, byte data_low) alarms |= DAHDI_ALARM_BLUE; if(data_low & REG_FRS0_RRA) alarms |= DAHDI_ALARM_YELLOW; + layer1_up_prev = priv->layer1_up; priv->layer1_up = alarms == 0; #if 0 /* @@ -1513,8 +1758,18 @@ static void layer1_state(xpd_t *xpd, byte data_low) priv->layer1_up = 0; #endif priv->alarms = alarms; - if(!priv->layer1_up) + if(!priv->layer1_up) { dchan_state(xpd, 0); + } else if (priv->is_cas && !layer1_up_prev) { + int i; + int num_cas_rs = (priv->pri_protocol == PRI_PROTO_E1) ? + NUM_CAS_RS: NUM_CAS_RS_T; + XPD_DBG(SIGNAL , xpd, + "Returning From Alarm Refreshing Rx register data \n"); + for(i = 0; i < num_cas_rs; i++) + query_subunit(xpd, REG_RS1_E + i); + } + if(SPAN_REGISTERED(xpd) && xpd->span.alarms != alarms) { char str1[MAX_PROC_WRITE]; char str2[MAX_PROC_WRITE]; @@ -1533,7 +1788,7 @@ static void layer1_state(xpd_t *xpd, byte data_low) XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", xpd->addr.subunit, data_low); } -static void process_cas_dchan(xpd_t *xpd, byte regnum, byte data_low) +static int decode_cas_e1(xpd_t *xpd, byte regnum, byte data_low) { struct PRI_priv_data *priv; uint pos = regnum - REG_RS2_E; @@ -1542,13 +1797,27 @@ static void process_cas_dchan(xpd_t *xpd, byte regnum, byte data_low) int chan2 = pos + 16; priv = xpd->priv; - if(!priv->is_cas) - return; + BUG_ON(!priv->is_cas); + BUG_ON(priv->pri_protocol != PRI_PROTO_E1); + XPD_DBG(SIGNAL, xpd, "RBS: RX: data_low=0x%02X\n", data_low); if(pos < 0 || pos >= NUM_CAS_RS) { XPD_ERR(xpd, "%s: got bad pos=%d [0-%d]\n", __FUNCTION__, pos, NUM_CAS_RS); - return; + return -EINVAL; + } + if(chan1 < 0 || chan1 > xpd->channels) { + XPD_NOTICE(xpd, "%s: %s CAS: Bad chan1 number (%d)\n", + __FUNCTION__, + pri_protocol_name(priv->pri_protocol), + chan1); + return -EINVAL; + } + if(chan2 < 0 || chan2 > xpd->channels) { + XPD_NOTICE(xpd, "%s: %s CAS: Bad chan2 number (%d)\n", + __FUNCTION__, + pri_protocol_name(priv->pri_protocol), + chan2); + return -EINVAL; } - priv->cas_replies++; if(priv->cas_rs_e[pos] != data_low) { int old1 = (priv->cas_rs_e[pos] >> 4) & 0xF; int old2 = priv->cas_rs_e[pos] & 0xF; @@ -1556,7 +1825,7 @@ static void process_cas_dchan(xpd_t *xpd, byte regnum, byte data_low) int new2 = data_low & 0xF; XPD_DBG(SIGNAL, xpd, "RBS: RX: RS%02d (channel %2d, channel %2d): 0x%02X -> 0x%02X\n", - rsnum, chan1+1, chan2+1, priv->cas_rs_e[pos], data_low); + rsnum, chan1+1, chan2+1, priv->cas_rs_e[pos], data_low); if(SPAN_REGISTERED(xpd)) { if(old1 != new1) dahdi_rbsbits(XPD_CHAN(xpd, chan1), new1); @@ -1566,9 +1835,120 @@ static void process_cas_dchan(xpd_t *xpd, byte regnum, byte data_low) priv->dchan_rx_counter++; priv->cas_rs_e[pos] = data_low; } else { +#if 0 XPD_DBG(SIGNAL, xpd, "RBS: RX: RS%02d (channel %2d, channel %2d): REPEAT 0x%02X\n", rsnum, chan1+1, chan2+1, priv->cas_rs_e[pos]); +#endif + } + return 0; +} + +static int decode_cas_t1(xpd_t *xpd, byte regnum, byte data_low) +{ + struct PRI_priv_data *priv; + uint rsnum; + uint chan_per_reg; + uint width; + int i; + + priv = xpd->priv; + BUG_ON(!priv->is_cas); + BUG_ON(priv->pri_protocol != PRI_PROTO_T1); + rsnum = regnum - REG_RS1_E; + if(rsnum < 0 || rsnum >= 12) { + XPD_ERR(xpd, "Bad rsnum=%d\n", rsnum); + return 0; + } + if(!priv->is_esf) + rsnum = rsnum % 6; /* 2 identical banks of 6 registers */ + chan_per_reg = CHAN_PER_REGS(priv); + width = 8 / chan_per_reg; + if(priv->cas_rs_e[rsnum] == data_low) { +#if 0 + XPD_DBG(SIGNAL, xpd, "RBS: RX: RS%02d: REPEAT 0x%02X\n", + rsnum+1, data_low); +#endif + return 0; } + XPD_DBG(SIGNAL, xpd, + "RBS: RX(%s,%d): RS%02d data_low=0x%02X\n", + (priv->is_esf) ? "esf" : "d4", + chan_per_reg, + rsnum+1, data_low); + for(i = 0; i < chan_per_reg; i++) { + uint rxsig = (data_low >> (i * width)) & BITMASK(width); + int pos; + struct dahdi_chan *chan; + + if (!priv->is_esf) + rxsig <<= 2; + pos = rsnum * chan_per_reg + chan_per_reg - i - 1; + if(pos < 0 || pos >= xpd->channels) { + XPD_ERR(xpd, "%s: Bad pos=%d\n", __FUNCTION__, pos); + continue; + } + chan = XPD_CHAN(xpd, pos); + if(!chan) { + XPD_ERR(xpd, "%s: Null channel in pos=%d\n", __FUNCTION__, pos); + continue; + } + if(chan->rxsig != rxsig) { + LINE_DBG(SIGNAL, xpd, pos, "i=%d rxsig=0x%02X\n", i, rxsig); + dahdi_rbsbits(chan, rxsig); + } + } + priv->cas_rs_e[rsnum] = data_low; + return 0; +} + +static void process_cas_dchan(xpd_t *xpd, byte regnum, byte data_low) +{ + struct PRI_priv_data *priv; + + priv = xpd->priv; + if(!priv->is_cas) { + static int rate_limit; + + if((rate_limit++ % 10003) == 0) + XPD_NOTICE(xpd, "RBS: RX: not in CAS mode. Ignore.\n"); + return; + } + if(!priv->layer1_up) { + static int rate_limit; + + if((rate_limit++ % 10003) == 0) + XPD_DBG(SIGNAL, xpd, "RBS: RX: No layer1.\n"); + } + if(!SPAN_REGISTERED(xpd)) { + static int rate_limit; + + if((rate_limit++ % 10003) == 0) + XPD_DBG(SIGNAL, xpd, "RBS: RX: Span not registered. Ignore.\n"); + return; + } + if(priv->pri_protocol == PRI_PROTO_E1) { + if(regnum < REG_RS2_E) { + XPD_NOTICE(xpd, + "%s: received register 0x%X in protocol %s. Ignore\n", + __FUNCTION__, regnum, pri_protocol_name(priv->pri_protocol)); + return; + } + if(decode_cas_e1(xpd, regnum, data_low) < 0) + return; + } else if(priv->pri_protocol == PRI_PROTO_T1) { + if(regnum > REG_RS12_E) { + XPD_NOTICE(xpd, + "%s: received register 0x%X in protocol %s. Ignore\n", + __FUNCTION__, regnum, pri_protocol_name(priv->pri_protocol)); + return; + } + if(decode_cas_t1(xpd, regnum, data_low) < 0) + return; + } else { + XPD_NOTICE(xpd, "%s: protocol %s is not supported yet with CAS\n", + __FUNCTION__, pri_protocol_name(priv->pri_protocol)); + } + priv->cas_replies++; } static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) @@ -1607,7 +1987,7 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) else if(regnum == REG_FRS1 && !REG_FIELD(info, do_subreg)) priv->reg_frs1 = data_low; if(priv->is_cas && !REG_FIELD(info, do_subreg)) { - if(regnum >= REG_RS2_E && regnum <= REG_RS16_E) { + if(regnum >= REG_RS1_E && regnum <= REG_RS16_E) { process_cas_dchan(xpd, regnum, data_low); } } @@ -1638,7 +2018,6 @@ static xproto_table_t PROTO_TABLE(PRI) = { .card_remove = PRI_card_remove, .card_dahdi_preregistration = PRI_card_dahdi_preregistration, .card_dahdi_postregistration = PRI_card_dahdi_postregistration, - .card_hooksig = PRI_card_hooksig, .card_tick = PRI_card_tick, .card_pcm_recompute = generic_card_pcm_recompute, .card_pcm_fromspan = PRI_card_pcm_fromspan, diff --git a/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex b/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex index 6419870..7f6ca28 100644 --- a/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex +++ b/drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex @@ -1,6 +1,6 @@ # -# $Id: PIC_TYPE_4.hex 7107 2009-05-18 12:35:20Z dima $ -# +# $Id: PIC_TYPE_4.hex 7308 2009-08-11 13:34:58Z dima $ +# :03000000A0AA0AA9 :03000100C41C41DB :030002000390392F @@ -104,7 +104,7 @@ :03006400000C404D :030065000000395F :030066000007D9B7 -:03006700000AB6D6 +:03006700000ACCC0 :03006800000C0089 :030069000007D3BA :03006A00000A6C1D @@ -146,171 +146,199 @@ :03008E000006D792 :03008F0000010A63 :0300900000002C41 -:030091000007D392 -:03009200000AB1B0 -:03009300000C500E -:0300940000003930 -:03009500000799C8 -:03009600000A95C8 -:0300970000021252 -:0300980000003035 -:030099000002144E -:03009A0000003132 -:03009B000002134D -:03009C000000322F -:03009D00000C0054 -:03009E000000332C -:03009F00000C70E2 -:0300A00000003924 -:0300A100000C5000 -:0300A20000003922 -:0300A30000021543 -:0300A40000003029 -:0300A50000021640 -:0300A60000003126 -:0300A70000021044 -:0300A80000003223 -:0300A900000C0048 -:0300AA0000003320 -:0300AB00000C70D6 -:0300AC0000003918 -:0300AD00000C50F4 -:0300AE0000003916 -:0300AF00000C4002 -:0300B00000003914 -:0300B100000C0040 -:0300B20000003912 +:03009100000C1D43 +:03009200000195D5 +:0300930000074320 +:03009400000AA7B8 +:030095000006D38F +:03009600000AA7B6 +:03009700000C0159 +:0300980000002A3B +:0300990000020161 +:03009A00000E0352 +:03009B0000064319 +:03009C00000AA1B6 +:03009D0000036AF3 +:03009E000002C895 +:03009F00000D0051 +:0300A000000A9BB8 +:0300A100000CFF51 +:0300A20000018AD0 +:0300A30000015AFF +:0300A400000697BC +:0300A50000010A4D +:0300A60000003A1D +:0300A7000007D37C +:0300A800000AC784 +:0300A900000C50F8 +:0300AA000000391A +:0300AB00000799B2 +:0300AC00000AAB9C +:0300AD000002123C +:0300AE000000301F +:0300AF0000021438 +:0300B0000000311C +:0300B10000021337 +:0300B20000003219 :0300B300000C003E -:0300B400000C003D -:0300B500000A64DA -:0300B60000036DD7 -:0300B70000020440 -:0300B800000E0334 -:0300B900000743FA -:0300BA00000ABD7C -:0300BB00000C0135 -:0300BC0000002D14 -:0300BD00000C0034 -:0300BE0000002916 -:0300BF0000020438 -:0300C000000D80B0 -:0300C1000000211B -:0300C200000C62CD -:0300C30000002218 -:0300C40000020136 -:0300C50000003206 -:0300C60000020233 -:0300C70000003105 -:0300C8000002092A -:0300C90000003004 -:0300CA0000090129 -:0300CB0000020C24 -:0300CC0000014DE3 -:0300CD00000643E7 -:0300CE00000AD154 -:0300CF000002101C -:0300D000000AD251 -:0300D100000C0020 -:0300D20000002506 -:0300D30000020424 -:0300D400000D809C -:0300D50000002107 -:0300D600000C63B8 -:0300D70000002204 -:0300D80000020122 -:0300D900000032F2 -:0300DA000002021F -:0300DB00000031F1 -:0300DC0000020916 -:0300DD00000030F0 -:0300DE0000090115 -:0300DF0000020C10 -:0300E00000014DCF -:0300E100000643D3 -:0300E200000AE52C -:0300E30000021008 -:0300E400000AE629 -:0300E500000C000C -:0300E600000026F1 +:0300B40000003316 +:0300B500000C70CC +:0300B6000000390E +:0300B700000C50EA +:0300B8000000390C +:0300B9000002152D +:0300BA0000003013 +:0300BB000002162A +:0300BC0000003110 +:0300BD000002102E +:0300BE000000320D +:0300BF00000C0032 +:0300C0000000330A +:0300C100000C70C0 +:0300C20000003902 +:0300C300000C50DE +:0300C40000003900 +:0300C500000C40EC +:0300C600000039FE +:0300C700000C002A +:0300C800000039FC +:0300C900000C0028 +:0300CA00000C0027 +:0300CB00000A64C4 +:0300CC0000036DC1 +:0300CD000002042A +:0300CE00000E031E +:0300CF00000743E4 +:0300D000000AD350 +:0300D100000C011F +:0300D20000002DFE +:0300D300000C001E +:0300D40000002900 +:0300D50000020422 +:0300D600000D809A +:0300D70000002105 +:0300D800000C62B7 +:0300D90000002202 +:0300DA0000020120 +:0300DB00000032F0 +:0300DC000002021D +:0300DD00000031EF +:0300DE0000020914 +:0300DF00000030EE +:0300E00000090113 +:0300E10000020C0E +:0300E20000014DCD +:0300E300000643D1 +:0300E400000AE728 +:0300E50000021006 +:0300E600000AE825 :0300E700000C000A -:0300E800000027EE -:0300E900000C0107 -:0300EA00000145CD -:0300EB00000643C9 -:0300EC00000B1AEC -:0300ED00000C7094 -:0300EE000001C747 -:0300EF00000022EC -:0300F0000002010A -:0300F100000032DA -:0300F20000020207 -:0300F300000031D9 -:0300F400000209FE -:0300F500000030D8 -:0300F600000901FD -:0300F700000C50AA -:0300F800000039CC -:0300F90000079964 -:0300FA00000AF900 +:0300E800000025F0 +:0300E9000002040E +:0300EA00000D8086 +:0300EB00000021F1 +:0300EC00000C63A2 +:0300ED00000022EE +:0300EE000002010C +:0300EF00000032DC +:0300F00000020209 +:0300F100000031DB +:0300F20000020900 +:0300F300000030DA +:0300F400000901FF +:0300F50000020CFA +:0300F60000014DB9 +:0300F700000643BD +:0300F800000AFB00 +:0300F900000210F2 +:0300FA00000AFCFD :0300FB00000C00F6 -:0300FC00000030D1 -:0300FD00000204FA -:0300FE00000348B4 -:0300FF00000348B3 -:03010000000348B1 -:03010100000348B0 -:03010200000D05E8 -:03010300000031C8 -:03010400000C00EC -:03010500000032C5 -:03010600000C00EA -:03010700000033C2 -:03010800000C7078 -:03010900000039BA -:03010A00000C5096 -:03010B00000039B8 -:03010C00000202EC -:03010D00000030BF -:03010E00000C00E2 +:0300FC00000026DB +:0300FD0000021AE4 +:0300FE0000014DB1 +:0300FF00000643B5 +:03010000000B03EE +:03010100000C0FE0 +:0301020000016693 +:03010300000C00ED +:03010400000027D1 +:03010500000C01EA +:03010600000145B0 +:03010700000643AC +:03010800000B36B3 +:03010900000C7077 +:03010A000001C72A +:03010B00000022CF +:03010C00000201ED +:03010D00000032BD +:03010E00000202EA :03010F00000031BC -:03011000000210DA -:03011100000032B9 -:03011200000C00DE -:03011300000033B6 -:03011400000C706C -:03011500000039AE -:03011600000C508A -:03011700000039AC -:03011800000C4098 -:03011900000039AA -:03011A00000325BA -:03011B00000C01D4 -:03011C000001E7F8 -:03011D00000C08CB -:03011E0000008757 -:03011F0000074393 -:03012000000B23AE -:03012100000206D3 -:03012200000025B5 -:03012300000C10BD -:0301240000008751 -:030125000007438D -:03012600000AE9E3 -:03012700000C01C8 -:030128000001C40F -:03012900000E03C2 -:03012A00000024AE -:03012B00000208C7 -:03012C0000074386 -:03012D00000B368E -:03012E0000020BC1 -:03012F00000D8040 -:0301300000003498 -:03013100000C3A85 -:030132000002C800 -:03013300000B328C -:0301340000020BBB -:0301350000003493 -:03013600000A6458 -:03013700000B3783 +:03011000000209E1 +:03011100000030BB +:03011200000901E0 +:03011300000C508D +:03011400000039AF +:0301150000079947 +:03011600000B15C6 +:03011700000C00D9 +:03011800000030B4 +:03011900000204DD +:03011A0000034897 +:03011B0000034896 +:03011C0000034895 +:03011D0000034894 +:03011E00000D05CC +:03011F00000031AC +:03012000000C00D0 +:03012100000032A9 +:03012200000C00CE +:03012300000033A6 +:03012400000C705C +:030125000000399E +:03012600000C507A +:030127000000399C +:03012800000202D0 +:03012900000030A3 +:03012A00000C00C6 +:03012B00000031A0 +:03012C00000210BE +:03012D000000329D +:03012E00000C00C2 +:03012F000000339A +:03013000000C7050 +:0301310000003992 +:03013200000C506E +:0301330000003990 +:03013400000C407C +:030135000000398E +:030136000003259E +:03013700000C01B8 +:030138000001E7DC +:03013900000C08AF +:03013A000000873B +:03013B0000074377 +:03013C00000B3F76 +:03013D00000206B7 +:03013E0000002599 +:03013F00000C10A1 +:0301400000008735 +:0301410000074371 +:03014200000B05AA +:03014300000C01AC +:030144000001C4F3 +:03014500000E03A6 +:0301460000002492 +:03014700000208AB +:030148000007436A +:03014900000B5256 +:03014A0000020BA5 +:03014B00000D8024 +:03014C000000347C +:03014D00000C3A69 +:03014E000002C8E4 +:03014F00000B4E54 +:0301500000020B9F +:0301510000003477 +:03015200000A643C +:03015300000B534B :00000001FF diff --git a/drivers/dahdi/xpp/init_card_4_30 b/drivers/dahdi/xpp/init_card_4_30 index ea04545..7eae895 100755 --- a/drivers/dahdi/xpp/init_card_4_30 +++ b/drivers/dahdi/xpp/init_card_4_30 @@ -150,24 +150,25 @@ sub init_quad() { } sub finish_quad() { - PRI::gen "0 WD BB FF"; # REGFP - PRI::gen "0 WD BC AC"; # REGFD + PRI::gen "0 WD BB 2C"; # REGFP + PRI::gen "0 WD BC FF"; # REGFD + PRI::gen "0 WD BB AC"; # REGFP PRI::gen "0 WD BB 2B"; # REGFP PRI::gen "0 WD BC 00"; # REGFD PRI::gen "0 WD BB AB"; # REGFP - PRI::gen "0 WD BC 2A"; # REGFD - PRI::gen "0 WD BB FF"; # REGFP - PRI::gen "0 WD BC AA"; # REGFD + PRI::gen "0 WD BB 2A"; # REGFP + PRI::gen "0 WD BC FF"; # REGFD + PRI::gen "0 WD BB AA"; # REGFP PRI::gen "0 WD BB 29"; # REGFP PRI::gen "0 WD BC FF"; # REGFD PRI::gen "0 WD BB A9"; # REGFP - PRI::gen "0 WD BC 28"; # REGFD - PRI::gen "0 WD BB 00"; # REGFP - PRI::gen "0 WD BC A8"; # REGFD + PRI::gen "0 WD BB 28"; # REGFP + PRI::gen "0 WD BC 00"; # REGFD + PRI::gen "0 WD BB A8"; # REGFP PRI::gen "0 WD BB 27"; # REGFP PRI::gen "0 WD BC FF"; # REGFD PRI::gen "0 WD BB A7"; # REGFP - PRI::gen "0 WD BC 00"; # REGFD + PRI::gen "0 WD BB 00"; # REGFP # PRI::gen "0 WD 80 00"; # PC1 (Port configuration 1): RPB_1.SYPR , XPB_1.SYPX } @@ -291,10 +292,10 @@ sub port_setup($) { # clock on RCLK.*/ PRI::gen "$portno WD 22 00"; # XC0: (Transmit Counter Offset = 497/T=2) - PRI::gen "$portno WD 23 04"; # XC1: + PRI::gen "$portno WD 23 04"; # XC1: X=4 => T=4-X=0 offset PRI::gen "$portno WD 24 00"; # RC0: (Receive Counter Offset = 497/T=2) - PRI::gen "$portno WD 25 05"; # RC1: + PRI::gen "$portno WD 25 05"; # RC1: Remaining part of RC0 my $sic2 = sprintf("%x", 0x00 | ($portno << 1)); @@ -312,14 +313,7 @@ sub port_setup($) { PRI::gen "$portno WD 02 00"; # CMDR - # Configure interrupts - PRI::gen "$portno WD 46 40"; # GCR: Interrupt on Activation/Deactivation of AIX, LOS - PRI::gen "$portno WD 45 00"; # CMR2: External sources for SYPR, SCLKR, SYPX, SCLKX for TX and RX. - #PRI::gen "$portno WD 22 00"; # XC0: Normal operation of Sa-bits - #PRI::gen "$portno WD 23 04"; # XC1: X=4 => T=4-X=0 offset - #PRI::gen "$portno WD 24 00"; # RC0: 0 offset - #PRI::gen "$portno WD 25 00"; # RC1: Remaining part of RC0 # Configure ports PRI::gen "$portno WD 85 80"; # GPC1 (Global Port Configuration 1): @@ -328,7 +322,6 @@ sub port_setup($) { PRI::gen "$portno WD 80 00"; # PC1: SYPR/SYPX provided to RPA/XPA inputs PRI::gen "$portno WD 84 31"; # PC5: XMFS active low, SCLKR is input, RCLK is output (unused) - PRI::gen "$portno WD 86 03"; # PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R PRI::gen "$portno WD 3B 00"; # Clear LCR1 - Loop Code Register 1 # printk("TE110P: Successfully initialized serial bus for card\n"); diff --git a/drivers/dahdi/xpp/xbus-pcm.c b/drivers/dahdi/xpp/xbus-pcm.c index 99f9c03..81efba0 100644 --- a/drivers/dahdi/xpp/xbus-pcm.c +++ b/drivers/dahdi/xpp/xbus-pcm.c @@ -604,6 +604,17 @@ void elect_syncer(const char *msg) update_sync_master(the_xbus, force_dahdi_sync); } +/* + * This function should be called with the xpd already locked + */ +void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len) +{ + xpd->pcm_len = new_pcm_len; + xpd->wanted_pcm_mask = new_mask; + XPD_DBG(SIGNAL, xpd, "pcm_len=%d wanted_pcm_mask=0x%X\n", + xpd->pcm_len, xpd->wanted_pcm_mask); +} + /* * This function is used by FXS/FXO. The pcm_mask argument signifies * channels which should be *added* to the automatic calculation. @@ -614,6 +625,7 @@ void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask) int i; int line_count = 0; unsigned long flags; + uint pcm_len; spin_lock_irqsave(&xpd->lock_recompute_pcm, flags); //XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask); @@ -633,12 +645,10 @@ void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask) pcm_mask = BIT(0); line_count = 1; } - xpd->pcm_len = (line_count) + pcm_len = (line_count) ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE : 0L; - xpd->wanted_pcm_mask = pcm_mask; - XPD_DBG(SIGNAL, xpd, "pcm_len=%d wanted_pcm_mask=0x%X\n", - xpd->pcm_len, xpd->wanted_pcm_mask); + update_wanted_pcm_mask(xpd, pcm_mask, pcm_len); spin_unlock_irqrestore(&xpd->lock_recompute_pcm, flags); } @@ -1258,6 +1268,7 @@ EXPORT_SYMBOL(elect_syncer); #ifdef DAHDI_SYNC_TICK EXPORT_SYMBOL(dahdi_sync_tick); #endif +EXPORT_SYMBOL(update_wanted_pcm_mask); EXPORT_SYMBOL(generic_card_pcm_recompute); EXPORT_SYMBOL(generic_card_pcm_tospan); EXPORT_SYMBOL(generic_card_pcm_fromspan); diff --git a/drivers/dahdi/xpp/xbus-pcm.h b/drivers/dahdi/xpp/xbus-pcm.h index 093ea60..bd9e5fa 100644 --- a/drivers/dahdi/xpp/xbus-pcm.h +++ b/drivers/dahdi/xpp/xbus-pcm.h @@ -103,6 +103,7 @@ void xbus_pcm_shutdown(void); int send_pcm_frame(xbus_t *xbus, xframe_t *xframe); void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask); void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe); +void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len); void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask); void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); diff --git a/drivers/dahdi/xpp/xpp_dahdi.c b/drivers/dahdi/xpp/xpp_dahdi.c index 6e7ee85..33fb137 100644 --- a/drivers/dahdi/xpp/xpp_dahdi.c +++ b/drivers/dahdi/xpp/xpp_dahdi.c @@ -940,6 +940,12 @@ static int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) __FUNCTION__, pos); return -ENODEV; } + if(!xpd->xops->card_hooksig) { + LINE_ERR(xpd, pos, + "%s: No hooksig method for this channel. Ignore.\n", + __FUNCTION__); + return -ENODEV; + } xbus = xpd->xbus; BUG_ON(!xbus); DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig); @@ -1081,7 +1087,8 @@ int dahdi_register_xpd(xpd_t *xpd) span->open = xpp_open; span->close = xpp_close; span->flags = DAHDI_FLAG_RBS; - span->hooksig = xpp_hooksig; /* Only with RBS bits */ + if(xops->card_hooksig) + span->hooksig = xpp_hooksig; /* Only with RBS bits */ span->ioctl = xpp_ioctl; span->maint = xpp_maint; /* diff --git a/drivers/dahdi/xpp/xproto.c b/drivers/dahdi/xpp/xproto.c index 70f82d5..4ae64f9 100644 --- a/drivers/dahdi/xpp/xproto.c +++ b/drivers/dahdi/xpp/xproto.c @@ -446,7 +446,6 @@ int xproto_register(const xproto_table_t *proto_table) CHECK_XOP(card_pcm_tospan); CHECK_XOP(card_dahdi_preregistration); CHECK_XOP(card_dahdi_postregistration); - CHECK_XOP(card_hooksig); // CHECK_XOP(card_ioctl); // optional method -- call after testing CHECK_XOP(card_register_reply); CHECK_XOP(XPD_STATE); -- cgit v1.2.3