--- sdla_te3.c	2008-09-17 12:38:51.000000000 -0400
+++ /tmp/sdla_te3.c	2008-09-23 12:12:56.000000000 -0400
@@ -79,10 +79,16 @@
 					 WAN_TE3_BIT_OOF_ALARM))
 
 /* DS3: Define E3 alarm states: LOS OOF YEL */
+#if 0
 #define IS_E3_ALARM(alarm)	((alarm) &				\
 					(WAN_TE3_BIT_LOS_ALARM |	\
 					 WAN_TE3_BIT_YEL_ALARM |	\
 					 WAN_TE3_BIT_OOF_ALARM))
+#endif
+
+#define IS_E3_ALARM(alarm)	((alarm) &				\
+					(WAN_TE3_BIT_YEL_ALARM |	\
+					 WAN_TE3_BIT_OOF_ALARM))
 
 /******************************************************************************
 **			  FUNCTION DEFINITIONS
@@ -99,10 +105,33 @@
 static unsigned int sdla_te3_read_alarms(sdla_fe_t *fe, int);
 static int sdla_te3_read_pmon(sdla_fe_t *fe, int);
 static int sdla_te3_flush_pmon(sdla_fe_t *fe);
+static int sdla_te3_post_init(void* pfe);
+static int sdla_te3_pre_release(void* pfe);
 
 static int sdla_te3_update_alarm_info(sdla_fe_t* fe, struct seq_file* m, int* stop_cnt);
 static int sdla_te3_update_pmon_info(sdla_fe_t* fe, struct seq_file* m, int* stop_cnt);
 
+static int sdla_te3_old_set_lb_modes(sdla_fe_t *fe, unsigned char type, unsigned char mode);
+static int sdla_te3_set_lb_modes(sdla_fe_t *fe, unsigned char type, unsigned char mode);
+
+static int sdla_te3_set_lb_modes_all(sdla_fe_t *fe, unsigned char type, unsigned char mode)
+{
+	int err;
+	sdla_t *card=fe->card;
+
+	DEBUG_EVENT("%s: NENAD %s LOOP\n",fe->name,
+			mode==WAN_TE3_LB_DISABLE?"Disable":"Enable");	
+
+	if (card->adptr_subtype == AFT_SUBTYPE_NORMAL){
+	       	err = sdla_te3_old_set_lb_modes(fe, type,mode); 
+	}else if (card->adptr_subtype == AFT_SUBTYPE_SHARK){
+	      	err = sdla_te3_set_lb_modes(fe, type,mode); 
+	}
+
+	return 0;
+}
+
+
 /******************************************************************************
  *				sdla_te3_get_fe_status()	
  *
@@ -157,9 +186,9 @@
  */
 static int sdla_te3_polling(sdla_fe_t *fe)
 {
-	DEBUG_EVENT("%s: %s: This function is still not supported!\n",
-			fe->name, __FUNCTION__);
-	return -EINVAL;
+       	int err;
+	err=sdla_te3_read_alarms(fe, WAN_FE_ALARM_READ|WAN_FE_ALARM_UPDATE);
+	return err;
 }
 
 /******************************************************************************
@@ -189,16 +218,39 @@
 	}else if (IS_E3(&fe->fe_cfg)){
 		if (IS_E3_ALARM(fe->fe_alarm)){
 			if (fe->fe_status != FE_DISCONNECTED){
-				DEBUG_EVENT("%s: E3 disconnected!\n",
-						fe->name);
+				fe->fe_param.te3.e3_connect_delay=0;
+
+				if (fe->fe_param.te3.e3_lb_ctrl == 1) {
+					fe->fe_param.te3.e3_lb_ctrl = 2;
+				} else {
+					sdla_te3_set_lb_modes_all(fe,WAN_TE3_LIU_LB_REMOTE,WAN_TE3_LB_ENABLE);
+					fe->fe_param.te3.e3_lb_ctrl=0;
+				}
+				//sdla_te3_set_lb_modes_all(fe,WAN_TE3_LIU_LB_REMOTE,WAN_TE3_LB_DISABLE);
+
+				DEBUG_EVENT("%s: E3 disconnected! State=%i\n",
+						fe->name,fe->fe_param.te3.e3_lb_ctrl);
 				fe->fe_status = FE_DISCONNECTED;
 			}
 		}else{
+
 			if (fe->fe_status != FE_CONNECTED){
-				DEBUG_EVENT("%s: E3 connected!\n",
-						fe->name);
-				fe->fe_status = FE_CONNECTED;
+
+				fe->fe_param.te3.e3_connect_delay++;
+				if (fe->fe_param.te3.e3_connect_delay >= 5) {
+					fe->fe_param.te3.e3_connect_delay=0;
+
+					if (fe->fe_param.te3.e3_lb_ctrl == 0) {
+						fe->fe_param.te3.e3_lb_ctrl=1;
+						sdla_te3_set_lb_modes_all(fe,WAN_TE3_LIU_LB_REMOTE,WAN_TE3_LB_DISABLE);
+					}
+
+					DEBUG_EVENT("%s: E3 connected! State=%i\n",
+							fe->name,fe->fe_param.te3.e3_lb_ctrl);
+					fe->fe_status = FE_CONNECTED;
+				}
 			}
+			
 		}
 	}else{
 		return -EINVAL;
@@ -1103,6 +1155,8 @@
 	/* Inialize Front-End interface functions */
 	fe_iface->config		= &sdla_te3_config;
 	fe_iface->unconfig		= &sdla_te3_unconfig;
+	fe_iface->post_init		= &sdla_te3_post_init;
+	fe_iface->pre_release		= &sdla_te3_pre_release;
 	fe_iface->polling		= &sdla_te3_polling;
 	fe_iface->isr			= &sdla_te3_isr;
 	fe_iface->process_udp		= &sdla_te3_udp;
@@ -1239,13 +1293,121 @@
 	data |= BIT_IO_CONTROL_RxLINECLK;
 	WRITE_REG(REG_IO_CONTROL, data);
 
+	if (IS_E3(&fe->fe_cfg)){
+		sdla_te3_set_lb_modes_all(fe,WAN_TE3_LIU_LB_REMOTE,WAN_TE3_LB_ENABLE);
+	}
+
+	fe->fe_param.te3.e3_lb_ctrl=0;
+	fe->fe_param.te3.e3_connect_delay=10;
+
 	/* Initialize Front-End parameters */
 	fe->fe_status	= FE_DISCONNECTED;
+
 	DEBUG_EVENT("%s: %s disconnected!\n",
 					fe->name, FE_MEDIA_DECODE(fe));
 	sdla_te3_read_alarms(fe, 1);
 
-	sdla_te3_set_intr(fe);
+	//sdla_te3_set_intr(fe);
+	return 0;
+}
+
+
+static int sdla_te3_add_timer(sdla_fe_t* fe, unsigned long delay)
+{
+	int	err=0;
+
+	if (wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical) ||
+	    wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)) {
+		return 0;
+	}
+
+#if defined(__WINDOWS__)
+	/* delay is in MS, so it can be used directly by wan_add_timer() */
+	err = wan_add_timer(&fe->timer, delay);
+#else	
+	err = wan_add_timer(&fe->timer, delay * HZ / 1000);
+#endif
+
+	if (err){
+		/* Failed to add timer */
+		return -EINVAL;
+	}
+	wan_set_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
+	return 0;	
+}
+
+
+
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+static void sdla_te3_timer(void* pfe)
+#elif defined(__WINDOWS__)
+static void sdla_te3_timer(IN PKDPC Dpc, void* pfe, void* arg2, void* arg3)
+#else
+static void sdla_te3_timer(unsigned long pfe)
+#endif
+{
+	sdla_fe_t	*fe = (sdla_fe_t*)pfe;
+	sdla_t 		*card = (sdla_t*)fe->card;
+	wan_device_t	*wandev = &card->wandev;
+
+	DEBUG_TEST("[TE3] %s: TE3 timer!\n", fe->name);
+	if (wan_test_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical)){
+		wan_clear_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
+		return;
+	}
+	if (!wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)){
+		/* Somebody clear this bit */
+		DEBUG_EVENT("WARNING: %s: Timer bit is cleared (should never happened)!\n", 
+					fe->name);
+		return;
+	}
+	wan_clear_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
+
+	if (wandev->fe_enable_timer){
+		wandev->fe_enable_timer(fe->card);
+	}
+
+	
+	sdla_te3_add_timer(fe, 1000);
+	
+
+	return;
+}
+
+
+static int sdla_te3_post_init(void* pfe)
+{
+	sdla_fe_t		*fe = (sdla_fe_t*)pfe;
+
+
+	/* Initialize and start T1/E1 timer */
+	wan_set_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical);
+	
+	wan_init_timer(
+		&fe->timer, 
+		sdla_te3_timer,
+	       	(wan_timer_arg_t)fe);
+
+	/* Initialize T1/E1 timer */
+	wan_clear_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical);
+
+	/* Start T1/E1 timer */
+	sdla_te3_add_timer(fe, 5000);
+	return 0;
+}
+
+static int sdla_te3_pre_release(void* pfe)
+{
+	sdla_fe_t		*fe = (sdla_fe_t*)pfe;
+
+
+	/* Kill TE timer poll command */
+	wan_set_bit(TE_TIMER_KILL,(void*)&fe->te_param.critical);
+	if (wan_test_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical)){
+		wan_del_timer(&fe->timer);
+	}
+	wan_clear_bit(TE_TIMER_RUNNING,(void*)&fe->te_param.critical);
+
 	return 0;
 }
 
