#include "./include/mtp3.h"
#include "./include/mtpstm.h"
#include "./include/mtpext.h"
#include "./include/mtpfunc.h"

// fix multiple definition
mtp3_dpc_index	mtp3SortRoutine;
_mtp3_state	mtp3ObjState;
_mtp3_input	mtp3ObjInput;
_mtp3_IPMng	MTP3IPMng;

/*@ignore@*/
void hmrt_tcoc_changeover_order(WORD chl);
void hmrt_tcoc_emergency_changeover_order(WORD chl);
void hmrt_tcoc_emergency_changeover_ack(WORD chl);
void hmrt_tcoc_changeover_ack(WORD chl);
void hmrt_tcoc_update_routing_tables(WORD chl);
void mark_alternative_linkset_available(BYTE *routine);
void mark_alternative_linkset_unavailable(BYTE *routine);
void mark_normal_linkset_available(BYTE *routine);
void mark_normal_linkset_unavailable(BYTE *routine);
void mark_dstSP_inaccessible(BYTE *routine);
BOOL Alinkset_status(BYTE	routine);
BOOL Nlinkset_status(BYTE	routine);

void start_mtp3T12(WORD link)
{
	t12_delay_mtp3[link] = mtp3_para->lt[link].t12;
	mtp3_t12_flag[link] = TIMER_START;
}

void stop_mtp3T12(WORD link)
{
	t12_delay_mtp3[link] = mtp3_para->lt[link].t12;//not decided
	mtp3_t12_flag[link] = TIMER_STOP;
}

void stop_mtp3T21(WORD linkset)
{
	t21_delay_mtp3[linkset] = mtp3_para->mtp3_t21;
	mtp3_t21_flag[linkset] = TIMER_STOP;
}

void start_mtp3T21(WORD linkset)
{
	t21_delay_mtp3[linkset] = mtp3_para->mtp3_t21;
	mtp3_t21_flag[linkset] = TIMER_START;
}

void tsrc_fun5(WORD linkset)
{
	int		i;
	BYTE	nw;
	network	*sp;
	WORD	sp_place;
	ls_info	*ls;
	BYTE	rs_2;/* normal route and alternative route status */

	if (linkset >= MAX_LS)
		return;
	nw = mtp3_para->ls_pro[linkset].nw_id;
	ls = &mtp3.ls[linkset];
	ls->adjacentsp_restarting = 0;/* cancel adjacent sp restarting */

	/* not support RSRT */
	sp = &mtp3.nw[nw];
	for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
	{
		sp_place = ls->influ_dstplace_intable_asNLS[i];
		rs_2 = sp->routine[sp_place];
		if (((rs_2 >> 6) & 3) == 2)// spc unreachable
		{
			mtp3.nw[nw].rsrt_input[sp_place] = RSRT_TSRC_ROUTE_SET_TEST;
		}
		if ((Nlinkset_status(rs_2) == LS_AVAILABLE)	&&
			(Alinkset_status(rs_2) == LS_UNAVAILABLE)	)
/*		if ( ((rs_2 & 3) == NLS_AVAILABLE)			&&
			 (((rs_2 >> 2) & 3) == ALS_UNAVAILABLE)	)*/
		{/* sp just accesible */
			mtp3.nw[nw].rtac_input[sp_place] = RTAC_DEST_ACCESSIBLE;
		}
		hmrt_tfrc_update_routing_tables(sp_place,nw);
	}
	for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
	{
		sp_place = ls->influ_dstplace_intable_asALS[i];
		rs_2 = sp->routine[sp_place];
		if (((rs_2 >> 6) & 3) == 2)// spc unreachable
		{
			mtp3.nw[nw].rsrt_input[sp_place] = RSRT_TSRC_ROUTE_SET_TEST;
		}
		if ((Nlinkset_status(rs_2) == LS_UNAVAILABLE)	&&
			(Alinkset_status(rs_2) == LS_AVAILABLE)	)
/*		if ( ((rs_2 & 3) == NLS_UNAVAILABLE)		&&
			 (((rs_2 >> 2) & 3) == ALS_AVAILABLE)	)*/
		{/* sp just accesible */
			mtp3.nw[nw].rtac_input[sp_place] = RTAC_DEST_ACCESSIBLE;
		}
		hmrt_tfrc_update_routing_tables(sp_place,nw);
	}
}

void mtp3T21_expired(WORD linkset)
{
	tsrc_fun5(linkset);
}

void start_mtp3T22(WORD link)
{
	t22_delay_mtp3[link] = 20;
	mtp3_t22_flag[link] = TIMER_START;
}

void start_mtp3T23(WORD link)
{
	t23_delay_mtp3[link] = 20;
	mtp3_t23_flag[link] = TIMER_START;
}

void start_mtp3T13(WORD link)
{
	t13_delay_mtp3[link] = mtp3_para->lt[link].t13;
	mtp3_t13_flag[link] = TIMER_START;
}

void stop_mtp3T13(WORD link)
{
	t13_delay_mtp3[link] = mtp3_para->lt[link].t13;
	mtp3_t13_flag[link] = TIMER_STOP;
}

void stop_mtp3T14(WORD link)
{
	t14_delay_mtp3[link] = mtp3_para->lt[link].t14;
	mtp3_t14_flag[link] = TIMER_STOP;
}

void start_mtp3T14(WORD link)
{
	t14_delay_mtp3[link] = mtp3_para->lt[link].t14;
	mtp3_t14_flag[link] = TIMER_START;
}

void mtp3Timer_proc(WORD i)
{
	if (mtp3_t12_flag[i] == TIMER_START)
	{
		t12_delay_mtp3[i] --;
		if (t12_delay_mtp3[i] == 0)
		{
			mtp3_t12_flag[i] = TIMER_STOP;
			t12_delay_mtp3[i] = mtp3_para->lt[i].t12;
			mtp3ObjInput.tlac_input_from_Tctl[i] = TLAC_T12_EXPIRED;
		}
	}

	if (mtp3_t13_flag[i] == TIMER_START)
	{
		t13_delay_mtp3[i] --;
		if (t13_delay_mtp3[i] == 0)
		{
			mtp3_t13_flag[i] = TIMER_STOP;
			t13_delay_mtp3[i] = mtp3_para->lt[i].t13;
			mtp3ObjInput.tlac_input_from_Tctl[i] = TLAC_T13_EXPIRED;
		}
	}

	if (mtp3_t14_flag[i] == TIMER_START)
	{
		t14_delay_mtp3[i] --;
		if (t14_delay_mtp3[i] == 0)
		{
			mtp3_t14_flag[i] = TIMER_STOP;
			t14_delay_mtp3[i] = mtp3_para->lt[i].t14;
			mtp3ObjInput.tlac_input_from_Tctl[i] = TLAC_T14_EXPIRED;
		}
	}

	if (mtp3_t22_flag[i] == TIMER_START)
	{
		t22_delay_mtp3[i] --;
		if (t22_delay_mtp3[i] == 0)
		{
			mtp3_t22_flag[i] = TIMER_STOP;
			t22_delay_mtp3[i] = mtp3_para->lt[i].t22;
			mtp3ObjInput.tlac_input_from_Tctl[i] = TLAC_T22_EXPIRED;
		}
	}

	if (mtp3_t23_flag[i] == TIMER_START)
	{
		t23_delay_mtp3[i] --;
		if (t23_delay_mtp3[i] == 0)
		{
			mtp3_t23_flag[i] = TIMER_STOP;
			t23_delay_mtp3[i] = mtp3_para->lt[i].t23;
			mtp3ObjInput.tlac_input_from_Tctl[i] = TLAC_T23_EXPIRED;
		}
	}

//	i = i & 127;
	i = i%MAX_LS;
	if (mtp3_t21_flag[i] == TIMER_START)
	{
		t21_delay_mtp3[i] --;
		if (t21_delay_mtp3[i] == 0)
		{	
			mtp3_t21_flag[i] = TIMER_STOP;
			t21_delay_mtp3[i] = mtp3_para->mtp3_t21;
			mtp3T21_expired(i);
		}
	}
}

void mtp3_send_tfp(WORD link,BYTE nw,WORD index)
{
	if (mtp3ObjState.lk_mtp3[link] == mtp3_localip)
	{
		mtp3.nw[nw].rtpc_input[index] = RTPC_TSRC_SEND_TFP_MSG;
		sdTFP_Ls = mtp3_para->lk[link].e1_to_linkset;
		rtpc_proc(nw,index);
	}
}

void tsrc_fun6(WORD link,BYTE nw,WORD sp_place)
{
	WORD	ls;
	WORD	nls;
	WORD	als;
	BYTE	*routine;
	int		lsx16;
	int		i;

	network	*sp;
	sp = &mtp3.nw[nw];
	ls = mtp3_para->lk[link].e1_to_linkset;


	nls = mtp3_para->nw[nw].routing[sp_place].normal_ls;
	als = mtp3_para->nw[nw].routing[sp_place].alternative_ls;

	routine = (BYTE*)&sp->routine[sp_place];


	if (ls == nls)/* normal route unavailable */
	{
//		printf("link %d unavailable,Nls %d UNAVAILABLE\n",link,nls);
		mark_normal_linkset_unavailable(&sp->routine[sp_place]);
		if (Alinkset_status(*routine) == LS_AVAILABLE)
//		if ( (((*routine) >> 2) & 3) == ALS_AVAILABLE )/* Alternative route available */
		/* this destination has alternative route */
		{/* new stp use for destination */
			if (mtp3ObjState.lk_mtp3[link] == mtp3_localip)
			{
//				printf("link %d send TFP via ALS\n",link);
				mtp3.nw[nw].rtpc_input[sp_place] = RTPC_TSRC_SEND_TFP_MSG;
				sdTFP_Ls = als;
				rtpc_proc(nw,sp_place);
				mtp3_debug(MTP3DB_EVENT,"[tsrc]net%d spc %lx normal linkset %d unavailable,send TFP to Als %d remote sp",nw,mtp3_para->nw[nw].routing[sp_place].dpc,ls,als);
			}
			//mark new stp used for destination
		}
		else
		{
			lsx16 = ls*16;
			for (i=0; i<16; i++)
			{
				if (mtp3ObjState.link_l3_state[ls_slc[lsx16+i]] == INHIBITED)	/* some link inhibited in alternative linkset */
					mtp3ObjInput.tlac_input_from_stm[ls_slc[lsx16+i]] = TLAC_UINHIBIT_SIGLINK_FROM_TSRC;
			}
			if (mtp3ObjState.lk_mtp3[link] == mtp3_localip)
			{
				sp->rtpc_input[sp_place] = RTPC_DEST_INACCESSIBLE;/* broadcast tfp */
				rtpc_proc(nw,sp_place);
//				printf("mark send tfp to adjacent sp\n");
				current_measure->ls_measure[ls][3]++;/* Broadcast TFP due to failure of measured link set */
				mtp3_debug(MTP3DB_EVENT,"[tsrc]net%d,spc %lx normal linkset %d unavailable,Unreachable!!,broad cast TFP",nw,mtp3_para->nw[nw].routing[sp_place].dpc,ls);
			}
			else
				mtp3_debug(MTP3DB_EVENT,"[tsrc]net%d,spc %lx normal linkset %d unavailable,Unreachable!!",nw,mtp3_para->nw[nw].routing[sp_place].dpc,ls);
			//tsfc_tsrc_destination_inacessible
		}
	}
	else if (ls == als)/* als unavailable */
	{
		mark_alternative_linkset_unavailable(&sp->routine[sp_place]);
		if (Nlinkset_status(*routine) == LS_AVAILABLE)
//		if ( ((*routine) & 3) == NLS_AVAILABLE )
		{
		}
		else
		{
			lsx16 = ls*16;
			for (i=0; i<16; i++)
			{
				if (mtp3ObjState.link_l3_state[ls_slc[lsx16+i]] == INHIBITED)	/* some link inhibited in alternative linkset */
					mtp3ObjInput.tlac_input_from_stm[ls_slc[lsx16+i]] = TLAC_UINHIBIT_SIGLINK_FROM_TSRC;
			}
			if (mtp3ObjState.lk_mtp3[link] == mtp3_localip)
			{
				mtp3_debug(MTP3DB_EVENT,"[tsrc]net%d,spc %lx alternative linkset %d unavailable,broadcast TFP",nw,mtp3_para->nw[nw].routing[sp_place].dpc,ls);
				sp->rtpc_input[sp_place] = RTPC_DEST_INACCESSIBLE;/* broadcast tfp */
				rtpc_proc(nw,sp_place);
//				printf("mark send tfp to adjacent sp,because als unavailable\n");
				current_measure->ls_measure[ls][3]++;/* Broadcast TFP due to failure of measured link set */
			}
			else
				mtp3_debug(MTP3DB_EVENT,"[tsrc]net%d,spc %lx alternative linkset %d unavailable,Unreachable!!",nw,mtp3_para->nw[nw].routing[sp_place].dpc,ls);
			//tsfc_tsrc_destination_inacessible
		}
	}
	if ( (sp->routine[sp_place] & 0x0f) == 0x0a)
	{
		mark_dstSP_inaccessible(&sp->routine[sp_place]);
	}
}


void tsrc_fun8(WORD ls,BYTE nw,WORD sp_place)
{
	WORD	nls;
	WORD	als;
	BYTE	*routine;

	network	*sp;
	sp = &mtp3.nw[nw];
	
	nls = mtp3_para->nw[nw].routing[sp_place].normal_ls;
	als = mtp3_para->nw[nw].routing[sp_place].alternative_ls;

	routine = (BYTE*)&sp->routine[sp_place];

	if ( ((*routine) >> 4) & 3 )/* dst acessible */
	{
		if (nls == ls)
		{
			if (Nlinkset_status(*routine) == LS_UNAVAILABLE)
//			if ( ((*routine) & 3) == NLS_UNAVAILABLE)
			{
				if ( ((*routine) & 0x0C) == ALS_UNAVAILABLE)
				{/* new stp use for destination */
				}
				else/* als available,route change back to normal route 
					 * stp no longer use for destination */
				{
					mtp3.nw[nw].rtac_input[sp_place] = RTAC_STP_NOLONGER_FOR_DEST;
					sdTFA_Ls = als;
					rtac_proc(nw,sp_place);
					mtp3_debug(MTP3DB_EVENT,"[tsrc]net%d,spc%lx normal linkset %d available,no long use als %d for routing,send TFA to als RSP",nw,mtp3_para->nw[nw].routing[sp_place].dpc,ls,als);
					{/* tsrc->rtac stp no longer use for destination */
					}
					{/* new stp use for destination */
					}
				}
				mtp3.nw[nw].rtpc_input[sp_place] = RTPC_TSRC_SEND_TFP_MSG;
				sdTFP_Ls = ls;
				rtpc_proc(nw,sp_place);
			}
			mark_normal_linkset_available(routine);
		}
		else if (als == ls)
		{/* mark als available */
			mark_alternative_linkset_available(routine);
		}
	}
	else/* dst not accessible */
	{
		mtp3.nw[nw].rtac_input[sp_place] = RTAC_DEST_ACCESSIBLE;
		//tsfc_tsrc_destination_accessible(ls);
		if (nls == ls)
		{
			mark_normal_linkset_available(routine);
			if (Nlinkset_status(*routine) == LS_UNAVAILABLE)
//			if ( ((*routine) & 3) == NLS_UNAVAILABLE)
			{/* new stp use for destination */
			}
		}
		else if (als == ls)
		{/* new stp use for destination */
			mark_alternative_linkset_available(routine);
		}
	}
}

void tsrc_fun7(WORD chl, BYTE nw)
{
	WORD	lsx8;
	WORD	sp_place;
	int		i;
	network	*sp;
	ls_info	*ls;
	WORD	lsno;

	lsno = mtp3_para->lk[chl].e1_to_linkset;
	lsx8 = lsno<<3;

	ls = &mtp3.ls[lsno];
	sp = &mtp3.nw[nw];
	for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
	{
		sp_place = ls->influ_dstplace_intable_asNLS[i];
		if ( !own_sp_restarting )
		{
			tsrc_fun8(lsno,nw,sp_place);
		}
		else
			mark_normal_linkset_available(&sp->routine[sp_place]);
	}
		
	/* select sp that use this linkset for alternative route */
	for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
	{
		sp_place = ls->influ_dstplace_intable_asALS[i];
		if ( !own_sp_restarting )
		{
			tsrc_fun8(lsno,nw,sp_place);
		}
		else
			mark_alternative_linkset_available(&sp->routine[sp_place]);
	}
}

void tsrc_tsrc_signalling_link_set_available(WORD chl)
{
	int		i;
	BYTE	nw;
	network	*sp;
	WORD	lsx8;
	WORD	sp_place;
	WORD	adsp_place;
	WORD	lsno;
	WORD	lsx16;
	BYTE	adsp_acessible;
	BYTE	owner_of_link;
	
	ls_info		*ls;
	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[lsno];
	lsx8 = lsno << 3;
	
	if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
		owner_of_link = 1;
	else
		owner_of_link = 0;

	nw = mtp3_para->ls_pro[lsno].nw_id;
	adsp_place = ls->adjacent_sp_place;
	if (adsp_place >= MAX_ROUTE)
		return;
	adsp_acessible = (mtp3.nw[nw].routine[adsp_place] >> 4) & 3;

	ls->adjacentsp_acessible = TRUE;
	current_measure->ls_measure[lsno][7]++;/* Stop of adjacent SP inaccessible */
	
	if ( own_sp_restarting )/* local restarting */
	{
		if (adsp_acessible == 1)
			cb_msg_can_exchange[chl] = TRUE;
		else
			cb_msg_can_exchange[chl] = FALSE;
		tsrc_fun7(chl,nw);
	}
	else
	{
		if ( adsp_acessible == 1 )/* adjacent sp acessible */
		{
			if (adsp_acessible == 1)
				cb_msg_can_exchange[chl] = TRUE;
			else
				cb_msg_can_exchange[chl] = FALSE;
			tsrc_fun7(chl,nw);
		}
		else/* adjacent sp inacessible */
		{
			lsx16 = lsno << 4;
			ls->adjacentsp_restarting = 1;
			start_mtp3T21(lsno);
			sp = &mtp3.nw[nw];
/*** mark all route available ***/
			for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
			{
				sp_place = ls->influ_dstplace_intable_asNLS[i];
				mark_normal_linkset_available(&sp->routine[sp_place]);
				if (Alinkset_status(sp->routine[sp_place]) == LS_AVAILABLE)
//				if ( ((sp->routine[sp_place] >> 2) & 3) == ALS_AVAILABLE)
				{
					if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
					{
//						printf("link %d send TFA via ALS\n",chl);
						mtp3.nw[nw].rtpc_input[sp_place] = RTPC_TSRC_SEND_TFP_MSG;
						sdTFA_Ls = mtp3_para->nw[nw].routing[lsno].alternative_ls;
						rtac_proc(nw,sp_place);
					}
				}
			}

			/* select sp that use this linkset for alternative route */
			for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
			{
				sp_place = ls->influ_dstplace_intable_asALS[i];
				mark_alternative_linkset_available(&sp->routine[sp_place]);
			}
/*** mark all route can available ***/
//			tsfc_tsrc_adjacent_sp_restarting(ls);
//			tprc_tsrc_adjacent_sp_restarting(ls);
			mtp3.ls[lsno].adjacentsp_restarting = 1;/* mark adjacent sp restarting */
			if (owner_of_link == 1)
				mtp3ObjInput.taprc_input[lsno] = TPRC_ADJACENT_SP_RESTARTING;
//			mtp3_debug(MTP3DB_EVENT,"chl %d,linkset %d adjacent sp restarting",chl,lsno);
		}
	}
}

void tsrc_tsrc_signalling_link_set_unavailable(WORD chl)
{
	BYTE	i;
	BYTE	nw;
	network	*sp;
	WORD	lsx8;
	WORD	sp_place;
	WORD	lsno;
	WORD	adsp_place;
	BYTE	owner_of_link;

	ls_info		*ls;
	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[lsno];
	lsx8 = lsno << 3;

	if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
		owner_of_link = 1;
	else
		owner_of_link = 0;

	nw = mtp3_para->ls_pro[lsno].nw_id;
	adsp_place = ls->adjacent_sp_place;
	if (adsp_place >= MAX_ROUTE)
		return;

	if ( (mtp3.nw[nw].routine[adsp_place] & 0x0f) == 0 )/* normal and alternative route are available before */
		co_msg_can_exchange[chl] = TRUE;
	else
	{
		ls->adjacentsp_acessible = FALSE;
		current_measure->ls_measure[lsno][5]++;/* Adjacent SP inaccessible */
		co_msg_can_exchange[chl] = FALSE;
	}

	sp = &mtp3.nw[nw];
	/* select sp that use this linkset as normal route */
	for ( i=0; i<(ls->influ_dstnum_asNLS % MAX_LS_DPC_ADD1); i++ )
	{
		sp_place = ls->influ_dstplace_intable_asNLS[i];
		if ( own_sp_restarting )
		{
			mark_normal_linkset_unavailable(&sp->routine[sp_place]);
			if (Alinkset_status(sp->routine[sp_place]) != LS_AVAILABLE)
			{
//			if ( ((sp->routine[sp_place] >> 2) & 3) != ALS_AVAILABLE )/* Alternative route available */
				mark_dstSP_inaccessible(&sp->routine[sp_place]);
				printf("mark inaccessible\n");
			}
		}
		else
			tsrc_fun6(chl,nw,sp_place);
	}
	
	/* select sp that use this linkset as alternative route */
	for ( i=0; i<(ls->influ_dstnum_asALS % MAX_LS_DPC_ADD1); i++ )
	{
		sp_place = ls->influ_dstplace_intable_asALS[i];
		if ( own_sp_restarting )
		{
			mark_alternative_linkset_unavailable(&sp->routine[sp_place]);
			if (Nlinkset_status(sp->routine[sp_place]) != LS_AVAILABLE)
//			if ( (sp->routine[sp_place] & 3) != NLS_AVAILABLE )/* normal route unavailable */
				mark_dstSP_inaccessible(&sp->routine[sp_place]);
		}
		else
			tsrc_fun6(chl,nw,sp_place);
	}
}

int	inhibit_allow_or_not(WORD ls,BYTE nw)
{
	int		dpc;
	BYTE	routine;

	for (dpc=0; dpc<MAX_ROUTE; dpc++)
	{
		routine = mtp3.nw[nw].routine[dpc];
		if ( (mtp3_para->nw[nw].routing[dpc].normal_ls == ls)	&&
			 (Alinkset_status(routine) == LS_UNAVAILABLE) )
//			 (((routine >> 2) & 3) == ALS_UNAVAILABLE)	)
			return FALSE;
		else if ( (mtp3_para->nw[nw].routing[dpc].alternative_ls == ls)	&&
				  (Nlinkset_status(routine) == LS_UNAVAILABLE)	)
//				  ((routine & 3) == NLS_UNAVAILABLE)				)
			return FALSE;
	}
	return TRUE;
}

void tsrc_fun15(WORD chl,BYTE inhibit_req_by)
{
	switch (inhibit_req_by)
	{
		case LOCAL_INHIBIT_REQ:
			mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_LOCAL_INHIBIT_DENIED;
			break;
		case REMOTE_INHIBIT_REQ:
			mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_REMOTE_INHIBIT_DENIED;
			break;
	}
}

void tsrc_inhibit_allow(WORD chl,BYTE inhibit_req_by)
{
	switch (inhibit_req_by)
	{
		case LOCAL_INHIBIT_REQ:
			mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_LOCAL_INHIBIT_ALLOWED;
			break;
		case REMOTE_INHIBIT_REQ:
			mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_REMOTE_INHIBIT_ALLOWED;
			link_inhibited[chl] = TRUE;/* mark link inhibited */
			break;
	}
}

void tsrc_fun13(WORD chl,BYTE inhibit_req_by)
{
	WORD	ls;
	BYTE	nw;
	BYTE	route_st;
	int		inhibit;
	WORD	sp_place;

	mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d rv inhibit request from tlac",chl);

	ls = mtp3_para->lk[chl].e1_to_linkset;
	nw = mtp3_para->ls_pro[ls].nw_id;
	if (mtp3ObjState.link_l3_state[chl] == UNAVAILABLE)/* link l3 state unavailable */
	{
		sp_place = mtp3.ls[ls].adjacent_sp_place;
		if (sp_place >= MAX_ROUTE)
			return;
		route_st = (mtp3.nw[nw].routine[sp_place] >> 4) & 3;
		if (route_st == SP_ACCESSIBLE)/* remote sp can access */
		{
			tsrc_inhibit_allow(chl,inhibit_req_by);
		}
		else/* remote sp can't access */
		{
			tsrc_fun15(chl,inhibit_req_by);/* [inhibit dennid] */
		}
		mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
	}
	else/* link l3 state available */
	{
		if (mtp3.ls[ls].links_available == 1)/* there is only one link left available in this linkset */
		{
			inhibit = inhibit_allow_or_not(ls,nw);
			if (inhibit == FALSE)/* inhibit this link maybe can cause one dpc not accessable */
				tsrc_fun15(chl,inhibit_req_by);/* [inhibit dennid] */
			else/* inhibit this link will not cause any dpc not accessable */
				tsrc_inhibit_allow(chl,inhibit_req_by);
		}
		else/* there is another available link in this linkset */
			tsrc_inhibit_allow(chl,inhibit_req_by);
	}
}

void tsrc_proc(WORD chl)
{
	BYTE		cc_lk_num;
	WORD		lsno;
	BYTE		rmSP_routine;/* remote sp routine */
	WORD		rmSP_place;
	
	ls_info		*ls;
	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[lsno];
	
	switch (mtp3ObjState.tsrc_state[chl])
	{
		case TSRC_IDLE_STATE:
			switch (mtp3ObjInput.tsrc_input_from_tlac[chl])
			{
				case TSRC_TLAC_LINK_UNAVAILABLE:
//					printf("tsrc link %d unavailable\n",chl);
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
					if (ls->links_available > 0)
        				ls->links_available--;
 		//           if ( /* emergency see 12.2.4 */ )
//      		          lk_llsc_tsrc_emergency(lk);
		            if ( ls->links_available == 0 )
        		    {
        		    	changeover_select[chl] = BETWEEN_LS;
						mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d unavailable,linkset %d unavailable",chl,lsno);
						tsrc_tsrc_signalling_link_set_unavailable(chl);
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d unavailable",chl);
						co_msg_can_exchange[chl] = TRUE;
						changeover_select[chl] = WITHIN_LS;
					}
				break;
				
				case TSRC_TLAC_LINK_AVAILABLE:
//					printf("tsrc link %d available\n",chl);
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
		            link_available[chl] = AVAILABLE;
        		    ls->links_available++;
		//            if ( /* not emergency see 12.2.4 */ )
		//                lk_llsc_tsrc_emergency_ceases(lk);
        		    if ( ls->links_available == 1 )/* no other links available in linkset */
					{
						mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d available,linkset available",chl);
						tsrc_tsrc_signalling_link_set_available(chl);
						changeback_select[chl] = BETWEEN_LS;
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d available",chl);
						changeback_select[chl] = WITHIN_LS;
						cb_msg_can_exchange[chl] = TRUE;
					}
				break;
				
				case TSRC_TLAC_LOCAL_INHIBIT_REQ:
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
					tsrc_fun13(chl,LOCAL_INHIBIT_REQ);
				break;
				
				case TSRC_TLAC_REMOTE_INHIBIT_REQ:
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
					tsrc_fun13(chl,REMOTE_INHIBIT_REQ);
				break;
				
				case TSRC_TLAC_LINK_INHIBITED:
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
					link_inhibited[chl] = TRUE;
				break;
				
				case TSRC_TLAC_CANCEL_LINK_INHIBITED:
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
					link_inhibited[chl] = FALSE;
				break;
				
				case TSRC_TLAC_UNINHIBIT_REQ:
					mtp3ObjInput.tsrc_input_from_tlac[chl] = IDLE;
					rmSP_place = mtp3.ls[lsno].adjacent_sp_place;
					if (rmSP_place > 255)
						return;
					rmSP_routine = mtp3.nw[mtp3_para->ls_pro[lsno].nw_id].routine[rmSP_place];
					if ( ((rmSP_routine >> 4) & 1) == SP_INACCESSIBLE)/* no route */
						mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_UNINHIBIT_NOT_POSSIBLE;
					else
						mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_UNINHIBIT_POSSIBLE;
				break;
				
				default:
				break;
			}

			switch (mtp3ObjInput.tsrc_input_from_tcoc[chl])
			{
				case TSRC_TCOC_ALTERNATIVE_ROUTING_DATA_REQUEST:
					mtp3ObjInput.tsrc_input_from_tcoc[chl] = IDLE;
		            /* obtain alternative routing data according to rules specified in Q.704 4.4 */
        		    /* during SP restart the adjacent SP is considered inaccessible */
		            /* locally or request from MTP level state machine */
/********/
/********/			changeover_required[chl] = TRUE;
        		    mtp3ObjInput.tcoc_input_from_tsrc[chl] = TCOC_ALTERATIVE_ROUTE_DT;
		            mtp3ObjState.tsrc_state[chl] = TSRC_WAIT01_STATE;
					mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d tcoc asking for alternative route date",chl);
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.tsrc_input_from_tcbc[chl])
			{
				case TSRC_TCBC_ALTERNATIVE_ROUTING_DATA_REQUEST:
					mtp3ObjInput.tsrc_input_from_tcbc[chl] = IDLE;
					cc_lk_num = 0;
	
					lsno = mtp3_para->lk[chl].e1_to_linkset;
					ls = &mtp3.ls[lsno];
				    /* obtain alternative routing data */
				    /* during SP restart the adjacent SP is considered inaccessible */
				    /* locally or request from MTP level state machine */
				    if ( changeback_select[chl] == BETWEEN_LS )/* this is the first link */
				    {
//						mtp3_debug(MTP3DB_EVENT,"link %d changeback_select BETWEEN_LS",chl);
				       	/* but change back message will not exchange between link set */
				    }
				    else
				    {
					}
//					printf("tsrc link %d tcbc alter data cmp\n",chl);
		      	    mtp3ObjInput.tcbc_input_from_tsrc[chl] = TCBC_ALTERATIVE_ROUTE_DT;
		            mtp3ObjState.tsrc_state[chl] = TSRC_WAIT02_STATE;
					tcbc_route_change[chl] = TRUE;
					mtp3_debug(MTP3DB_EVENT,"[tsrc]link %d tcbc asking for alternative route date",chl);
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.tsrc_input_from_stm[chl])
			{
				default:
				break;
			}
		
		case TSRC_WAIT01_STATE:/* 1 TSRC_WAIT1_STATE */
			if (mtp3ObjInput.tsrc_input_from_tcoc[chl] == TSRC_TCOC_CHANGEOVER_EXECUTED)
	        {
				mtp3ObjInput.tsrc_input_from_tcoc[chl] = IDLE;
	        	changeover_completed[chl] = 1;
	            mtp3ObjState.tsrc_state[chl] = TSRC_IDLE_STATE;
	        }
			else if (mtp3ObjInput.tsrc_input_from_tcoc[chl] == TSRC_TCOC_CHANGEOVER_NOT_REQ)
			{
				mtp3ObjInput.tsrc_input_from_tcoc[chl] = IDLE;
				mtp3ObjState.tsrc_state[chl] = TSRC_IDLE_STATE;
			}
		break;
		
		case TSRC_WAIT02_STATE:/* 2 TSRC_WAIT2_STATE */
			if ( mtp3ObjInput.tsrc_input_from_tcbc[chl] == TSRC_PROCEDURE_TERMINATED )
			{
				mtp3ObjInput.tsrc_input_from_tcbc[chl] = IDLE;
				changeover_completed[chl] = 0;
				mtp3ObjState.tsrc_state[chl] = TSRC_IDLE_STATE;
			}
		break;

		case TSRC_WAIT03_STATE:
			break;
		case TSRC_WAIT04_STATE:
			break;
		case TSRC_WAIT05_STATE:
			/* this state's function put in the tprc state machine */
			break;
		default:
		break;
	}
}

void tlac_fun5(WORD link)
{
	mtp3ObjInput.tcbc_input[link] = TCBC_LINK_AVAILABLE;
	changeback_in_progress[link] = TRUE;
	mtp3ObjInput.tsrc_input_from_tlac[link] = TSRC_TLAC_LINK_AVAILABLE;
	mtp3ObjState.tlac_state[link] = TLAC_AVAILABLE_STATE;
}

void tlac_fun6(WORD link)
{
	if (changeover_in_progress[link] == TRUE)
	{
		mtp3ObjInput.tcoc_input_from_stm[link] = TCOC_LINK_AVAILABLE;
	}
	else
		tlac_fun5(link);
}

void tlac_fun7(WORD link)
{
	sd_STM_msg(link,SIGNAL_LUN);
	uninhibit_in_progress[link] = TRUE;
	start_mtp3T12(link);
}

void tlac_fun1(WORD link)
{
	if (changeback_in_progress[link] == TRUE)
	{
//		mtp3_debug(MTP3DB_EVENT,"changeback in progress");
		link_available[link] = FALSE;
	}
	else
	{
		changeover_in_progress[link] = TRUE;
		mtp3ObjInput.tcoc_input_from_stm[link] = TCOC_LINK_UNAVAILABLE;
	}
	mtp3ObjInput.tsrc_input_from_tlac[link] = TSRC_TLAC_LINK_UNAVAILABLE;
	mtp3ObjState.tlac_state[link] = TLAC_UNAVAILABLE_STATE;
}

void mgmt_tlac_proc(WORD link,BYTE input)
{
	switch (input)
	{
		case 0:
			break;
		case 1:
			break;
	}
}

void tlac_proc(WORD chl)
{
	ls_info		*ls;
	int			lsno;

	if (init_tlac_state[chl] == TRUE)
	{
		init_tlac_state[chl] = IDLE;
		mtp3ObjState.tlac_state[chl] = TLAC_UNAVAILABLE_STATE;
		changeover_in_progress[chl] = FALSE;
		changeback_in_progress[chl] = FALSE;
		failed[chl] = TRUE;
		mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
		return;
	}
	
	lsno = mtp3_para->lk[chl].e1_to_linkset;
	ls = &mtp3.ls[mtp3_para->lk[chl].e1_to_linkset];

	switch (mtp3ObjState.tlac_state[chl])
	{
		case TLAC_UNAVAILABLE_STATE:
			switch (mtp3ObjInput.tlac_input_from_mgmt[chl])
			{
				case TLAC_MGMT_INHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_mgmt[chl] = IDLE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LOCAL_INHIBIT_REQ;
					current_measure->lk_measure1[chl][7]++;//Local management inhibit
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv local MGMT inhibit request in unavailable state",chl);
					break;
				case TLAC_MGMT_UINHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_mgmt[chl] = IDLE;
					management_req[chl] = TRUE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_UNINHIBIT_REQ;
					current_measure->lk_measure1[chl][8]++;//Local management uninhibit
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv local MGMT uninhibit request in unavailable state",chl);
					break;
				default:
					break;
			}

			switch (mtp3ObjInput.tlac_input_from_hmdt[chl])
			{
				case TLAC_HMDT_INHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (link_remotely_inhibited[chl] == TRUE)
					{	
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv LIN,send LIA",chl);
						sd_STM_msg(chl,SIGNAL_LIA);/* send inhibit ack signal */
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv LIN,send LIA,mark Inhibited",chl);
						link_remotely_inhibited[chl] = TRUE;
						link_locally_inhibited[chl] = FALSE;
						sd_STM_msg(chl,SIGNAL_LIA);
						mtp3ObjState.link_l3_state[chl] = INHIBITED;
						mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_INHIBITED;
						start_mtp3T22(chl);
					}
				break;
				
				case TLAC_HMDT_UINHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (link_inhibited[chl] == TRUE)
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(unavai)]link %d (inhibited) rv LUN,send LUA",chl);
						link_remotely_inhibited[chl] = FALSE;
						sd_STM_msg(chl,SIGNAL_LUA);
						stop_mtp3T13(chl);
						if (link_locally_inhibited[chl] != TRUE)
						{
							mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_CANCEL_LINK_INHIBITED;
							link_inhibited[chl] = FALSE;
							if 	( (blocked_by[chl] == IDLE) &&
								  (failed[chl] != TRUE)		)
								tlac_fun6(chl);
							else
								mtp3ObjState.link_l3_state[chl] = UNAVAILABLE;
						}
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(unavai)]link %d (unavailable) rv LUN,send LUA",chl);
						sd_STM_msg(chl,SIGNAL_LUA);
					}
				break;
				
				case TLAC_HMDT_INHIBIT_ACK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (local_inhibit_in_progress[chl] == TRUE)
					{
						link_locally_inhibited[chl] = TRUE;
						link_remotely_inhibited[chl] = FALSE;
						link_inhibited[chl] = TRUE;
						mtp3ObjState.link_l3_state[chl] = INHIBITED;
						local_inhibit_in_progress[chl] = FALSE;
						mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_INHIBITED;
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv LIA,TLAC->TSRC:LINK INHIBITED",chl);
						stop_mtp3T14(chl);
					}
					start_mtp3T22(chl);
				break;
				
				case TLAC_HMDT_UNINHIBIT_ACK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv LUA",chl);
					if (uninhibit_in_progress[chl] == TRUE)
					{
						management_req[chl] = FALSE;
						uninhibit_in_progress[chl] = FALSE;
						mtp3ObjState.link_l3_state[chl] = UNAVAILABLE;
						stop_mtp3T12(chl);
						if (link_remotely_inhibited[chl] != TRUE)
						{
							link_inhibited[chl] = FALSE;
							link_locally_inhibited[chl] = FALSE;
//							mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_CANCEL_LINK_INHIBITED;
							if 	( (blocked_by[chl] == IDLE)	&&
								  (failed[chl] != TRUE)		)
								tlac_fun6(chl);
						}
					}
				break;
				
				case TLAC_HMDT_INHIBIT_DENIED:
				break;
				
				case TLAC_HMDT_FORCE_UNINHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (link_inhibited[chl] == TRUE)
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d (inhibited) rv LFU",chl);
						sd_STM_msg(chl,SIGNAL_LUN);
						uninhibit_in_progress[chl] = TRUE;
						start_mtp3T12(chl);
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv LFU",chl);
						sd_STM_msg(chl,SIGNAL_LUN);
					}
				break;
				
				case TLAC_HMDT_CHANGEOVER_ORDER:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if ( changeover_in_progress[chl] == TRUE )
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv COO,TLAC->TCOC:COO COMMAND",chl);
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_COO_COMMAND;
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv COO,send ECA",chl);
						hmrt_tcoc_emergency_changeover_ack(chl);
					}
				break;
				
				case TLAC_HMDT_ECHANGEOVER_ORDER:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if ( changeover_in_progress[chl] == TRUE) /*changeover is executing */
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv ECO,TLAC->TCOC:ECO COMMAND",chl);
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_ECO_COMMAND;
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv ECO,send ECA",chl);
						sd_STM_msg(chl,SIGNAL_ECA);
					}
				break;

				case TLAC_HMDT_LOCAL_INHIBIT_TEST:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (link_remotely_inhibited[chl] != TRUE)
					{
						sd_STM_msg(chl,SIGNAL_LFU);
						start_mtp3T13(chl);
					}
					break;
				case TLAC_HMDT_REMOTE_INHIBIT_TEST:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (link_locally_inhibited[chl] != TRUE)
					{
						sd_STM_msg(chl,SIGNAL_LUN);
						start_mtp3T12(chl);
					}
					break;

				default:
				break;
			}

			switch (mtp3ObjInput.tlac_input_from_stm[chl])
			{
				case TLAC_TCBC_CHANGEBACK_TERMINATED:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					changeback_in_progress[chl] = FALSE;
					if ( changeover_order[chl] == TRUE)
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_COO_COMMAND;
					else if ( emergency_changeover_order[chl] == TRUE)
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_ECO_COMMAND;
					else if ( link_available[chl] != TRUE )
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_LINK_UNAVAILABLE;
					link_available[chl] = IDLE;
					changeover_order[chl] = IDLE;
					emergency_changeover_order[chl] = IDLE;
					changeover_in_progress[chl] = TRUE;/* mark change over in progress */
				break;
				
				case TLAC_TCOC_CHANGEOVER_EXECUTED:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					changeover_in_progress[chl] = IDLE;/* cancel mark */
					if (link_inhibited[chl] != TRUE)
					{
						if ( failed[chl] != TRUE )
						{
							tlac_fun5(chl);
						}
					}
				break;

				case TLAC_LOCAL_INHIBIT_ALLOWED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d local inhibit allow",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LIN);
					local_inhibit_in_progress[chl] = TRUE;
					start_mtp3T14(chl);
				break;

				case TLAC_REMOTE_INHIBIT_ALLOWED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d remote inhibit allow",chl);
				break;
				case TLAC_LOCAL_INHIBIT_DENIED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d local inhibit denied",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
				break;

				case TLAC_REMOTE_INHIBIT_DENIED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d remote inhibit denied",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
				break;

				case TLAC_UINHIBIT_SIGLINK_FROM_TSRC:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d rv uninhibit sig from TSRC",chl);
					if (uninhibit_in_progress[chl] != TRUE)
					{
						uninhibit_in_progress[chl] = TRUE;
						if 	( (blocked_by[chl] != IDLE)	||
							  (failed[chl] == TRUE)		)
						{
							mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d uninhibit no success, blocked or failed",chl);
						}
						else
						{
							if (link_locally_inhibited[chl] == TRUE)
							{
								mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d send LUN",chl);
								sd_STM_msg(chl,SIGNAL_LUN);
								start_mtp3T12(chl);
							}
							else if (link_remotely_inhibited[chl] == TRUE)
							{
								mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d send LFU",chl);
								sd_STM_msg(chl,SIGNAL_LFU);
								start_mtp3T13(chl);
							}
							else
							{
								mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d is not being local or remotely inhibited",chl);
							}
						}
					}
					else
						mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d uninhibit in progress",chl);
				break;

				case TLAC_UNINHIBIT_NOT_POSSIBLE:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d uninhibit not possible",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					if 	( (blocked_by[chl] != IDLE)	&&
						  (failed[chl] == TRUE)		)
					{
						mgmt_tlac_proc(chl,MGMT_UNINHIBIT_NOT_POSSIBLE);
						management_req[chl] = FALSE;
					}
					else
					{
						sd_STM_msg(chl,SIGNAL_LUN);
						uninhibit_in_progress[chl] = TRUE;
						start_mtp3T12(chl);
					}
				break;

				case TLAC_UNINHIBIT_POSSIBLE:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d uninhibit possible",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LUN);
					uninhibit_in_progress[chl] = TRUE;
					start_mtp3T12(chl);
				break;

				case TLAC_RESTART_BEGINS:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					mtp3ObjState.tlac_state[chl] = TLAC_SP_RESTARTING_STATE;
				break;
				
				case TLAC_TCOC_CHANGEOVER_NOT_REQ:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					changeover_in_progress[chl] = IDLE;/* cancel mark */
					if ( failed[chl] != TRUE )
					{
						mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_AVAILABLE;
						mtp3ObjState.tlac_state[chl] = TLAC_AVAILABLE_STATE;
					}
				break;

				default:
				break;
			}
			
			switch (mtp3ObjInput.tlac_input_from_slm[chl])
			{
				case TLAC_LSAC_SIGLINK_FAILED:
					mtp3ObjInput.tlac_input_from_slm[chl] = IDLE;
					failed[chl] = TRUE;/* mark link fail */
				break;
				
				case TLAC_LSAC_LINK_IN_SERVICE:
					mtp3ObjInput.tlac_input_from_slm[chl] = IDLE;
					failed[chl] = FALSE;/* cancel mark link fail */
					if (link_inhibited[chl] != TRUE)
					{
						if (changeover_in_progress[chl] == TRUE)
						{
							mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d in service,changeover in progress,TLAC->TCOC:LINK AVAILABLE",chl);
							mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_LINK_AVAILABLE;
						}
						else
						{
							mtp3_debug(MTP3DB_EVENT,"[TLAC(unavai)]link %d in service,TLAC->TSRC(TCBC):LINK AVAILABLE",chl);
							tlac_fun5(chl);
						}
					}
				break;
				
				case TLAC_LSAC_REMOTE_PROCESSOR_OUTAGE:
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.tlac_input_from_Tctl[chl])
			{
				case TLAC_T12_EXPIRED:
					mtp3ObjInput.tlac_input_from_Tctl[chl] = IDLE;
					uninhibit_in_progress[chl] = FALSE;/* cancel uninhibit in progress */
					if (t12_expired_2nd_time[chl] == TRUE)
					{
						t12_expired_2nd_time[chl] = FALSE;
						mgmt_tlac_proc(chl,MGMT_UNINHIBIT_NOT_POSSIBLE);
					}
					else
					{
						t12_expired_2nd_time[chl] = TRUE;
						if (management_req[chl] == TRUE)
						{
							mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_UNINHIBIT_REQ;
						}
						else
							tlac_fun7(chl);
					}
					break;
				case TLAC_T13_EXPIRED:
					mtp3ObjInput.tlac_input_from_Tctl[chl] = IDLE;
					if (t13_expired_2nd_time[chl] == TRUE)
					{
						mgmt_tlac_proc(chl,MGMT_UNINHIBIT_NOT_POSSIBLE);
					}
					else
					{
						sd_STM_msg(chl,SIGNAL_LFU);
						start_mtp3T13(chl);
					}
					break;
				case TLAC_T14_EXPIRED:
					mtp3ObjInput.tlac_input_from_Tctl[chl] = IDLE;
					local_inhibit_in_progress[chl] = FALSE;/* cancel local inhibit in progress */
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LOCAL_INHIBIT_REQ;/* local inhibit request */
					break;
				case TLAC_T22_EXPIRED:
					mtp3ObjInput.tlac_input_from_Tctl[chl] = IDLE;
					if (link_locally_inhibited[chl] == TRUE)
					{
						sd_STM_msg(chl,SIGNAL_LLT);
						start_mtp3T22(chl);
					}
					break;
				case TLAC_T23_EXPIRED:
					mtp3ObjInput.tlac_input_from_Tctl[chl] = IDLE;
					if (link_remotely_inhibited[chl] == TRUE)
					{
						sd_STM_msg(chl,SIGNAL_LRT);
						start_mtp3T23(chl);
					}
					break;
				default:
					break;
			}

		break;

		case TLAC_AVAILABLE_STATE:
			switch (mtp3ObjInput.tlac_input_from_mgmt[chl])
			{
				case TLAC_MGMT_INHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_mgmt[chl] = IDLE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LOCAL_INHIBIT_REQ;
					current_measure->lk_measure1[chl][7]++;//Local management inhibit
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv local MGMT uninhibit request",chl);
					break;
				case TLAC_MGMT_UINHIBIT_SIGLINK:
					mtp3ObjInput.tlac_input_from_mgmt[chl] = IDLE;
					current_measure->lk_measure1[chl][8]++;//Local management uninhibit
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv local MGMT uninhibit request",chl);
					break;
				default:
					break;
			}

			switch ( mtp3ObjInput.tlac_input_from_hmdt[chl])
			{
				case TLAC_HMDT_INHIBIT_SIGLINK:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv LIN",chl);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_REMOTE_INHIBIT_REQ;
				break;
				
				case TLAC_HMDT_UINHIBIT_SIGLINK:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv LUN",chl);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LUA);
				break;
				
				case TLAC_HMDT_INHIBIT_ACK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (local_inhibit_in_progress[chl] == TRUE)
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d rv LIA,inhibit in progress",chl);
						link_locally_inhibited[chl] = TRUE;
						link_remotely_inhibited[chl] = FALSE;
						local_inhibit_in_progress[chl] = FALSE;
						stop_mtp3T14(chl);
						link_inhibited[chl] = TRUE;
//						mtp3ObjInput.tsrc_input_from_stm[chl] = TSRC_TLAC_LINK_INHIBITED;
						mgmt_tlac_proc(chl,MGMT_TLAC_LINK_INHIBITED);
						start_mtp3T22(chl);
						tlac_fun1(chl);
					}
					else
						mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv LIA",chl);
				break;
				
				case TLAC_HMDT_UNINHIBIT_ACK:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
				break;
				
				case TLAC_HMDT_INHIBIT_DENIED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv LID",chl);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					mgmt_tlac_proc(chl,MGMT_INHIBIT_DENIED);
					local_inhibit_in_progress[chl] = FALSE;
					stop_mtp3T14(chl);
				break;
				
				case TLAC_HMDT_FORCE_UNINHIBIT_SIGLINK:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d rv LFU",chl);
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LUN);
				break;
				
				case TLAC_HMDT_CHANGEOVER_ORDER:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					mtp3ObjInput.lsac_input_from_stm[chl] = LSAC_TLAC_CHANGEOVER_ORDER_RECEIVED;
					failed[chl] = TRUE;/* mark failed */
					if ( changeback_in_progress[chl] == TRUE )
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d rv COO command,changeback in progress",chl);
						changeover_order[chl] = TRUE;/* mark received coo command */
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d rv COO command,TLAC->TCOC:COO COMMAND",chl);
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_COO_COMMAND;
						changeover_in_progress[chl] = TRUE;
					}
					mtp3ObjState.tlac_state[chl] = TLAC_UNAVAILABLE_STATE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_UNAVAILABLE;
				break;
				
				case TLAC_HMDT_ECHANGEOVER_ORDER:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					mtp3ObjInput.lsac_input_from_stm[chl] = LSAC_TLAC_CHANGEOVER_ORDER_RECEIVED;
					failed[chl] = TRUE;
					if ( changeback_in_progress[chl] == TRUE )
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d rv ECO command,changeback in progress",chl);
						emergency_changeover_order[chl] = TRUE;
					}
					else
					{
						mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d rv EOO command,TLAC->TCOC:EOO COMMAND",chl);
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_ECO_COMMAND;
						changeover_in_progress[chl] = TRUE;
					}
					mtp3ObjState.tlac_state[chl] = TLAC_UNAVAILABLE_STATE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_UNAVAILABLE;
				break;

				case TLAC_HMDT_LOCAL_INHIBIT_TEST:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LFU);
					start_mtp3T13(chl);
					break;
				case TLAC_HMDT_REMOTE_INHIBIT_TEST:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LUN);
					start_mtp3T12(chl);
					break;

				default:
				break;
			}

			switch (mtp3ObjInput.tlac_input_from_stm[chl])
			{
				case TLAC_TCBC_CHANGEBACK_TERMINATED:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					changeback_in_progress[chl] = FALSE;
				break;
				
				case TLAC_TCOC_CHANGEOVER_EXECUTED:
				break;
				
				case TLAC_TCOC_CHANGEOVER_NOT_REQ:
				break;

				case TLAC_LOCAL_INHIBIT_ALLOWED:
					mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d local inhibit allow",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LIN);
					local_inhibit_in_progress[chl] = TRUE;
					start_mtp3T14(chl);
				break;

				case TLAC_REMOTE_INHIBIT_ALLOWED:
					mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d remote inhibit allow",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					link_remotely_inhibited[chl] = TRUE;
					link_locally_inhibited[chl] = FALSE;
					sd_STM_msg(chl,SIGNAL_LIA);
//					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_INHIBITED;
					link_inhibited[chl] = TRUE;
					start_mtp3T23(chl);
					tlac_fun1(chl);
				break;

				case TLAC_LOCAL_INHIBIT_DENIED:
					mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d local inhibit denied",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					mgmt_tlac_proc(chl,MGMT_INHIBIT_DENIED);
				break;

				case TLAC_REMOTE_INHIBIT_DENIED:
					mtp3_debug(MTP3DB_EVENT,"[tlac(avai)]link %d remote inhibit denied",chl);
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					sd_STM_msg(chl,SIGNAL_LID);
				break;

				case TLAC_RESTART_BEGINS:
					link_available[chl] = AVAILABLE;
					mtp3ObjState.tlac_state[chl] = TLAC_SP_RESTARTING_STATE;
				break;

				default:
				break;
			}
			
			switch (mtp3ObjInput.tlac_input_from_slm[chl])
			{
				case TLAC_LSAC_SIGLINK_FAILED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d outof service",chl);
					mtp3ObjInput.tlac_input_from_slm[chl] = IDLE;
					failed[chl] = TRUE;/* mark link fail */
					tlac_fun1(chl);
				break;
				
				case TLAC_LSAC_LINK_IN_SERVICE:
					mtp3ObjInput.tlac_input_from_slm[chl] = IDLE;
					mtp3_debug(MTP3DB_EVENT,"[TLAC(avai)]link %d in service",chl);
				break;
				
				case TLAC_LSAC_REMOTE_PROCESSOR_OUTAGE:
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.tlac_input_from_Tctl[chl])
			{
				case TLAC_T12_EXPIRED:
					break;
				case TLAC_T13_EXPIRED:
					break;
				case TLAC_T14_EXPIRED:
					mtp3ObjInput.tlac_input_from_Tctl[chl] = IDLE;
					local_inhibit_in_progress[chl] = FALSE;/* cancel local inhibit in progress */
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LOCAL_INHIBIT_REQ;/* local inhibit request */
					break;
				default:
					break;
			}

		break;

		case TLAC_SP_RESTARTING_STATE:
			switch (mtp3ObjInput.tlac_input_from_slm[chl])
			{
				case TLAC_LSAC_SIGLINK_FAILED:
					mtp3_debug(MTP3DB_EVENT,"[TLAC(rest)]link %d unavailable in restarting state",chl);
//					printf("tlac link %d failed\n",chl);
					mtp3ObjInput.tlac_input_from_slm[chl] = IDLE;
					failed[chl] = TRUE;/* mark link fail */
					link_available[chl] = FALSE;
					mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_LINK_UNAVAILABLE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_UNAVAILABLE;
				break;
				
				case TLAC_LSAC_LINK_IN_SERVICE:
					mtp3ObjInput.tlac_input_from_slm[chl] = IDLE;
					failed[chl] = FALSE;
					link_available[chl] = TRUE;
					mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_AVAILABLE;
					mtp3ObjInput.tcbc_input[chl] = TCBC_LINK_AVAILABLE;
					if ( (ls->links_available - 1) == mtp3.ls[lsno].linksNum_configured )
						current_active_ls_num ++;
					mtp3_debug(MTP3DB_EVENT,"[TLAC(rest)]link %d in service in restarting state",chl);
				break;
				
				case TLAC_LSAC_REMOTE_PROCESSOR_OUTAGE:
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.tlac_input_from_hmdt[chl])
			{
				case TLAC_HMDT_CHANGEOVER_ORDER:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (failed[chl] == FALSE)/* link available */
					{
						failed[chl] = TRUE;/* mark failed */
						mtp3ObjInput.lsac_input_from_stm[chl] = LSAC_TLAC_CHANGEOVER_ORDER_RECEIVED;
						mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_UNAVAILABLE;
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_COO_COMMAND;
						mtp3_debug(MTP3DB_ERROR,"[TLAC(rest)]link %d RECEIVE COO(link active)\n\r",chl);
					}
					else
					{
						mtp3_debug(MTP3DB_ERROR,"[TLAC(rest)]link %d RECEIVE COO(link fail)\n\r",chl);
					}
				break;
				
				case TLAC_HMDT_ECHANGEOVER_ORDER:
					mtp3ObjInput.tlac_input_from_hmdt[chl] = IDLE;
					if (failed[chl] == FALSE)
					{
						failed[chl] = TRUE;/* mark failed */
						mtp3ObjInput.lsac_input_from_stm[chl] = LSAC_TLAC_CHANGEOVER_ORDER_RECEIVED;
						mtp3ObjInput.tsrc_input_from_tlac[chl] = TSRC_TLAC_LINK_UNAVAILABLE;
						mtp3ObjInput.tcoc_input_from_stm[chl] = TCOC_TLAC_ECO_COMMAND;
						mtp3_debug(MTP3DB_ERROR,"[TLAC(rest)]link %d RECEIVE ECO IN RESTART STATE(link active)\n\r",chl);
					}
					else
					{
						mtp3_debug(MTP3DB_ERROR,"[TLAC(rest)]link %d RECEIVE ECO IN RESTART STATE(link fail)\n\r",chl);
					}
				break;
			}

			switch (mtp3ObjInput.tlac_input_from_stm[chl])
			{
				case TLAC_RESTART_ENDS:
					mtp3ObjInput.tlac_input_from_stm[chl] = IDLE;
					if ( link_available[chl] == TRUE )
						mtp3ObjState.tlac_state[chl] = TLAC_AVAILABLE_STATE;
					else
						mtp3ObjState.tlac_state[chl] = TLAC_UNAVAILABLE_STATE;
				break;

				case TLAC_ADJACENT_SP_RESTART_ENDS:
				break;
			}
		break;

		default:
		break;
	}
}

void changeover_not_req(WORD chl)
{
	mtp3ObjState.tcoc_state[chl] = TCOC_IDLE_STATE;
	mtp3ObjInput.lsac_input_from_tcoc[chl] = LSAC_TCOC_STM_READY;
	mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_TCOC_CHANGEOVER_NOT_REQ;
	mtp3ObjInput.tsrc_input_from_tcoc[chl] = TSRC_TCOC_CHANGEOVER_NOT_REQ;
}

void tcoc_proc(WORD chl)
{
	ls_info		*ls;
	int			l2_input;
	
	ls = &mtp3.ls[mtp3_para->lk[chl].e1_to_linkset];
	
	
	switch (mtp3ObjState.tcoc_state[chl])
	{
		case TCOC_IDLE_STATE:
			switch (mtp3ObjInput.tcoc_input_from_stm[chl])
			{
				case TCOC_LINK_UNAVAILABLE:
					mtp3_debug(MTP3DB_EVENT,"[tcoc]link %d unavailable",chl);
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
					mtp3ObjState.tcoc_state[chl] = TCOC_WAIT01_STATE;
					mtp3ObjInput.tsrc_input_from_tcoc[chl] = TSRC_TCOC_ALTERNATIVE_ROUTING_DATA_REQUEST;
				break;
			
				case TCOC_LINK_AVAILABLE:
				break;
			
				case TCOC_TLAC_COO_COMMAND:
//					mtp3_debug(MTP3DB_EVENT,"link %d rev coo",chl);
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
					remote_bsnt_retrieved[chl] = TRUE;
					mtp3ObjState.tcoc_state[chl] = TCOC_WAIT05_STATE;
				break;
			
				case TCOC_TLAC_ECO_COMMAND:
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
					remote_bsnt_retrieved[chl] = FALSE;
					mtp3ObjState.tcoc_state[chl] = TCOC_WAIT05_STATE;
				break;
				
				default:
				break;
			}

			switch (mtp3ObjInput.tcoc_input_from_hmdt[chl])
			{
				case TCOC_HMDT_COA_COMMAND:
					remote_bsnt_retrieved[chl] = TRUE;
					mtp3ObjInput.tcoc_input_from_hmdt[chl] = IDLE;
					mtp3_debug(MTP3DB_ERROR,"[tcoc]link %d RV COA IN IDLE STATE\n\r",chl);
				break;
				
				case TCOC_HMDT_ECA_COMMAND:
					remote_bsnt_retrieved[chl] = FALSE;
					mtp3ObjInput.tcoc_input_from_hmdt[chl] = IDLE;
					mtp3_debug(MTP3DB_ERROR,"[tcoc]link %d RV ECA IN IDLE STATE\n\r",chl);
				break;
				
				default:
				break;
			}
		break;
		
		case TCOC_WAIT01_STATE:
			if (mtp3ObjInput.tcoc_input_from_stm[chl] == TCOC_LINK_AVAILABLE)
			{
				mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
				mtp3ObjInput.tcoc_input_from_tsrc[chl] = IDLE;
				mtp3_debug(MTP3DB_ERROR,"[tcoc]link %d AVAILABLE AT WAIT1 STATE\n\r",chl);
				changeover_not_req(chl);
			}
			else if ( mtp3ObjInput.tcoc_input_from_tsrc[chl] == TCOC_ALTERATIVE_ROUTE_DT )
			{
				mtp3_debug(MTP3DB_EVENT,"[tcoc]link %d get routing data from tsrc",chl);
//				printf("tcoc link %d route data\n",chl);
				mtp3ObjInput.tcoc_input_from_tsrc[chl] = IDLE;
				if ( changeover_required[chl] == TRUE )
				{
					if ( co_msg_can_exchange[chl] == TRUE )
					{
						co_msg_can_exchange[chl] = IDLE;
//						mtp3_debug(MTP3DB_EVENT,"chl %d cc msg can exchange",chl);
						if ( local_bsnt_retrievable[chl] == TRUE)
							hmrt_tcoc_changeover_order(chl);/* send coo */
						else
						{
							hmrt_tcoc_emergency_changeover_order(chl);
							mtp3ObjInput.lsac_input_from_tcoc[chl] = LSAC_TCOC_STOP_L2;
						}
						t2_delay_mtp3[chl] = mtp3_para->lt[chl].t2;
						mtp3ObjState.tcoc_state[chl] = TCOC_WAITACK_STATE;
					}
					else if ( co_msg_can_exchange[chl] == FALSE )
					{
						co_msg_can_exchange[chl] = IDLE;
						t1_delay_mtp3[chl] = mtp3_para->lt[chl].t1;
						mtp3ObjState.tcoc_state[chl] = TCOC_WAIT07_STATE;
					}
				}
				else/* changeover not required */
				{
					mtp3_debug(MTP3DB_EVENT,"[tcoc]link %d changeover not required,update routing table",chl);
					hmrt_tcoc_update_routing_tables(chl);
				}
			}
		break;
		
		case TCOC_WAIT05_STATE:/* wait for e1 l1 state change to unavailable */
			if (mtp3ObjInput.tcoc_input_from_stm[chl] == TCOC_LINK_AVAILABLE)
			{
				mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
				changeover_not_req(chl);
//				mtp3_debug(MTP3DB_EVENT,"TCOC LINK %d AVAILABLE AT WAIT5 STATE",chl);
				mtp3ObjState.tcoc_state[chl] = TCOC_IDLE_STATE;
			}
			else
			{
/*				if ( local_bsnt_retrievable[chl] == TRUE )
					hmrt_tcoc_changeover_ack(chl);
				else*/
					hmrt_tcoc_emergency_changeover_ack(chl);
				mtp3ObjInput.tsrc_input_from_tcoc[chl] = TSRC_TCOC_ALTERNATIVE_ROUTING_DATA_REQUEST;
				mtp3ObjState.tcoc_state[chl] = TCOC_WAIT06_STATE;
				send_command_to_mtp2(chl,MTP2_DEACTIVE_LINK);
			}
		break;

		case TCOC_WAIT06_STATE:
			if (mtp3ObjInput.tcoc_input_from_stm[chl] == TCOC_LINK_AVAILABLE)
			{
				mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
				mtp3ObjInput.tcoc_input_from_tsrc[chl] = IDLE;
				mtp3_debug(MTP3DB_ERROR,"[tcoc]link %d AVAILABLE AT WAIT6 STATE\n\r",chl);
				changeover_not_req(chl);
			}
			else if ( mtp3ObjInput.tcoc_input_from_tsrc[chl] == TCOC_ALTERATIVE_ROUTE_DT )
			{
				mtp3ObjInput.tcoc_input_from_tsrc[chl] = IDLE;
//				mtp3_debug(MTP3DB_EVENT,"tcoc link %d get data",chl);
				if ( remote_bsnt_retrieved[chl] == TRUE )
				{
//					mtp3_debug(MTP3DB_EVENT,"chl %d retrieve begins in WAIT6",chl);
					send_command_to_mtp2(chl,MTP2_RETRIEVE);
					mtp3ObjState.tcoc_state[chl] = TCOC_RETRIEVING_STATE;
				}
				else
				{
					mtp3ObjState.tcoc_state[chl] = TCOC_SEND_BUFMSG_STATE;
				}
			}
		break;
		
		case TCOC_WAIT07_STATE:
			if (mtp3ObjInput.tcoc_input_from_stm[chl] == TCOC_LINK_AVAILABLE)
			{
				mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
				mtp3ObjInput.tcoc_input_from_tsrc[chl] = IDLE;
				mtp3_debug(MTP3DB_ERROR,"[tcoc]link %d AVAILABLE AT WAIT07 STATE\n\r",chl);
				changeover_not_req(chl);
			}
			else
			{

				t1_delay_mtp3[chl] = t1_delay_mtp3[chl] - 1;
				if ( t1_delay_mtp3[chl] == 0 )
				{
					changeover_not_req(chl);
					mtp3_debug(MTP3DB_EVENT,"[tcoc]link %d update routing table after T1 expired",chl);
					hmrt_tcoc_update_routing_tables(chl);
				}
			}
		break;
		
		case TCOC_WAITACK_STATE:
			switch (mtp3ObjInput.tcoc_input_from_stm[chl])
			{
				case TCOC_LINK_UNAVAILABLE:
				break;
				
				case TCOC_LINK_AVAILABLE:
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
					changeover_not_req(chl);
				break;
					
				case TCOC_TLAC_COO_COMMAND:
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
					if ( local_bsnt_retrievable[chl] == TRUE )
						hmrt_tcoc_changeover_ack(chl);/* send COA */
					else
						hmrt_tcoc_emergency_changeover_ack(chl);
					send_command_to_mtp2(chl,MTP2_RETRIEVE);
//					mtp3_debug(MTP3DB_EVENT,"chl %d retrieve begins in WAITACK",chl);
					mtp3ObjState.tcoc_state[chl] = TCOC_RETRIEVING_STATE;
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
				break;
					
				case TCOC_TLAC_ECO_COMMAND:
					mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
					if ( local_bsnt_retrievable[chl] == TRUE )
						hmrt_tcoc_changeover_ack(chl);
					else
						hmrt_tcoc_emergency_changeover_ack(chl);
					mtp3ObjState.tcoc_state[chl] = TCOC_SEND_BUFMSG_STATE;
					mtp3ObjInput.tcoc_input_from_hmdt[chl] = IDLE;
				break;
					
				default:
				break;
			}
			
			switch (mtp3ObjInput.tcoc_input_from_hmdt[chl])
			{
				case TCOC_HMDT_COA_COMMAND:
					mtp3ObjInput.tcoc_input_from_hmdt[chl] = IDLE;
					if (mtp3ObjState.tcoc_state[chl] == TCOC_WAITACK_STATE)
					{
//						mtp3_debug(MTP3DB_EVENT,"chl %d rv coa at waitack state",chl);
						send_command_to_mtp2(chl,MTP2_RETRIEVE);
						mtp3ObjState.tcoc_state[chl] = TCOC_RETRIEVING_STATE;
					}
				break;
				
				case TCOC_HMDT_ECA_COMMAND:
					mtp3ObjInput.tcoc_input_from_hmdt[chl] = IDLE;
					if (mtp3ObjState.tcoc_state[chl] == TCOC_WAITACK_STATE)
					{
						mtp3ObjState.tcoc_state[chl] = TCOC_SEND_BUFMSG_STATE;
					}
				break;
				
				default:
				break;
			}
			
			t2_delay_mtp3[chl] = t2_delay_mtp3[chl] - 1;
			if ( t2_delay_mtp3[chl] == 0 )
			{
//				mtp3_debug(MTP3DB_EVENT,"chl %d rv coa timeout waitack state",chl);
				if (mtp3ObjState.tcoc_state[chl] == TCOC_WAITACK_STATE)
				{
					mtp3ObjInput.lsac_input_from_tcoc[chl] = LSAC_TCOC_STOP_L2;
					mtp3ObjState.tcoc_state[chl] = TCOC_SEND_BUFMSG_STATE;
				}
			}
		break;
		
		case TCOC_RETRIEVING_STATE:
			l2_input = retrieved_bsnt[chl];
/*			if (l2_input == TCOC_L2_RETRIEVE_CMP)
			{*/
				mtp3ObjState.tcoc_state[chl] = TCOC_SEND_BUFMSG_STATE;
/*			}
			else if (l2_input == TCOC_L2_RETRIEVE_NOT_POSSIBLE)
			{
				mtp3ObjState.tcoc_state[chl] = TCOC_SEND_BUFMSG_STATE;
			}*/
		break;
		
		case TCOC_SEND_BUFMSG_STATE:
			mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_TCOC_CHANGEOVER_EXECUTED;
			mtp3ObjInput.tsrc_input_from_tcoc[chl] = TSRC_TCOC_CHANGEOVER_EXECUTED;
			mtp3ObjInput.tcoc_input_from_stm[chl] = IDLE;
			mtp3ObjInput.tcoc_input_from_hmdt[chl] = IDLE;
			mtp3ObjState.tcoc_state[chl] = TCOC_IDLE_STATE; /* IDLE STATE */
			mtp3ObjInput.lsac_input_from_tcoc[chl] = LSAC_TCOC_STM_READY;
			hmrt_tcoc_update_routing_tables(chl);
			mtp3_debug(MTP3DB_EVENT,"[tcoc]link %d update routing table after retrieved msg",chl);
		break;
		
		default:
		break;
	}
}

void changeback_terminated(WORD chl)
{
	mtp3ObjInput.tlac_input_from_stm[chl] = TLAC_TCBC_CHANGEBACK_TERMINATED;
	mtp3ObjInput.tsrc_input_from_tcbc[chl] = TSRC_PROCEDURE_TERMINATED;
	mtp3ObjState.tcbc_state[chl] = TCBC_IDLE_STATE;
	mtp3_debug(MTP3DB_EVENT,"[tcbc]link %d change back complete,update routing table",chl);
	hmrt_tcbc_update_routing_tables(chl);
}

void tcbc_proc(WORD chl)
{
	ls_info		*ls;
	WORD		lsno;
	
	ls = &mtp3.ls[mtp3_para->lk[chl].e1_to_linkset];
	
	switch (mtp3ObjState.tcbc_state[chl])
	{
		case TCBC_IDLE_STATE:
			switch (mtp3ObjInput.tcbc_input[chl])
			{
				case TCBC_LINK_UNAVAILABLE:
				break;
				
				case TCBC_LINK_AVAILABLE:
					mtp3_debug(MTP3DB_EVENT,"[tcbc]link %d available",chl);
					mtp3ObjInput.tcbc_input[chl] = IDLE;
					mtp3ObjInput.tsrc_input_from_tcbc[chl] = TSRC_TCBC_ALTERNATIVE_ROUTING_DATA_REQUEST;
					mtp3ObjState.tcbc_state[chl] = TCBC_WAIT_FOR_ROUTING_DATA_STATE;
				break;
				
				case TCBC_HMDT_CBD_COMMAND:
					mtp3ObjInput.tcbc_input[chl] = IDLE;
					hmrt_tcbc_changeback_ack(chl);
				break;
				
				case TCBC_HMDT_CBA_COMMAND:
					mtp3ObjInput.tcbc_input[chl] = IDLE;
				break;
				
				default:
				break;
			}
		break;
		
		case TCBC_WAIT_FOR_ROUTING_DATA_STATE:
			if ( mtp3ObjInput.tcbc_input_from_tsrc[chl] == TCBC_ALTERATIVE_ROUTE_DT )
			{
				mtp3_debug(MTP3DB_EVENT,"[tcbc]link %d get routing data from tsrc",chl);
//				printf("tcbc link %d get data complete\n",chl);
				mtp3ObjInput.tcbc_input_from_tsrc[chl] = IDLE;
				lsno = mtp3_para->lk[chl].e1_to_linkset;
				if ( tcbc_route_change[chl] == TRUE )
				{
					if ( cb_msg_can_exchange[chl] == TRUE )
					/* adjacent sp acessible */
					{
						hmrt_tcbc_changeback_declaration(chl);
						t4_delay_mtp3[chl] = mtp3_para->lt[chl].t4;
						mtp3ObjState.tcbc_state[chl] = TCBC_FIRST_ATTEMPT_STATE;
					}
					else
					{
//						mtp3_debug(MTP3DB_EVENT,"start t3");
						t3_delay_mtp3[chl] = mtp3_para->lt[chl].t3;
						mtp3ObjState.tcbc_state[chl] = TCBC_TCTRL_DIVERSION_STATE;
					}
				}
				else
				{
//					mtp3_debug(MTP3DB_EVENT,"error");
					mtp3ObjState.tcbc_state[chl] = TCBC_IDLE_STATE;
					changeback_terminated(chl);
				}
			}
		break;
		
		case TCBC_TCTRL_DIVERSION_STATE:
			t3_delay_mtp3[chl] = t3_delay_mtp3[chl] - 1;
			if ( t3_delay_mtp3[chl] == 0 )
				changeback_terminated(chl);
		break;
		
		case TCBC_FIRST_ATTEMPT_STATE:
			if ( mtp3ObjInput.tcbc_input[chl] == TCBC_HMDT_CBA_COMMAND )
			{
//				mtp3_debug(MTP3DB_EVENT,"tcbc receive cba");
				mtp3ObjInput.tcbc_input[chl] = IDLE;
				changeback_terminated(chl);
			}
			
			t4_delay_mtp3[chl] = t4_delay_mtp3[chl] - 1;
			if ( t4_delay_mtp3[chl] == 0 )
			{
				if (mtp3ObjState.tcbc_state[chl] == TCBC_FIRST_ATTEMPT_STATE)
				{
					hmrt_tcbc_changeback_declaration(chl);
					t5_delay_mtp3[chl] = mtp3_para->lt[chl].t5;
					mtp3ObjState.tcbc_state[chl] = TCBC_SECOND_ATTEMPT_STATE;
				}
			}
		break;
		
		case TCBC_SECOND_ATTEMPT_STATE:
			t5_delay_mtp3[chl] = t5_delay_mtp3[chl] - 1;
			if 	( t5_delay_mtp3[chl] == 0 			||
				  mtp3ObjInput.tcbc_input[chl] == TCBC_HMDT_CBA_COMMAND )
			{
				mtp3ObjInput.tcbc_input[chl] = IDLE;
				changeback_terminated(chl);
			}
		break;

		default:
		break;
	}
}

void tprc_mgmt_signalling_point_restart_indication()
{
	int		i,j;
	// tprc to llsc restart begins
	
	for ( i=0; i<MAX_LK; i++)
	{
		//llsc_input_from_stm[chl] = LLSC_INPUT_FROM_STM;
		mtp3ObjInput.tsrc_input_from_stm[i] = TSRC_RESTART_BEGINS;
		mtp3ObjInput.tlac_input_from_stm[i] = TLAC_RESTART_BEGINS;
		//tfrc_input_from_stm[chl] = TFRC_INPUT_FROM_STM;
		//rtrc_input_from_stm[chl] = RTRC_INPUT_FROM_STM;
		for ( j=0; j<4; j++ )
		{
			mtp3.nw[j].rtpc_input[i] = RTPC_RESTART_BEGINS;
			mtp3.nw[j].rtac_input[i] = RTAC_RESTART_BEGINS;
//			mtp3.nw[j].rsrt_input[i] = RSRT_RESTART_BEGINS;
			/* start t18 */
		}
	}
}

void tsrc_send_state_proc(BYTE nw)
{
	int		dst;

	for (dst=0; dst<MAX_ROUTE; dst++)
	{
		if ( (mtp3.nw[nw].routine[dst] >> 6) == 2 ) 
		{
			if ( (mtp3_para->nw[nw].routing[dst].normal_ls < 128)		&&
				 (mtp3_para->nw[nw].routing[dst].dpc != 0)				)
				mtp3.nw[nw].rtpc_input[dst] = RTPC_DEST_INACCESSIBLE;
				hmrt_tfrc_update_routing_tables(dst,tprc_nw);
		}
	}
}

void tprc_fun2()
{
	tsrc_send_state_proc(tprc_nw);
	tprc_nw++;
	mtp3ObjState.tprc_state = TPRC_WAIT03_STATE;
	t20_delay_mtp3 = mtp3_para->mtp3_t20;
}

void tprc_proc()/* we always have stp function */
{
	int		i;

	switch (mtp3ObjState.tprc_state)
	{
		case TPRC_IDLE_STATE:
			switch (mtp3ObjInput.tprc_input)
			{
				case TPRC_SP_RESTART_INDICATION:
					mtp3ObjInput.tprc_input = IDLE;
					mtp3ObjState.tprc_state = TPRC_WAIT01_STATE;
					t18_delay_mtp3 = mtp3_para->mtp3_t18;
					break;

				default:
					break;
			}
			break;

		case TPRC_WAIT01_STATE:
			t18_delay_mtp3 = t18_delay_mtp3 - 1;
			if ( t18_delay_mtp3 == 0 )/* t18 expired */
			{
				if (rv_TRA_num == active_ls_num)
					tprc_fun2();
				else
				{
					t19_delay_mtp3 = mtp3_para->mtp3_t19;//start t19
					mtp3ObjState.tprc_state = TPRC_WAIT02_STATE;
				}
			}
			else
			{
				if ( current_active_ls_num == active_ls_num)
				{
					if (rv_TRA_num == active_ls_num)
						tprc_fun2();
					else
					{
						mtp3ObjState.tprc_state = TPRC_WAIT02_STATE;
						t19_delay_mtp3 = mtp3_para->mtp3_t19;
					}
				}
			}
			break;

		case TPRC_WAIT02_STATE:
			t19_delay_mtp3 = t19_delay_mtp3 - 1;
			if ( t19_delay_mtp3 == 0 )
			{
				tprc_fun2();
			}
			break;

		case TPRC_WAIT03_STATE:
			t20_delay_mtp3 = t20_delay_mtp3 - 1;
			if ( t20_delay_mtp3 == 0 )
			{
				for ( i=0; i<MAX_LK; i++)
				{
					//llsc_input_from_stm[chl] = LLSC_INPUT_FROM_STM;
					mtp3ObjInput.tsrc_input_from_stm[i] = TSRC_RESTART_ENDS;
					mtp3ObjInput.tlac_input_from_stm[i] = TLAC_RESTART_ENDS;
					//tfrc_input_from_stm[chl] = TFRC_INPUT_FROM_STM;
					//rtrc_input_from_stm[chl] = RTRC_INPUT_FROM_STM;
				}
				mtp3ObjState.tprc_state = TPRC_RESTART_ENDS_STATE;
			}
			else
			{
				if ( tprc_nw < 4 )
				{
					tsrc_send_state_proc(tprc_nw);
					tprc_nw ++;
				}
				else
					tprc_nw = 0;
			}
			break;

		case TPRC_RESTART_ENDS_STATE:
			mtp3_debug(MTP3DB_EVENT,"sp restart ends");
			mtp3ObjInput.tprc_input = IDLE;
			for (i=0; i<MAX_LS; i++)
			{
				hmrt_tra_msg(i);
			}
			mtp3ObjState.tprc_state = TPRC_IDLE_STATE;
			rv_TRA_num = 0;
			own_sp_restarting = 0;
			break;

		default:
			break;
	}
}

void taprc_proc(WORD linkset)/* [STM]adjacent sp restart control,send TFP/TRA to adjacent sp */
{
	int		i;
	network	*sp;
	BYTE	nw;

	linkset = linkset & 0x7f;
	if (linkset >= MAX_LS)
		return;
	nw = mtp3_para->ls_pro[linkset].nw_id;
	sp = &mtp3.nw[nw];

	switch (mtp3ObjInput.taprc_input[linkset])
	{
		case TPRC_ADJACENT_SP_RESTARTING:
			for (i=taprc_loop[linkset]; i<=taprc_loop[linkset]+7; i++)
			{
				if ((sp->routine[i] & 0x30) == 0)/* dst inaccessible */
				{
					if ( (mtp3_para->nw[nw].routing[i].normal_ls < 128)		&&
						 (mtp3_para->nw[nw].routing[i].dpc != 0)			)
					{
						mtp3.nw[nw].rtpc_input[i] = RTPC_TSRC_SEND_TFP_MSG;
						sdTFP_Ls = linkset;/* send TFP to this linkset's remote sp */
						rtpc_proc(nw,i);
					}
				}
			}
			taprc_loop[linkset] = taprc_loop[linkset] + 8;
			if ( taprc_loop[linkset] == 0 )
			{
				mtp3ObjInput.taprc_input[linkset] = IDLE;
				sending_phase_finished[linkset] = TRUE;
				hmrt_tra_msg(linkset);
//				mtp3_debug(MTP3DB_EVENT,"Sd TFA to linkset %d remote sp",linkset);
			}
			break;
		default:
			break;
		
	}
}
/*@end@*/
