/*****************************************************************************

 @(#) $Id: lk_lsac.h,v 0.7.2.1 2001/02/03 05:48:37 brian Test $

 -----------------------------------------------------------------------------

 Copyright (C) 1997-2001  Brian Bidulock <bidulock@dallas.net>

 All Rights Reserved.

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 675 Mass
 Ave, Cambridge, MA 02139, USA.

 -----------------------------------------------------------------------------

 Last Modified $Date: 2001/02/03 05:48:37 $ by $Author: brian $

 *****************************************************************************/

#ifndef __LKI_LSAC_H__
#define __LKI_LSAC_H__

/*
 *  Signalling Link Managmenet (SLM)
 *
 *  Signalling Link Activity Control (LSAC) Figure 27/Q.704
 */

static void lk_t17_timeout(lk_t *lk)
{
    if ( lk->statem.lsac_state == LK_STATE_WAIT ) {
        lk->statem.lsac_state = LK_STATE_ACTIVATING_RESTORING;
        if ( lk->statem.emergency )
            lk->dcalls->sl_emerg(lk);
        lk->dcalls->sl_start(lk);
    }
}

#define lk_lsac_data_link lk_lsac_activate_link
static inline void lk_lsac_activate_link(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_INACTIVE:
            lk->statem.lsac_state = LK_STATE_ACTIVATING_RESTORING;
            lk_lsla_start_activation(lk);
            lk->statem.activation = 1;
            break;
    }
}

static inline void lk_lsac_activation_not_possible(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk->statem.lsac_state = LK_STATE_INACTIVE;
            lk_lsld_deactivate_link(lk);
            if ( !lk->statem.activation_restoration_unsuccessful )
                ls_llsc_activate_another_link(lk->module);
            break;
    }
}

static inline void lk_lsac_emergency(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_INACTIVE:
            lk->statem.emergency = 1;
            break;
        case LK_STATE_ACTIVATING_RESTORING:
            lk->statem.emergency = 1;
            lk->dcalls->sl_emerg(lk);
            break;
        case LK_STATE_ACTIVE:
            lk->statem.emergency = 1;
            break;
    }
}

static inline void lk_lsac_emergency_ceases(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_INACTIVE:
            lk->statem.emergency = 0;
            break;
        case LK_STATE_ACTIVATING_RESTORING:
            lk->statem.emergency = 0;
            lk->dcalls->sl_normal(lk);
            break;
        case LK_STATE_ACTIVE:
            lk->statem.emergency = 0;
            break;
    }
}

static inline void lk_lsac_local_processor_outage(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_INACTIVE:
            lk->statem.local_processor_outage = 1;
            lk->dcalls->sl_lpo(lk); /* national option */
            break;
    }
}

static inline void lk_lsac_local_processor_recovered(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_INACTIVE:
            lk->statem.local_processor_outage = 0;
            lk->dcalls->sl_resume(lk); /* national option */
            break;
    }
}

static inline void lk_lsac_slt_successful(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk->statem.lsac_state = LK_STATE_ACTIVE;
            ls_tlac_link_in_service(lk->module);
            ls_llsc_link_active(lk->module);
            lk->statem.first_failure = 0;
            lk->statem.activation_restoration_unsuccessful = 0;
            break;
    }
}

static inline void lk_lsac_in_service(lk_t *lk) /* from sl */
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk_sltc_start_slt(lk);
            break;
    }
}

static inline void lk_lsac_out_of_service(lk_t *lk) /* from sl */
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            if ( lk->statem.first_failure ) {
                lk_lsta_terminal_available(lk);
                lk->statem.first_failure = 0;
            } else {
                lk->statem.first_failure = 1;
            }
            if ( lk->statem.activation ) {
                lk->statem.activation = 0;
                lk_lsla_restart_activation(lk);
            } else
                lk_lslr_restart_restoration(lk);
            break;
        case LK_STATE_ACTIVE:
            lk->statem.lsac_state = LK_STATE_FAILED;
            lk_tlac_signalling_link_failed(lk);
            ls_llsc_link_failed(lk->module);
            break;
    }
}

static inline void lk_lsac_start_signalling_link(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk->statem.lsac_state = LK_STATE_WAIT;
            lk_timer_start(t17);
            break;
    }
}

static inline void lk_lsac_activation_unsuccessful(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            if ( !lk->statem.activation_restoration_unsuccessful ) {
                lk->statem.activation_restoration_unsuccessful = 1;
                ls_llsc_activate_another_link(lk->module);
            }
            break;
    }
}

static inline void lk_lsac_restoration_unsuccessful(lk_t *lk)
{
    lk_lsac_activation_unsuccessful(lk);
}

static inline void lk_lsac_deactivate_link(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk->statem.lsac_state = LK_STATE_INACTIVE;
            lk->dcalls->sl_stop(lk);
            lk_lsld_deactivate_link(lk);
            lk_lsla_deactivate_link(lk);
            ls_llsc_link_inactive(lk->module);
            if ( lk->statem.activation_restoration_unsuccessful )
                lk->statem.activation_restoration_unsuccessful = 0;
            else
                ls_llsc_activate_another_link(lk->module);
            break;
        case LK_STATE_ACTIVE:
            lk->statem.lsac_state = LK_STATE_WAIT;
            ls_tlac_signalling_link_failed(lk->module);
            break;
    }
}

static inline void mgmt_lsac_deactivate_link(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk_lsac_deactivate_link(lk);
            break;
        case LK_STATE_ACTIVE:
            lk->statem.lsac_state = LK_STATE_WAIT;
            ls_llsc_activate_another_link(lk->module);
            lk_lsac_deactivate_link(lk);
            break;
    }
}

static inline void lk_lsac_slt_failed(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk_lsac_deactivate_link(lk);
            break;
    }
}

static inline void lk_lsac_restart_ends(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            ls_tlac_signalling_link_failed(lk->module);
            break;
    }
}

static inline void lk_lsac_remote_processor_recovered(lk_t *lk) /* from sl */
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVATING_RESTORING:
            lk_sltc_start_slt(lk);
            break;
        case LK_STATE_ACTIVE:
            lk_tlac_remote_processor_recovered(lk);
            break;
    }
}

static inline void lk_lsac_stop_l2(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_ACTIVE:
            lk->statem.lsac_state = LK_STATE_FAILED;
            lk->dcalls->sl_stop(lk);
            ls_llsc_link_failed(lk->module);
            break;
    }
}

static inline void lk_lsac_stm_ready(lk_t *lk)
{
    switch ( lk->statem.lsac_state ) {
        case LK_STATE_FAILED:
            lk->statem.lsac_state = LK_STATE_ACTIVATING_RESTORING;
            lk_lslr_start_restoration(lk);
            break;
        case LK_STATE_WAIT:
            lk->statem.lsac_state = LK_STATE_INACTIVE;
            lk->dcalls->sl_stop(lk);
            lk_lsld_deactivate_link(lk);
            ls_llsc_link_inactive(lk->module);
            break;
    }
}

static inline void lk_lsac_changeover_order_received(lk_t *lk)
{
    lk_lsac_stop_l2(lk);
}

static inline void lk_lsac_flush_buffers(lk_t *lk)
{
    if ( lk->statem.lsac_state == LK_STATE_ACTIVE )
        lk->dcalls->sl_clear_bufs(lk);
}

static inline void lk_lsac_continue(lk_t *lk)
{
    if ( lk->statem.lsac_state == LK_STATE_ACTIVE )
        lk->dcalls->sl_resume(lk);
}

static inline void lk_lsac_remote_processor_outage(lk_t *lk) /* from sl */
{
    if ( lk->statem.lsac_state == LK_STATE_ACTIVE )
        lk_tlac_remote_processor_outage(lk);
}

#endif  __LKI_LSAC_H__

