summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dahdi/wcb4xxp/base.c108
-rw-r--r--drivers/dahdi/wcb4xxp/wcb4xxp.h5
2 files changed, 77 insertions, 36 deletions
diff --git a/drivers/dahdi/wcb4xxp/base.c b/drivers/dahdi/wcb4xxp/base.c
index 4935fe6..15c065c 100644
--- a/drivers/dahdi/wcb4xxp/base.c
+++ b/drivers/dahdi/wcb4xxp/base.c
@@ -90,6 +90,7 @@ static int milliwatt = 0;
static int pedanticpci = 0;
static int teignorered = 0;
static int alarmdebounce = 500;
+static int persistentlayer1 = 1;
static int vpmsupport = 1;
static int timer_1_ms = 2000;
static int timer_3_ms = 30000;
@@ -139,7 +140,7 @@ static struct devtype hfc8s_BN = {"BeroNet BN8S0", .ports = 8, .card_type = BN8S
static struct devtype hfc4s_SW = {"Swyx 4xS0 SX2 QuadBri", .ports = 4, .card_type = BSWYX_SX2 };
static struct devtype hfc4s_EV = {"CCD HFC-4S Eval. Board", .ports = 4,
.card_type = QUADBRI_EVAL };
-
+
#define CARD_HAS_EC(card) ((card)->card_type == B410P)
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
@@ -1294,6 +1295,9 @@ static void hfc_force_st_state(struct b4xxp *b4, int port, int state, int resume
hfc_handle_state(&b4->spans[port]);
}
+static void hfc_stop_st(struct b4xxp_span *s);
+static void hfc_start_st(struct b4xxp_span *s);
+
/* figures out what to do when an S/T port's timer expires. */
static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
{
@@ -1307,10 +1311,15 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
s->hfc_timer_on[t_no]);
}
/*
- * there are three timers associated with every HFC S/T port.
- * T1 is used by the NT state machine, and is the maximum time the NT side should wait for G3 (active) state.
- * T2 is not actually used in the driver, it is handled by the HFC-4S internally.
- * T3 is used by the TE state machine; it is the maximum time the TE side should wait for the INFO4 (activated) signal.
+ * There are four timers associated with every HFC S/T port:
+ * T1 is used by the NT state machine, and is the maximum time the NT side
+ * should wait for G3 (active) state.
+ * T2 is not actually used in the driver, it is handled by the HFC-4S
+ * internally.
+ * T3 is used by the TE state machine; it is the maximum time the TE side should
+ * wait for the INFO4 (activated) signal.
+ * T4 is a special timer used for debug purposes for monitoring of L1 state
+ * during activation attempt.
*/
/* First, disable the expired timer; hfc_force_st_state() may activate it again. */
@@ -1324,7 +1333,14 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
hfc_force_st_state(b4, s->port, 1, 1);
break;
case HFC_T3: /* switch to F3 (deactivated), resume auto mode */
- hfc_force_st_state(b4, s->port, 3, 1);
+ hfc_stop_st(s);
+ if (persistentlayer1)
+ hfc_start_st(s);
+ break;
+ case HFC_T4:
+ hfc_handle_state(s);
+ s->hfc_timers[HFC_T4] = b4->ticks + 1000;
+ s->hfc_timer_on[HFC_T4] = 1;
break;
default:
if (printk_ratelimit()) {
@@ -1347,9 +1363,9 @@ static void hfc_update_st_timers(struct b4xxp *b4)
for (i=0; i < b4->numspans; i++) {
s = &b4->spans[i];
- for (j=HFC_T1; j <= HFC_T3; j++) {
-
-/* we don't really do timer2, it is expired by the state change handler */
+ for (j = HFC_T1; j < ARRAY_SIZE(s->hfc_timers); j++) {
+ /* we don't really do timer2, it is expired by the
+ * state change handler */
if (j == HFC_T2)
continue;
@@ -1433,6 +1449,7 @@ static void hfc_handle_state(struct b4xxp_span *s)
break;
case 0x7: /* TE state F7: Activated */
s->hfc_timer_on[HFC_T3] = 0;
+ s->hfc_timer_on[HFC_T4] = 0;
s->newalarm = 0;
break;
}
@@ -1454,14 +1471,17 @@ static void hfc_handle_state(struct b4xxp_span *s)
/* If we're in F3 and receiving INFO0, start T3 and jump to F4 */
if (!nt && (sta == 3) && (state & V_INFO0)) {
- s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
- s->hfc_timer_on[HFC_T3] = 1;
- if (DBG_ST) {
- dev_info(&b4->pdev->dev,
- "port %d: receiving INFO0 in state 3, "
- "setting T3 and jumping to F4\n", s->port + 1);
+ if (persistentlayer1) {
+ s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
+ s->hfc_timer_on[HFC_T3] = 1;
+ if (DBG_ST) {
+ dev_info(&b4->pdev->dev,
+ "port %d: receiving INFO0 in state 3, "
+ "setting T3 and jumping to F4\n",
+ s->port + 1);
+ }
+ hfc_start_st(s);
}
- hfc_force_st_state(b4, s->port, 4, 1);
}
/* read in R_BERT_STA to determine where our current sync source is */
@@ -1476,6 +1496,24 @@ static void hfc_handle_state(struct b4xxp_span *s)
}
}
+static void hfc_stop_all_timers(struct b4xxp_span *s)
+{
+ s->hfc_timer_on[HFC_T4] = 0;
+ s->hfc_timer_on[HFC_T3] = 0;
+ s->hfc_timer_on[HFC_T2] = 0;
+ s->hfc_timer_on[HFC_T1] = 0;
+}
+
+static void hfc_stop_st(struct b4xxp_span *s)
+{
+ struct b4xxp *b4 = s->parent;
+
+ hfc_stop_all_timers(s);
+
+ b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA
+ V_ST_ACT_DEACTIVATE);
+}
+
/*
* resets an S/T interface to a given NT/TE mode
*/
@@ -1486,10 +1524,16 @@ static void hfc_reset_st(struct b4xxp_span *s)
b4 = s->parent;
+ hfc_stop_st(s);
+
/* force state G0/F0 (reset), then force state 1/2 (deactivated/sensing) */
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_LD_STA);
flush_pci(); /* make sure write hit hardware */
+ s->span.alarms = DAHDI_ALARM_RED;
+ s->newalarm = DAHDI_ALARM_RED;
+ dahdi_alarm_notify(&s->span);
+
udelay(10);
/* set up the clock control register. Must be done before we activate the interface. */
@@ -1520,9 +1564,13 @@ static void hfc_start_st(struct b4xxp_span *s)
/* start T1 if in NT mode, T3 if in TE mode */
if (s->te_mode) {
- s->hfc_timers[HFC_T3] = b4->ticks + 500; /* 500ms wait first time, timer_t3_ms afterward. */
+ s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timer_on[HFC_T3] = 1;
s->hfc_timer_on[HFC_T1] = 0;
+
+ s->hfc_timers[HFC_T4] = b4->ticks + 1000;
+ s->hfc_timer_on[HFC_T4] = 1;
+
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"setting port %d t3 timer to %lu\n",
@@ -1540,17 +1588,6 @@ static void hfc_start_st(struct b4xxp_span *s)
}
}
-#if 0 /* TODO: This function is not called anywhere */
-static void hfc_stop_st(struct b4xxp_span *s)
-{
- b4xxp_setreg_ra(s->parent, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_ACT_DEACTIVATE);
-
- s->hfc_timer_on[HFC_T1] = 0;
- s->hfc_timer_on[HFC_T2] = 0;
- s->hfc_timer_on[HFC_T3] = 0;
-}
-#endif
-
/*
* read in the HFC GPIO to determine each port's mode (TE or NT).
* Then, reset and start the port.
@@ -1583,8 +1620,6 @@ static void hfc_init_all_st(struct b4xxp *b4)
dev_info(&b4->pdev->dev,
"Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE"));
- hfc_reset_st(s);
- hfc_start_st(s);
}
}
@@ -1841,10 +1876,10 @@ static int hdlc_tx_frame(struct b4xxp_span *bspan)
char debugbuf[256];
unsigned long irq_flags;
-/* if we're ignoring TE red alarms and we are in alarm, restart the S/T state machine */
- if (bspan->te_mode && teignorered && bspan->newalarm == DAHDI_ALARM_RED) {
- hfc_force_st_state(b4, bspan->port, 3, 1);
- }
+ /* if we're ignoring TE red alarms and we are in alarm, restart the
+ * S/T state machine */
+ if (bspan->te_mode && bspan->newalarm != 0)
+ hfc_start_st(bspan);
fifo = bspan->fifos[2];
res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size);
@@ -2332,6 +2367,10 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
if (lc->sync)
b4->spans[lc->sync - 1].sync = (span->offset + 1);
+ hfc_reset_st(bspan);
+ if (persistentlayer1)
+ hfc_start_st(bspan);
+
b4xxp_reset_span(bspan);
/* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */
@@ -3110,6 +3149,7 @@ module_param(vpmsupport, int, S_IRUGO);
module_param(timer_1_ms, int, S_IRUGO | S_IWUSR);
module_param(timer_3_ms, int, S_IRUGO | S_IWUSR);
module_param(companding, charp, S_IRUGO);
+module_param(persistentlayer1, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm");
MODULE_PARM_DESC(spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4");
diff --git a/drivers/dahdi/wcb4xxp/wcb4xxp.h b/drivers/dahdi/wcb4xxp/wcb4xxp.h
index 80a28fe..c35c5dd 100644
--- a/drivers/dahdi/wcb4xxp/wcb4xxp.h
+++ b/drivers/dahdi/wcb4xxp/wcb4xxp.h
@@ -376,6 +376,7 @@
#define HFC_T1 0
#define HFC_T2 1
#define HFC_T3 2
+#define HFC_T4 3
#define MAX_SPANS_PER_CARD 8
@@ -396,8 +397,8 @@ struct b4xxp_span {
unsigned long alarmtimer;
int te_mode; /* 1=TE, 0=NT */
- unsigned long hfc_timers[WCB4XXP_CHANNELS_PER_SPAN]; /* T1, T2, T3 */
- int hfc_timer_on[WCB4XXP_CHANNELS_PER_SPAN]; /* 1=timer active */
+ unsigned long hfc_timers[4]; /* T1, T2, T3, Fake T4 */
+ int hfc_timer_on[4]; /* 1=timer active */
int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */
/* HDLC controller fields */