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

 @(#) $Id: sls_hmdt.h,v 0.7.2.4 2001/02/03 05:48:53 brian Test $

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

 Copyright (C) 1997, 1998, 1999, 2000  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:53 $ by $Author: brian $

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

#ifndef __SLS_HMDT_H__
#define __SLS_HMDT_H__

/*
 *  This is the Signalling Link Set version of the HMDT state machine.  If the
 *  message is a management message which can be handled by the link set state
 *  machines it is handled here.  Otherwise, the message is forwarded to the
 *  MTP state machines (at the route and routeset levels).  In any case, the
 *  message has already been decoded (by HMDC) to the extent that it can be
 *  determined whether the message is a management or user part message.  No
 *  other parsing of the received message is necessary.  If the message is
 *  passed on to the MTP for further distribution, it is passed already
 *  parsed.
 *
 *  This state machine also keeps track of Own SP Restart conditions.  That
 *  way, messages which are not accepted during Own SP Restart are discarded
 *  here instead of being passed to the MTP (route and route set) state
 *  machines to be ultimately discarded.
 */

/*
 *  Referenced funtions.
 */

static inline void lk_lsda_hmdt_connection_not_possible(lk_t *lk, mblk_t *mp);
static inline void lk_lsda_hmdt_connection_not_successful(lk_t *lk, mblk_t *mp);
static inline void lk_lsda_hmdt_connection_successful(lk_t *lk, mblk_t *mp);
static inline void lk_lsda_hmdt_signalling_data_link_connection_order(lk_t *lk, mblk_t *mp);

static inline void lk_sltc_hmdt_signalling_link_test_ack(lk_t *lk, mblk_t *mp);
static inline void lk_sltc_hmdt_signalling_link_test_ack_special(lk_t *lk, mblk_t *mp);
static inline void lk_sltc_hmdt_signalling_link_test_msg(lk_t *lk, mblk_t *mp);
static inline void lk_sltc_hmdt_signalling_link_test_msg_special(lk_t *lk, mblk_t *mp);

static inline void lk_tcbc_hmdt_changeback_ack(lk_t *lk, mblk_t *mp);
static inline void lk_tcbc_hmdt_changeback_declaration(lk_t *lk, mblk_t *mp);

static inline void lk_tlac_hmdt_changeover_order(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_emergency_changeover_order(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_force_unihibit_signalling_link(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_inhibit_ack(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_inhibit_denied(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_inhibit_signalling_link(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_local_inhibit_test(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_remote_inhibit_test(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_unihibit_ack(lk_t *lk, mblk_t *mp);
static inline void lk_tlac_hmdt_uninhibit_signalling_link(lk_t *lk, mblk_t *mp);

static inline void lk_tcoc_hmdt_changeover_ack(lk_t *lk, mblk_t *mp);
static inline void lk_tcoc_hmdt_emergency_changeover_ack(lk_t *lk, mblk_t *mp);

static inline void mtp_hmdt_hmdc_message_for_distribution(lk_t *lk, mblk_t *mp);


/*
 *  Forward declarations.
 */

static inline void lk_hmdt_hmdc_message_for_distribution(lk_t *lk, mblk_t *mp);

/*
 *  Consistent with:
 *
 *      Signalling Message Handling (SHM)
 *      Message Distribution (HMDT)
 *      Figure 25/Q.704
 */

static inline void lk_hmdt_hmdc_message_for_distribution(lk_t *lk, mblk_t *mp)
{
    ls_t *ls = lk->module;
    ls_prim_t *p = (ls_prim_t *)mp->b_rptr;
    if ( ls->statem.own_sp_restart ) {
        switch ( p->sig.signal ) {
            case LS_SIGNAL_TFP:
            case LS_SIGNAL_TFR:
            case LS_SIGNAL_TFA:
            case LS_SIGNAL_TRA:
            case LS_SIGNAL_SLTM:
            case LS_SIGNAL_SLTA:
            case LS_SIGNAL_SSLTM:
            case LS_SIGNAL_SSLTA:
                break;
            default:
                /* discard all other messages while restarting */
                freemsg(mp);
                return;
        }
    }
    switch ( p->sig.mh.si ) {
        case 0x0:
            switch ( p->sig.mh.h0 ) {
                case 0x1:
                case 0x2:
                    switch ( p->sig.signal ) {
                        case LS_SIGNAL_COO:
                            return lk_tlac_hmdt_changeover_order(&ls->device[p->coo.slc], mp);
                        case LS_SIGNAL_COA:
                            return lk_tcoc_hmdt_changeover_ack(&ls->device[p->coa.slc], mp);
                        case LS_SIGNAL_CBD:
                            return lk_tcbc_hmdt_changeback_declaration(&ls->device[p->cbd.slc], mp);
                        case LS_SIGNAL_CBA:
                            return lk_tcbc_hmdt_changeback_ack(&ls->device[p->cba.slc], mp);
                        case LS_SIGNAL_ECO:
                            return lk_tlac_hmdt_emergency_changeover_order(&ls->device[p->eco.slc], mp);
                        case LS_SIGNAL_ECA:
                            return lk_tcoc_hmdt_emergency_changeover_ack(&ls->device[p->eca.slc], mp);
                    }
                    break;
                case 0x6:
                    switch ( p->sig.signal ) {
                        case LS_SIGNAL_LIN:
                            return lk_tlac_hmdt_inhibit_signalling_link(&ls->device[p->lin.slc], mp);
                        case LS_SIGNAL_LIA:
                            return lk_tlac_hmdt_inhibit_ack(&ls->device[p->lia.slc], mp);
                        case LS_SIGNAL_LUN:
                            return lk_tlac_hmdt_uninhibit_signalling_link(&ls->device[p->lun.slc], mp);
                        case LS_SIGNAL_LUA:
                            return lk_tlac_hmdt_unihibit_ack(&ls->device[p->lua.slc], mp);
                        case LS_SIGNAL_LID:
                            return lk_tlac_hmdt_inhibit_denied(&ls->device[p->lid.slc], mp);
                        case LS_SIGNAL_LFU:
                            return lk_tlac_hmdt_force_unihibit_signalling_link(&ls->device[p->lfu.slc], mp);
                        case LS_SIGNAL_LLI:
                            return lk_tlac_hmdt_local_inhibit_test(&ls->device[p->lli.slc], mp);
                        case LS_SIGNAL_LRI:
                            return lk_tlac_hmdt_remote_inhibit_test(&ls->device[p->lri.slc], mp);
                    }
                    break;
                case 0x8:
                    switch ( p->sig.signal ) {
                        case LS_SIGNAL_DLC:
                            return lk_lsda_hmdt_signalling_data_link_connection_order(&ls->device[p->dlc.slc], mp);
                        case LS_SIGNAL_CSS:
                            return lk_lsda_hmdt_connection_successful(&ls->device[p->css.slc], mp);
                        case LS_SIGNAL_CNS:
                            return lk_lsda_hmdt_connection_not_successful(&ls->device[p->cns.slc], mp);
                        case LS_SIGNAL_CNP:
                            return lk_lsda_hmdt_connection_not_possible(&ls->device[p->cnp.slc], mp);
                    }
                    break;
                case 0x4:
                case 0x5:
                case 0x7:
                    mtp_hmdt_hmdc_message_for_distribution(lk, mp);
                    return;
                default:
                    break;
            }
            break;
        case 0x1:
        case 0x2:
            switch ( p->sig.mh.h0 ) {
                case 0x1:
                case 0x2:
                    switch ( p->sig.signal ) {
                        case LS_SIGNAL_SLTM:
                            return lk_sltc_hmdt_signalling_link_test_msg(&ls->device[p->sltm.slc], mp);
                        case LS_SIGNAL_SLTA:
                            return lk_sltc_hmdt_signalling_link_test_ack(&ls->device[p->slta.slc], mp);
                        case LS_SIGNAL_SSLTM:
                            return lk_sltc_hmdt_signalling_link_test_msg_special(&ls->device[p->ssltm.slc], mp);
                        case LS_SIGNAL_SSLTA:
                            return lk_sltc_hmdt_signalling_link_test_ack_special(&ls->device[p->sslta.slc], mp);
                    }
                    break;
            }
            break;
        default:
            mtp_hmdt_hmdc_message_for_distribution(lk, mp);
            return;
    }
    freemsg(mp);
    return;
}

#endif  __SLS_HMDT_H__

