summaryrefslogtreecommitdiff
path: root/xpp/card_bri.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/card_bri.c')
-rw-r--r--xpp/card_bri.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/xpp/card_bri.c b/xpp/card_bri.c
index fecaee9..ad10aed 100644
--- a/xpp/card_bri.c
+++ b/xpp/card_bri.c
@@ -40,8 +40,8 @@ static const char rcsid[] = "$Id$";
#error CONFIG_ZAPATA_BRI_DCHANS is not defined
#endif
-DEF_PARM(int, print_dbg, 0, 0600, "Print DBG statements"); /* must be before zap_debug.h */
-DEF_PARM(uint, poll_interval, 100, 0600, "Poll channel state interval in milliseconds (0 - disable)");
+DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */
+DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)");
enum xhfc_states {
ST_RESET = 0, /* G/F0 */
@@ -129,6 +129,8 @@ typedef union {
byte reg;
} su_rd_sta_t;
+#define REG30_LOST 3 /* in polls */
+
#define BRI_DCHAN_SIGCAP ( \
ZT_SIG_EM | \
ZT_SIG_CLEAR | \
@@ -165,6 +167,15 @@ enum led_state {
BRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */
};
+#define LED_STATE_NAME(x) [ BRI_ ## x ] = #x
+static const char *led_state_names[] = {
+ LED_STATE_NAME(LED_OFF),
+ LED_STATE_NAME(LED_ON),
+ LED_STATE_NAME(LED_BLINK_SLOW),
+ LED_STATE_NAME(LED_BLINK_FAST),
+};
+#undef LED_STATE_NAME
+
enum bri_led_names {
GREEN_LED = 0,
RED_LED = 1
@@ -194,7 +205,7 @@ struct BRI_priv_data {
int t4; /* timer 4 for deactivation */
ulong l1_flags;
bool reg30_good;
- ulong last_reg30_reply;
+ uint reg30_ticks;
/*
* D-Chan: buffers + extra state info.
@@ -225,7 +236,7 @@ static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, bool red_led, enum led_state to_led_
static /* 0x0F */ DECLARE_CMD(BRI, REGISTER_REQUEST, byte chipsel, bool writing, bool do_subreg, byte regnum, byte subreg, byte data_low, byte data_high);
#define DEBUG_BUF_SIZE (100)
-static void dump_hex_buf(xpd_t *xpd, char *msg, byte *buf, int len)
+static void dump_hex_buf(xpd_t *xpd, char *msg, byte *buf, size_t len)
{
char debug_buf[DEBUG_BUF_SIZE + 1];
int i;
@@ -372,6 +383,7 @@ static int send_bri_multibyte(xpd_t *xpd, byte *buf, int len, bool eoftx)
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
+ int ret;
BUG_ON(len < 0);
/*
@@ -400,7 +412,10 @@ static int send_bri_multibyte(xpd_t *xpd, byte *buf, int len, bool eoftx)
if(print_dbg)
dump_xframe("SEND_BRI_MULTI", xbus, xframe);
#endif
- return xframe_send(xbus, xframe);
+ ret = xframe_send(xbus, xframe);
+ if(ret < 0)
+ NOTICE("%s: %s: failed sending xframe\n", __FUNCTION__, xbus->busname);
+ return ret;
}
/*
@@ -412,6 +427,7 @@ static int tx_dchan(xpd_t *xpd)
struct zt_chan *dchan;
int len;
int eoframe;
+ int ret;
priv = xpd->priv;
BUG_ON(!priv);
@@ -463,7 +479,11 @@ static int tx_dchan(xpd_t *xpd)
priv->txframe_begin = 1;
else
priv->txframe_begin = 0;
- return send_bri_multibyte(xpd, priv->dchan_tbuf, len, eoframe);
+ ret = send_bri_multibyte(xpd, priv->dchan_tbuf, len, eoframe);
+ if(ret < 0)
+ NOTICE("%s/%s: %s: failed sending xframe\n",
+ __FUNCTION__, xpd->xbus->busname, xpd->xpdname);
+ return ret;
}
/*---------------- BRI: Methods -------------------------------------------*/
@@ -539,7 +559,7 @@ static int BRI_card_init(xbus_t *xbus, xpd_t *xpd)
* FPGA firmware limitation:
* Force HOST sync *before* sending PCM
*/
- CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, 1, 0);
+ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_HOST, 0);
DBG("done: %s/%s\n", xbus->busname, xpd->xpdname);
priv->initialized = 1;
CALL_PROTO(BRI, SET_LED, xbus, xpd, GREEN_LED, BRI_LED_ON);
@@ -656,9 +676,10 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
if((priv->tick_counter % LED_TICKS) == 0) {
int i;
- if(priv->reg30_good && time_before(priv->last_reg30_reply + HZ/2, jiffies)) {
+ if(priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) {
/* No reply for 1/2 a second */
- ERR("%s/%s: Lost state tracking\n", xbus->busname, xpd->xpdname);
+ ERR("%s/%s: Lost state tracking for %d ticks\n",
+ xbus->busname, xpd->xpdname, priv->reg30_ticks);
priv->reg30_good = 0;
}
if(!priv->reg30_good) {
@@ -676,6 +697,7 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
}
tx_dchan(xpd);
priv->tick_counter++;
+ priv->reg30_ticks++;
return 0;
}
@@ -694,6 +716,7 @@ static int BRI_card_close(xpd_t *xpd, lineno_t pos)
static int BRI_span_startup(xpd_t *xpd)
{
struct BRI_priv_data *priv;
+ struct zt_chan *dchan;
BUG_ON(!xpd);
priv = xpd->priv;
@@ -701,8 +724,18 @@ static int BRI_span_startup(xpd_t *xpd)
DBG("%s/%s: STARTUP\n", xpd->xbus->busname, xpd->xpdname);
write_state_register(xpd, 0); /* Enable L1 state machine */
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1);
- if(SPAN_REGISTERED(xpd))
+ if(SPAN_REGISTERED(xpd)) {
+ dchan = &xpd->span.chans[2];
xpd->span.flags |= ZT_FLAG_RUNNING;
+ /*
+ * Zaptel (wrongly) assume that D-Channel need HDLC decoding
+ * and during zaptel registration override our flags.
+ *
+ * Don't Get Mad, Get Even: Now we override zaptel :-)
+ */
+ dchan->flags |= ZT_FLAG_BRIDCHAN;
+ dchan->flags &= ~ZT_FLAG_HDLC;
+ }
return 0;
}
@@ -817,8 +850,9 @@ static int BRI_span_shutdown(xpd_t *xpd)
BUG_ON(!priv);
XFRAME_NEW(xframe, pack, xbus, BRI, SET_LED, xpd->id);
#if 1
- DBG("%s/%s: %s %d\n", xbus->busname, xpd->xpdname,
- (red_led)?"RED":"GREEN", to_led_state);
+ DBG("%s/%s: %s %s (%d)\n", xbus->busname, xpd->xpdname,
+ (red_led)?"RED":"GREEN",
+ led_state_names[to_led_state], to_led_state);
#endif
bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds);
bri_leds->state = to_led_state;
@@ -860,7 +894,7 @@ static void su_new_state(xpd_t *xpd, byte reg_x30)
BUG_ON(!priv);
xbus = xpd->xbus;
new_state.reg = reg_x30;
- priv->last_reg30_reply = jiffies;
+ priv->reg30_ticks = 0;
priv->reg30_good = 1;
if((xpd->type == XPD_TYPE_BRI_TE && new_state.bits.v_su_sta == ST_TE_ACTIVATED) ||
(xpd->type == XPD_TYPE_BRI_NT && new_state.bits.v_su_sta == ST_NT_ACTIVATED)) {
@@ -868,7 +902,17 @@ static void su_new_state(xpd_t *xpd, byte reg_x30)
update_xpd_status(xpd, ZT_ALARM_NONE);
} else {
priv->ledcontrol[which_led] = BRI_LED_OFF;
+ /*
+ * Do NOT notify Zaptel about the disconnection.
+ * If we do, Asterisk stops transmitting on the D-channel and
+ * we can't reactivate layer-1.
+ * Without the notification, Asterisk thinks that we are active
+ * (although the PSTN stopped layer-1) and on call setup, sends
+ * us D-channel data, which triggers the layer-1 activation.
+ */
+#if 0
update_xpd_status(xpd, ZT_ALARM_RED);
+#endif
}
if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta)
return; /* same same */
@@ -1098,7 +1142,7 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in
} else
len += sprintf(page + len, "Unkown\n");
len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter);
- len += sprintf(page + len, "Last Poll Reply at: %ld\n", priv->last_reg30_reply);
+ len += sprintf(page + len, "Last Poll Reply: %d ticks ago\n", priv->reg30_ticks);
len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good);
len += sprintf(page + len, "Drop Counter: %d\n", priv->drop_counter);
for(led = 0; led < NUM_LEDS; led++) {