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

 @(#) $Id: sls_lsda.h,v 0.7.2.9 2001/02/03 05:48:54 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:54 $ by $Author: brian $

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

#ifndef __SLS_LSDA_H__
#define __SLS_LSDA_H__

/*
 *  Referenced functions.
 *
 *  This state machine accesses HMRT functions.
 */

static inline void lk_tsrc_lsda_alternative_routing_data_request(lk_t *lk);

/* link and linkset functions */

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

static void inline lk_lsla_lsda_data_link(lk_t *lk);
static void inline lk_lsla_lsda_no_data_link(lk_t *lk);

static void inline lk_lslr_lsda_data_link(lk_t *lk);
static void inline lk_lslr_lsda_no_data_link(lk_t *lk);

/*
 *  Forward declarations.
 */

static void inline lk_t7_timeout(lk_t *lk);

static void inline lk_lsda_tsrc_alternate_routing_data(lk_t *lk);    /* from MTP */

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

static void inline lk_lsda_lsld_data_link_available(lk_t *lk);

static void inline lk_lsda_lsla_determine_data_link(lk_t *lk);

static void inline lk_lsda_lslr_determine_data_link(lk_t *lk);

/*
 *  Message building functions.
 */

static inline void lk_lsda_send_signalling_data_link_connection_order(lk_t *lk, mblk_t *mp)
{
    ls_t *ls;
    ls_prim_t *p;
    if ( !(mp = __msg_alloc(mp)) ) return;
    ls = lk->module;
    p = (ls_prim_t *)mp->b_rptr;
    p->primitive      = LS_MESSAGE_FOR_ROUTING_IND;
    p->sig.signal     = LS_SIGNAL_DLC;
    p->dlc.mh.ni     = ls->config.ni;
    p->dlc.mh.mp     = 0x3;
    p->dlc.mh.si     = 0x0;
    p->dlc.mh.rl.dpc = ls->config.apc;
    p->dlc.mh.rl.opc = ls->config.lpc;
    p->dlc.mh.rl.sls = lk->config.slc;  /* FIXME */
    p->dlc.slc       = lk->config.slc;
    p->dlc.sdli      = lk->statem.sdli; /* FIXME */
    lk_hmrt_lsda_signalling_data_link_connection_order(lk, mp);
}

/*
 *  Signalling Link Management (SLM)
 *  Signalling Link Data Link Allocation (LSDA)
 *  Figure 42/Q.704
 */

static void inline lk_lsda_lsla_determine_data_link(lk_t *lk)
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_IDLE:
            lk->statem.activation = 1;
            lk_tsrc_lsda_alternative_routing_data_request(lk);
            lk->statem.lsda_state = LK_STATE_WAIT;
            break;
    }
}

static void inline lk_lsda_lslr_determine_data_link(lk_t *lk)
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_IDLE:
            lk->statem.restoration = 1;
            lk_tsrc_lsda_alternative_routing_data_request(lk);
            lk->statem.lsda_state = LK_STATE_WAIT;
            break;
    }
}

static void inline lk_lsda_lsld_data_link_available(lk_t *lk)
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_IDLE:
            lk->statem.data_link_available = 1;
            break;
        case LK_STATE_WAIT:
            lk->statem.data_link_available = 1;
            break;
        case LK_STATE_WAITING:
            lk->statem.data_link_available = 1;
            break;
        case LK_STATE_WAITING_FOR_CONNECTION:
            lk->statem.data_link_available = 1;
            break;
    }
}

static void inline lk_lsda_hmdt_signalling_data_link_connection_order(lk_t *lk, mblk_t *mp)  /* from remote MTP */
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_IDLE:
            lk->statem.sdli = ((ls_prim_t *)mp->b_rptr)->dlc.sdli;  /* FIXME */
            /* FIXME: don't know what to do with these: put them in routing request? */
            lk_tsrc_lsda_alternative_routing_data_request(lk);
            lk->statem.lsda_state = LK_STATE_WAITING;
            break;
    }
    freemsg(mp);
}

static void inline lk_lsda_hmdt_connection_successful(lk_t *lk, mblk_t *mp) /* from remote MTP */
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_WAITING_FOR_CONNECTION:
            lk_timer_stop(t7);
            if ( lk->statem.activation  ) lk_lsla_lsda_data_link(lk);
            if ( lk->statem.restoration ) lk_lslr_lsda_data_link(lk);
            lk->statem.activation = 0;
            lk->statem.restoration = 0;
            lk->statem.lsda_state = LK_STATE_IDLE;
            break;
    }
    freemsg(mp);
}

static void lk_t7_timeout(lk_t *lk)
{
    /* FIXME: make me dooo something */
}

static void inline lk_lsda_hmdt_connection_not_successful(lk_t *lk, mblk_t *mp) /* from remote MTP */
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_WAITING_FOR_CONNECTION:
            lk_timer_stop(t7);
            if ( lk->statem.data_link_available ) { /* FIXME: is this check correct? */
                /* FIXME: select data link */
                lk_lsda_send_signalling_data_link_connection_order(lk, mp);
                lk_timer_start(t7);
                lk->statem.lsda_state = LK_STATE_WAITING_FOR_CONNECTION;
            } else {
                if ( lk->statem.activation  ) lk_lsla_lsda_no_data_link(lk);
                if ( lk->statem.restoration ) lk_lslr_lsda_no_data_link(lk);
                lk->statem.activation = 0;
                lk->statem.restoration = 0;
                lk->statem.lsda_state = LK_STATE_IDLE;
                freemsg(mp);
            }
            return;
    }
    freemsg(mp);
}

static void inline lk_lsda_hmdt_connection_not_possible(lk_t *lk, mblk_t *mp) /* from remote MTP */
{
    switch ( lk->statem.lsda_state ) {
        case LK_STATE_WAITING_FOR_CONNECTION:
            lk_timer_stop(t7);
            if ( lk->statem.activation  ) lk_lsla_lsda_no_data_link(lk);
            if ( lk->statem.restoration ) lk_lslr_lsda_no_data_link(lk);
            lk->statem.activation = 0;
            lk->statem.restoration = 0;
            lk->statem.lsda_state = LK_STATE_IDLE;
            break;
    }
    freemsg(mp);
}

static void inline lk_lsda_tsrc_alternate_routing_data(lk_t *lk)
{
    /*
     *  Alternate routing data identifies alternative link
     *  to be used for routing link management messages.
     */
    switch (lk->statem.lsda_state ) {
        case LK_STATE_WAIT:
            if ( lk->statem.data_link_available ) { /* FIXME: is this check correct? */
                /* FIXME: select data link */
                lk_lsda_send_signalling_data_link_connection_order(lk, NULL);
                lk_timer_start(t7);
                lk->statem.lsda_state = LK_STATE_WAITING_FOR_CONNECTION;
            } else {
                if ( lk->statem.activation  ) lk_lsla_lsda_no_data_link(lk);
                if ( lk->statem.restoration ) lk_lslr_lsda_no_data_link(lk);
                lk->statem.activation = 0;
                lk->statem.restoration = 0;
                lk->statem.lsda_state = LK_STATE_IDLE;
            }
            break;
        case LK_STATE_WAITING:
            break;
    }
}

/*
 *  12.4    Signalling link management procedures based on automatic allocation of
 *          signalling data links and signalling terminals
 *
 *  12.4.1  Signalling link activation
 *
 *  12.4.1.1    In the absence of failures a link set contains a certain
 *  predetermined number of active (i.e. aligned) signalling links.  The link set
 *  may also contain a number of inactive signalling links.
 *
 *  An inactive signalling link is a signalling link currently not in operation.  It
 *  is not associated with any signalling terminal or signalling data link (i.e. the
 *  signalling link is only identified by its position in the link set).
 *
 *  The number of active and inactive signalling links (in the absence of failures),
 *  and the priority order for the signalling links in a link set, should be
 *  identical at both ends of the link set.
 *
 *  12.4.1.2    Whenever the number of active signalling links is below the value
 *  specified for the link set, actions to activate new inactive signalling links
 *  should be taken automatically.  This is, for example, applicable when a link set
 *  is to be brought into service for the first time (see 12.4.4) or when a link
 *  failure occurs.  In the latter case, activation starts when the restoration
 *  attempts on the faulty link are considered unsuccessful (see 12.4.2).
 *
 *  The signalling link(s) to activate is the inactive link(s) having the highest
 *  priority in the link set.
 *
 *  If it is not possible to activate a signalling link, an attempt to activate the
 *  next inactive signalling link (in priority order) is made.  In the case when an
 *  activation attempt performed on the last signalling link in the link set is
 *  unsuccessful, the "next" signalling link is the first inactive link in the link
 *  set (i.e., a cyclic assignment).
 *
 *  NOTE - Activation of the next signalling link is only initiated if the link set
 *  includes an alternative link group, having access to other signalling terminals
 *  and/or other signalling data links than the signalling link for which activation
 *  is not possible.
 *
 *  Activation of particular signallin link may also be initiated upon receiving a
 *  request from the remote signalling point, or my a manual request.
 *
 *  Activation shall not be initiated automatically for a signalling link previously
 *  inactivated by means of a manual intervention.
 *
 *  12.4.1.3    When a decision is taken to activate a signallin link, the
 *  signalling terminals and signallin data link to tbe employed have to be
 *  allocated.
 *
 *  A signalling terminal is allocated automatically by means of the function
 *  defined in 12.5.
 *
 *  The signalling data link is allocated automatically by means of the function
 *  defined in 12.6.  However, in conjunction with link set activation the identity
 *  of the signalling data link to use may be predetermined (see further 12.4.4).  A
 *  signalling data link which is not connected to a signalling terminal may be
 *  utilized for other purposes, e.g. as a speech circuit.  When the data link is to
 *  be employed for signalling, it must be removed from its alternative use.
 *
 *  In the case when the automatic allocation functions cannot provide a signalling
 *  terminal or a signallin data link, the activation attempt is aborted.
 *
 *  12.4.1.4    When the signalling data link and signalling terminal to be used for
 *  a particular signalling link are determined, the signalling terminal is
 *  connected to the signalling data link and signalling link initial alignment
 *  starts (see clause 7/Q.703).  If the initial alignment procedure is successful,
 *  the signalling link is active and a signalling link set test is started.  If the
 *  signalling link test is successful, the link becomes ready to convey signalling
 *  traffic.
 *
 *  If initial alignment is not possible, as determined at Message Transfer Part
 *  level 2 (see clause 7/Q.703), alternative signalling data links are
 *  automatically connected to the signalling terminal, until an initial alignment
 *  procedure is successfully completed.  In the case when the function for
 *  automatic allocation of signalling data links cannot provide an alternative
 *  signalling data link, the activation is regarded as unsuccessful and activation
 *  of the next inactive signalling link (if any) is initiated (see, however, the
 *  Note to 12.4.1.2 above).
 *
 *  12.4.2  Signalling link restoration
 *
 *  12.4.2.1    After a signalling link failure is recognized, signalling link
 *  initial alignment will take place (see clause 7/Q.703).  In the case when the
 *  initial alignment is successful, a signalling link test is started.  If the
 *  signalling link test is successful the link becomes restored and thus available
 *  for signalling.
 *
 *  If the initial alignment is unsuccessful or if the test fails, the signalling
 *  terminal and signalling data link may be faulty and require replacement.
 *
 *  12.4.2.2    The signalling data link may be automatically replaced by an
 *  alternative, in accordance with the principles defined in 12.6.  After the new
 *  signalling data link has been connected to the signalling terminal, signalling
 *  link initial alignment starts.  If successful, the signalling link is restored.
 *  If not, alternative data links are connected to the signalling terminal, until
 *  an initial alignment procedure is successfully completed.
 *
 *  If the automatic allocation function cannot provide a new signalling data link,
 *  activation of the next inactive signalling link (if any) is initiated (see,
 *  however, the Note to 12.4.1.2).  Successive initial alignment attempts may,
 *  however, continue on the previous (faulty) signalling link after a time T17
 *  until it is restarted or its signalling terminal is disconnected.
 *
 *  12.4.2.3    The signalling terminal amy be automatically replaced in accordance
 *  with the principles defined in 12.5.  After the new signalling terminal has been
 *  connected to the signalling data link, signalling link initial alignment starts.
 *  If successful, the signalling link is restored.  If not, activation of the next
 *  signalling link in the link set (if any) starts (see, however, the Note to
 *  12.4.1.2).
 *
 *  Successive initial alignment attempts may, however, continue on the previous
 *  (faulty) signalling link after a time T17 until it is restored or, for example,
 *  the signalling terminal or signallin data link is disconnected.
 *
 *  NOTE - Activation of the next signalling link in the link set should not be
 *  initiated as long as one of the activities described in 12.4.2.2 and 12.4.2.3
 *  above is taking place.
 *
 *  12.4.3  Signalling link deactivation
 *
 *  In the absence of failures, a link set contains a specified number of active
 *  (i.e. aligned) signalling links.  Whenever that number is exceeded (e.g. as a
 *  result of signalling link restoration) the active signalling link having the
 *  lowest priority in the link set is to be made inactive automatically, provided
 *  that no signalling traffic is carried on that signalling link.
 *
 *  Deactivation of a particular signalling link amy also be initiated manually,
 *  e.g. in conjunction with manual maintenance activities.
 *
 *  When a decision has been taken to deactivate a signalling link, the signalling
 *  terminal and signalling data link may be disconnected.  After deactivation the
 *  idle signalling terminal and signalling data link may become parts of other
 *  signalling links (see 12.5 and 12.6).
 *
 *  12.4.4  Link set activation
 *
 *  Link set activation is applicable in the case when a link set is not having any
 *  signalling links in service is to be started for the first time or after a
 *  failures (see 12.3.4).  The link set activation procedure is performed as
 *  specified in 12.3.4, also as regards the allocation of signalling data links,
 *  i.e. signalling data links are allocated in accordance with predetermined list
 *  assigning a signalling data link to some or all of the singalling links in the
 *  link set.  This is done in order to cater for the situation when it is not
 *  possible to communicate with the remote end of the link set (see 12.6).
 *  However, when a signalling link has become active, signalling data link
 *  allocation may again be performed automatically (i.e., activation of a
 *  signalling link takes place as specified in 12.4.1).
 *  
 *  12.5    Automatic allocation of signalling terminals
 *
 *  In conjunction with the signalling link activation and restoration procedures
 *  specified in 12.3 and 12.4, signalling terminals may be allocated automatically
 *  to signalling link.  A signalling terminal applicable to the link group is
 *  allocated in accordance with the following principles:
 *
 *  a)  an idle signalling terminal (i.e. a signalling terminal not connected to a
 *      signalling data link) is chosen if possible;
 *
 *  b)  if no idle signalling terminal is chosen which is connected to an
 *      unsuccessfully restored or activated signalling link.
 *
 *  NOTE 1 - Activation and restoration is regarded as unsuccessful when it is not
 *  possible to complete the initial alignment procedure successfully (see 12.3 and
 *  12.4).
 *
 *  Measures should be employed to ensure that signalling terminal to be allocated
 *  to signalling links are able to function correctly (see Recommendation Q.707).
 *
 *  A link set may be assigned a certain number of signalling terminals.  A
 *  signalling terminal may be transferred from a signalling link in one link set to
 *  a signalling link in another set (in accordance with b) above) only when the
 *  remaining number of signalling terminals in the link set is not below the
 *  specified value.
 *
 *  NOTE 2 - From a link set with a minimum number of signalling terminals, only one
 *  signalling terminal and signallin data link may be removed at a timer (e.g. for
 *  testing see Recommendation Q.707).
 *
 *  12.6    Automatic allocation of signalling data links
 *
 *  12.6.1  In conjunction with the signalling link activation and restoration
 *  procedures specified in 12.4, signalling data links may be allocated
 *  automatically.  Any signalling data link applicable to a link group may be
 *  chosen for a signalling link within that link group.
 *
 *  The signalling data links applicable to a link group are determined bilateral
 *  agreement and may, for example, include all speech circuits between two
 *  exchanges.  A signalling data link may also be established as a semi-permanent
 *  connection via one or more intermediate exchanges.
 *
 *  When a potential signalling data link is not employed for signalling, it is
 *  normally used for other purposes (e.g. as a speech circuit).
 *
 *  The identity of the signalling data link to be used for a particular signalling
 *  link is determined at one of the two involved signalling points and reported to
 *  the remote end by a signalling data link connection order message.  The
 *  signalling point controlling the choice of signalling data link is the
 *  signalling point initiating the activation or restoration procedure or, in the
 *  case when both ends initiate the procedure at the same time, the signalling
 *  point having the highest signalling point code (included in the label of the
 *  message).
 *
 *  12.6.2  When a signalling data link has been chosen at a signalling point, the
 *  data link is made unavailable for other uses (e.g. as a speech circuit) and an
 *  order to connect the appointed signalling data link to a signalling terminal is
 *  sent to the signalling point at the remote end of the signalling link.
 *
 *  The signalling-data-link-connection-order message contains:
 *
 *  -   the label, indicating the destination and originating signalling points and
 *      the identity of the signalling link to activate or restore;
 *
 *  -   the signalling-data-link-connection-order,
 *  -   the identity of the signalling data link.
 *
 *  Formats and codes for the signalling-data-link-connection-order message appear
 *  in clause 15.
 *
 *  12.6.3  Upon reception of the signalling-data-link-connection-order, the
 *  following applies:
 *
 *  a)  In the case when the signalling link to which a received
 *      signalling-data-link-connection-order message refers is inactive as seen
 *      from the receiving signalling point, the message is regarded as an order to
 *      activate the concerned signalling link, resulting in, for example,
 *      allocation of a signalling terminal.  The signalling data link indicated in
 *      the signalling-data-link-connection-order is then connected to the
 *      associated signallinga terminal and signalling link initial alignment
 *      starts.  An acknowledgement is sent to the route signalling point.
 *
 *      If it is not possible to connect the appointed signalling data link to a
 *      signalling terminal (e.g. because there is no working signalling terminal
 *      available), the acknowledgement contains an indication informing the remote
 *      signalling point whether or not an alternative signalling data link should
 *      be allocated to the concerned signalling link.
 *
 *  b)  If the signalling point receives a signalling-data-link-connection-order
 *      when waiting for an acknowledgement, the order is disregarded in the case
 *      when the signalling point code of the receiving signalling point is higher
 *      than the signalling point code of the remote signalling point.  If the
 *      remote signalling point has the higher signalling point code, the message is
 *      acknowledged and the signalling data link referred to in the received
 *      message is connected.
 *
 *  c)  If a signalling-data-link-connection-order is received in other situations
 *      (e.g. in the case of an error in procedure), no actions are taken.
 *
 *  The signalling-data-link-connection-acknowledgement contains the label,
 *  indicating the destination and originating signalling points and the identity of
 *  the signalling link to activate or restore, and one of the following signals:
 *
 *  -   connection-successful signal, indicating that the signalling data link has
 *      been connected to a signalling terminal;
 *
 *  -   connection-not-successful signal, indicating that it was not possible to
 *      connect the signalling data link to a signalling terminal, and that an
 *      alternative signalling data link should be allocated.
 *
 *  -   connection-not-possible signal, indicating that it was not possible to
 *      connect the signalling data link to a signalling terminal, and that no
 *      alternative signalling data link should be allocated.
 *
 *  The formats and codes for the signalling data link connection acknowledgement
 *  message apear in clause 15.
 *
 *  12.6.4  When the signalling point initiating the procedure receives a message
 *  indicating that signalling data link and signalling terminal have been connected
 *  at the remote end, the signalling data link is connected to the associated
 *  signalling terminalan initial alignment starts (see 12.4).
 *
 *  In the acknowledgement indicates that it was not possible to connect the
 *  signalling data link to a signalling terminal at the remote end, an alternative
 *  signalling data link is allocated and a new
 *  signalling-data-link-connection-order is sent (as specified above).  However, if
 *  the acknowledgement indicates that no alternative signalling data link should be
 *  allocated, the activation or restoration procedure is terminated for the
 *  concerned signalling link.
 *
 *  If no signalling-data-link-connection-acknowledgement or order is received from
 *  the remote signalling point within a time T7 (see clause 16), the
 *  signalling-data-link-connection-order is repeated.
 *
 *  12.6.5  When a signalling data link is disconnected in conjunction with
 *  signalling link restoration or deactivation, the signalling data link is made
 *  idle (and available, e.g. as a speech circuit).
 *
 *  12.7    Different signalling link management procedures at the two ends of a
 *          link set
 *
 *  Normally both ends of a link set will use the same signalling link management
 *  procedures.
 *
 *  However, if one end uses the basic signalling link management procedures, the
 *  other end may use the signalling link management procedures based on automatic
 *  allocation of signalling terminals.  In that case a signalling link includes a
 *  predetermined signalling terminal at one end, a predetermined signalling data
 *  link and at the other end, any of the signalling terminals applicable to the
 *  concerned link group.
 *
 *  If one end of a link set uses the basic signalling link management procedures
 *  and the other end uses the signalling link management procedures based on
 *  automatic allocation of signalling terminals, the values of the initial
 *  alignment time-out T2 does not have to be different at the two ends of the link
 *  set.
 *
 */

#endif  __SLS_LSDA_H__

