summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-11-04 21:45:55 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-11-04 21:45:55 +0000
commit303b8aadf67449b6633bac29135e2e8134fb8a97 (patch)
treeb4817a27c4f917e93958f67b65c3dfb3fc17d48c
parent8326c1faa72044e72fd4095cd9f8eec960633a7b (diff)
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
-rw-r--r--drivers/dahdi/xpp/card_bri.c11
-rw-r--r--drivers/dahdi/xpp/card_pri.c545
-rw-r--r--drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex360
-rwxr-xr-xdrivers/dahdi/xpp/init_card_4_3031
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.c19
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.h1
-rw-r--r--drivers/dahdi/xpp/xpp_dahdi.c9
-rw-r--r--drivers/dahdi/xpp/xproto.c1
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
@@ -605,6 +605,17 @@ void elect_syncer(const char *msg)
}
/*
+ * 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.
* Normally, this argument is 0.
@@ -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);