diff src/g23m-gprs/llc/llc_ul.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/llc/llc_ul.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,623 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  
+|  Modul   :  
++----------------------------------------------------------------------------- 
+|  Copyright 2002 Texas Instruments Berlin, AG 
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Berlin, AG 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Berlin, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  This modul is part of the entity LLC and implements all labels
+|             in the SDL-documentation (U-statemachine) that are called from
+|             more than one diagram/place.
++----------------------------------------------------------------------------- 
+*/ 
+
+#ifndef LLC_UL_C
+#define LLC_UL_C
+#endif
+
+#define ENTITY_LLC
+
+/*==== INCLUDES =============================================================*/
+
+#include "typedefs.h"   /* to get Condat data types */
+#include "vsi.h"        /* to get a lot of macros */
+#include "macdef.h"
+#include "gprs.h"
+#include "gsm.h"        /* to get a lot of macros */
+#include "cnf_llc.h"    /* to get cnf-definitions */
+#include "mon_llc.h"    /* to get mon-definitions */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#include "llc.h"        /* to get the global entity definitions */
+
+#include "llc_uf.h"     /* to get local U functions */
+#include "llc_ul.h"     /* to get local U labels */
+#include "llc_llmes.h"  /* to get signal interface to LLME */
+#include "llc_t200s.h"  /* to get signal interface to T200 */
+#include "llc_txs.h"    /* to get signal interface to TX */
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_handle_mX_zero_rsp
++------------------------------------------------------------------------------
+| Description : This function handles the XID response in case we want to set
+|               mX to zero and the peer does not. 
+|
+| Parameters  : mX_req  - requested value of mD or mU
+|               n201_i  - ptr to current n201_i
+|               mX      - ptr to current (=received) mD or current mU
+|               kX      - ptr to current kD or current kU
+|               kX_min  - minimum value of kD or kU
+|               kX_max  - maximum value of kD or kU
+|               kX_type - XID_KU or XID_KD
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_handle_mX_zero_rsp (USHORT mX_req, USHORT* n201_i, 
+                                  USHORT mX,     USHORT  mX_max,    
+                                  UBYTE* kX,     UBYTE   kX_min, 
+                                  UBYTE  kX_type )
+{
+  TRACE_FUNCTION( "u_handle_mX_zero_rsp" );
+
+  /*
+   * calc new N201-I and/or kX, if necessary
+   */
+#if XID_N201_I_MIN != 0u /* avoid division with 0 */
+  if ( (mX_max == 0u) AND (mX_req != 0u) AND (*kX * mX > mX_req) )
+  {
+    /*
+     * first try to reduce n201-I only, else reduce also k
+     * Note: *kX can't be 0 here
+     */
+    if ( *kX * XID_N201_I_MIN <= mX_req * 16u )
+    {
+      /*
+       * calc and tag N201-I
+       */
+      *n201_i = (mX_req * 16u) / *kX;
+      
+      llc_data->u->xid_tag |= (0x00000001L << XID_N201_I);
+
+    }
+    else if ( kX_min * XID_N201_I_MIN <= mX_req * 16u )
+    {
+      /*
+       * calc and tag N201-I and kX 
+       */
+      *n201_i = XID_N201_I_MIN;
+      *kX     = (mX_req * 16u) / XID_N201_I_MIN;
+
+      llc_data->u->xid_tag |= (0x00000001L << XID_N201_I);
+      llc_data->u->xid_tag |= (0x00000001L << kX_type);
+    }
+    else
+    {
+      TRACE_ERROR("Requested value of mX is too small");
+    }
+  }
+#endif /* XID_N201_I_MIN != 0u */
+} /* u_handle_mX_zero_rsp() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_xid
++------------------------------------------------------------------------------
+| Description : Describes label XID
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to an LL_UNITDATA_IND
+|                                 primitive
+|               command         - contains command of primitive
+|               cr_bit          - setting of C/R bit
+|               pf_bit          - setting of P/F bit
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_xid (T_LL_UNITDATA_IND *ll_unitdata_ind, 
+                         T_COMMAND command,
+                         T_BIT cr_bit,
+                         T_BIT pf_bit)
+{ 
+  BOOL              reset_received;
+  BOOL              xid_ind;
+
+  
+  TRACE_FUNCTION( "u_label_xid" );
+
+  if (pf_bit EQ 1)
+  {
+    /*
+     * Check XID parameters and store the decoded values in 
+     * llc_data->decoded_xid.
+     */
+    if (u_check_xid (&ll_unitdata_ind->sdu, cr_bit, command))
+    {
+      /*
+       * In case of reset, all incarnations in ABM are set to ADM 
+       * by u_eval_xid()!
+       */
+      u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+      if (llc_data->u->xid_pending)
+      {
+        /*
+         * We have an XID command collision!
+         */
+
+        if ( (llc_data->decoded_l3_xid.valid EQ TRUE) AND 
+             !(llc_data->u->xid_tag_sent & (0x00000001L << XID_LAYER_3)))
+        {
+          /*
+           * Peer XID command contains layer-3 parameters, our XID command
+           * doesn't.
+           */
+          llc_data->u->xid_pending = FALSE;
+
+          sig_u_t200_stop_req();
+
+          /*
+           * Label XID_VALID
+           */
+          u_label_xid_valid (ll_unitdata_ind, reset_received, xid_ind);
+        }
+        else if (reset_received)
+        {
+          /*
+           * An XID command including a valid reset shall not be ignored
+           * and takes precedence over all collision issues
+           */
+          llc_data->u->xid_pending = FALSE;
+
+          sig_u_t200_stop_req();
+
+          /*
+           * Label XID_VALID
+           */
+          u_label_xid_valid (ll_unitdata_ind, reset_received, xid_ind);
+        }
+        else
+        {
+          /*
+           * Layer-3 XID parameters are present in both or neither XID 
+           * commands.
+           */
+          PFREE (ll_unitdata_ind);
+        }
+      }
+      else /* xid_pending == FALSE (no XID command sent) */
+      {
+        /*
+         * Label XID_VALID
+         */
+        u_label_xid_valid (ll_unitdata_ind, reset_received, xid_ind);
+      }
+    }
+    else /* u_check_xid() == FALSE (XID invalid) */
+    {
+      PFREE (ll_unitdata_ind);
+      TRACE_0_INFO("invalid XID information field");
+    }
+  }
+  else /* pf_bit == 0 (bit is not set) */
+  {
+    PFREE (ll_unitdata_ind);
+  }
+
+  return;
+} /* u_label_xid() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_xidres
++------------------------------------------------------------------------------
+| Description : Describes label XIDRES
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to an LL_UNITDATA_IND
+|                                 primitive
+|               command         - contains command of primitive
+|               cr_bit          - setting of C/R bit
+|               pf_bit          - setting of P/F bit
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_xidres (T_LL_UNITDATA_IND *ll_unitdata_ind, 
+                            T_COMMAND command,
+                            T_BIT cr_bit,
+                            T_BIT pf_bit)
+{ 
+  BOOL              reset_received;
+  BOOL              xid_ind;
+  BOOL              l3p_outstanding;
+
+  
+  TRACE_FUNCTION( "u_label_xidres" );
+
+  if (pf_bit EQ 1)
+  {
+    /*
+     * Check XID parameters and store the decoded
+     * values in llc_decode_xid
+     */
+    if (u_check_xid (&ll_unitdata_ind->sdu, cr_bit, command))
+    {
+      l3p_outstanding = (llc_data->u->xid_tag_sent & (0x1L << XID_LAYER_3)) ? TRUE : FALSE;
+
+      /*
+       * An XID response frame should only be handled if the XID L3 
+       * para are included or not same as requested. Else ignore it!
+       */
+      if (llc_data->decoded_l3_xid.valid == l3p_outstanding)
+      {
+        /*
+         * If an XID parameter is not included in the response and
+         * if it was included in the request, the requested value is
+         * implicit accepted.
+         */
+        u_handle_optimization ();
+
+        /*
+         * Now check XID parameter
+         */
+        u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+        /*
+         * Label XIDRES_VALID
+         */
+
+        llc_data->u->xid_pending = FALSE;
+
+        sig_u_t200_stop_req ();
+
+        if (l3p_outstanding)
+        {
+          u_send_ll_xid_cnf ();
+        }
+        else
+        {
+          if (xid_ind == TRUE)
+          {
+            u_send_ll_xid_ind ();
+          }
+        }
+
+        PFREE (ll_unitdata_ind);
+      }
+      else
+      {
+        /*
+         * Ignore frame
+         */
+        PFREE (ll_unitdata_ind);
+      }
+    }
+    else
+    {
+      /*
+       * Request T200 to let the timer manually expire.
+       */
+      sig_u_t200_expire_req ();
+      PFREE (ll_unitdata_ind);
+    }
+  }
+  else /* bit is not set */
+  {
+    PFREE (ll_unitdata_ind);
+  }
+} /* u_label_xidres() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_xid_sabm_send
++------------------------------------------------------------------------------
+| Description : Describes label XID_SABM_SEND
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to an LL_UNITDATA_IND
+|                                 primitive
+|               cr_bit          - setting of C/R bit
+|               pf_bit          - setting of P/F bit
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_xid_sabm_send (T_LL_UNITDATA_IND *ll_unitdata_ind, 
+                                   T_BIT cr_bit,
+                                   T_BIT pf_bit)
+{ 
+  BOOL              reset_received;
+  BOOL              xid_ind;
+
+  
+  TRACE_FUNCTION( "u_label_xid_sabm_send" );
+
+  if (pf_bit EQ 1)
+  {
+    /*
+     * Check XID parameters and store the decoded values in 
+     * llc_data->decoded_xid.
+     */
+    if (u_check_xid (&ll_unitdata_ind->sdu, cr_bit, U_XID))
+    {
+      /*
+       * We have received an valid XID. If a reset is included
+       * this must be handled even in case of an collision
+       */
+      if (llc_data->decoded_xid.reset.valid)
+      {
+        /*
+         * All incarnations in ABM are set to ADM by u_eval_xid()!
+         */
+        u_eval_xid (cr_bit, &reset_received, &xid_ind);
+
+        /*
+         * Label XID_VALID
+         */
+        u_label_xid_valid (ll_unitdata_ind, reset_received, xid_ind);
+      }
+      else
+      {
+        PFREE (ll_unitdata_ind);
+      }
+    }
+    else /* u_check_xid() == FALSE (XID invalid) */
+    {
+      PFREE (ll_unitdata_ind);
+      TRACE_0_INFO("invalid XID information field");
+    }
+  }
+  else /* pf_bit == 0 (bit is not set) */
+  {
+    PFREE (ll_unitdata_ind);
+  }
+
+  return;
+} /* u_label_xid_sabm_send() */
+
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_xid_valid
++------------------------------------------------------------------------------
+| Description : Describes label XID_VALID
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to an LL_UNITDATA_IND
+|                                 primitive
+|               reset_received  - indicates if reset parameter has been 
+|                                 received
+|               xid_ind         - indicates if LL_XID_IND must be sent to
+|                                 layer 3
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_xid_valid (T_LL_UNITDATA_IND *ll_unitdata_ind,
+                               BOOL reset_received,
+                               BOOL xid_ind)
+{ 
+  UBYTE  inc;
+  
+  TRACE_FUNCTION( "u_label_xid_valid" );
+
+  if (reset_received)
+  {
+  	/* LLC informs GRLC to flush out LLC PDUs maintained in GRLC when XID reset
+     * is received by LLC */
+    PALLOC (grlc_flush_data_req, GRLC_FLUSH_DATA_REQ);
+    PSEND (hCommGRLC, grlc_flush_data_req);
+
+    /*
+     * First send reset indication, then handle it.
+     */
+    {
+    PALLOC (ll_reset_ind, LL_RESET_IND);
+    ll_reset_ind->sapi = llc_data->current_sapi;
+    TRACE_PRIM_TO("SND");
+    PSEND (hCommSNDCP, ll_reset_ind);
+    }
+    /*
+     * V(U) and V(UR) are set to 0. All services that are 
+     * affected from ABM -> ADM are also reset.
+     */
+    sig_u_llme_reset_ind();
+    /*
+     * Check if the config primitive "DELAY" was received and wait 
+     * for certain number of milliseconds
+     */
+    if (llc_data->millis > 0) {
+      TRACE_1_OUT_PARA("Sleeping for :%d milliseconds", llc_data->millis);
+      vsi_t_sleep(VSI_CALLER llc_data->millis); 
+    }
+    /* 
+     * After receiving a reset all running L3 requests should 
+     * be ignored and no confirmation has to be send.
+     */
+    for (inc = 0; inc < U_NUM_INC; inc++)
+    {
+      SWITCH_SERVICE (llc, u, inc);
+
+      llc_data->u->release_requested   = FALSE;
+      llc_data->u->ll_xid_resp_pending = FALSE;
+    }
+
+    /*
+     * Switch back to original SAPI
+     */
+    SWITCH_LLC (ll_unitdata_ind->sapi);
+  }
+
+  u_tag_xid_parameters (MS_RESPONSE, FALSE);
+
+  /*
+   * Check if we have to send an LL_XID_IND
+   */
+  if (llc_data->u->xid_tag & (0x00000001L << XID_N201_U) AND llc_data->u->requested_xid.n201_u.valid)
+  {
+     xid_ind = TRUE;
+  }
+  if (llc_data->u->xid_tag & (0x00000001L << XID_N201_I) AND llc_data->u->requested_xid.n201_i.valid)
+  {
+     xid_ind = TRUE;
+  }
+
+  /*
+   * If no Layer 3 XID parameters are included we don't have to wait 
+   * for an LL_XID_RES
+   */
+  if (llc_data->decoded_l3_xid.valid NEQ TRUE)
+  {
+    /*
+     * Label S_XID_RES
+     */
+    u_send_xid (MS_RESPONSE);
+  }
+
+  if (xid_ind)
+  {
+    u_send_ll_xid_ind ();
+  }
+
+  if (reset_received)
+  {
+
+    /*
+     * V(U) and V(UR) are set to 0. All services that are 
+     * affected from ABM -> ADM are also reset.
+     */
+    sig_u_llme_ready_ind();
+    
+    /*
+     * Switch back to original SAPI
+     */
+    SWITCH_LLC (ll_unitdata_ind->sapi);
+  }
+
+
+
+  PFREE (ll_unitdata_ind);
+
+  return;
+} /* u_label_xid_valid() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_frmr_cond
++------------------------------------------------------------------------------
+| Description : Describes label FRMR_COND
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to the frame that caused the
+|                                 frame rejection condition
+|               cr_bit          - C/R bit setting of frame
+|               frmr_reason     - reason of frame rejection condition
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_frmr_cond (T_LL_UNITDATA_IND *ll_unitdata_ind,
+                               T_BIT cr_bit,
+                               UBYTE frmr_reason)
+{
+  TRACE_FUNCTION ( "u_label_frmr_cond" );
+
+  u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_COND);
+
+  u_send_frmr (ll_unitdata_ind, U_FRAME, FRMR_CTRL_LENGTH_UNKNOWN, 
+    llc_data->sapi->vs, llc_data->sapi->vr,
+    cr_bit, frmr_reason);
+
+  PFREE (ll_unitdata_ind);
+
+  return;
+} /* u_label_frmr_cond() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_frmr_cond_reest
++------------------------------------------------------------------------------
+| Description : Describes label FRMR_COND_REEST
+|
+| Parameters  : ll_unitdata_ind - a valid pointer to the frame that caused the
+|                                 frame rejection condition
+|               cr_bit          - C/R bit setting of frame
+|               frmr_reason     - reason of frame rejection condition
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_frmr_cond_reest (T_LL_UNITDATA_IND *ll_unitdata_ind,
+                                     T_BIT cr_bit,
+                                     UBYTE frmr_reason)
+{
+  TRACE_FUNCTION ( "u_label_frmr_cond_reest" );
+
+  u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_COND_REEST);
+
+  SET_STATE (U, U_LOCAL_ESTABLISHMENT);
+
+  sig_u_llme_abmrel_ind();
+
+  u_send_frmr (ll_unitdata_ind, U_FRAME, FRMR_CTRL_LENGTH_UNKNOWN, 
+    llc_data->sapi->vs, llc_data->sapi->vr,
+    cr_bit, frmr_reason);
+
+  PFREE (ll_unitdata_ind);
+
+  llc_data->u->retransmission_counter = 0;
+
+  /*
+   * Send LL_ESTABLISH_IND after successful establishment.
+   */
+  llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT;
+
+  /*
+   * Re-establishment procedure: send GRLC_DATA_REQ (SABM), start T200.
+   */
+  u_send_sabm();
+
+  return;
+} /* u_label_frmr_cond_reest() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : u_label_s_est_ind
++------------------------------------------------------------------------------
+| Description : Describes label S_EST_IND
+|
+| Parameters  : pf_bit  - setting of P/F bit
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void u_label_s_est_ind (T_BIT pf_bit)
+{
+  TRACE_FUNCTION ( "u_label_s_est_ind" );
+
+  SET_STATE (U, U_REMOTE_ESTABLISHMENT);
+
+  u_send_ll_establish_ind ();
+
+  sig_u_llme_abmrel_ind();
+
+  return;
+} /* u_label_s_est_ind() */
+
+