view src/g23m-gprs/sm/sm.c @ 171:3a8c90814d1a

armio.c: GTM900 support from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 19 Jun 2019 04:27:44 +0000
parents d393cd9bb723
children
line wrap: on
line source

/*----------------------------------------------------------------------------
|  Project :  3G PS
|  Module  :  SM
+-----------------------------------------------------------------------------
|             Copyright 2003 Texas Instruments.
|             All rights reserved. 
| 
|             This file is confidential and a trade secret of Texas 
|             Instruments .
|             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. 
+-----------------------------------------------------------------------------
| Purpose:    Utility functions implementation in the SM entity.
|             For design details, see:
|             8010.908 SM Detailed Specification
+---------------------------------------------------------------------------*/

/*==== DECLARATION CONTROL =================================================*/

/*==== INCLUDES =============================================================*/

#include <stdio.h>
#include "sm.h"

/*==== CONSTS ===============================================================*/

/*==== TYPES ================================================================*/

/*==== LOCALS ===============================================================*/

/*==== PRIVATE FUNCTIONS ====================================================*/

/*==== PUBLIC FUNCTIONS =====================================================*/

/*
+------------------------------------------------------------------------------
| Function    : sm_nsapi2nsapi_set
+------------------------------------------------------------------------------
| Description : Returns nsapi_set corresponding to the input NSAPI
|
| Parameters  : nsapi               - NSAPI to convert to nsapi_set
+------------------------------------------------------------------------------
*/
U16 sm_nsapi2nsapi_set(int /*@alt U8@*/ nsapi)
{
  return (U16)(1UL << (U8)nsapi);
}

/*
+------------------------------------------------------------------------------
| Function    : sm_add_nsapi_to_nsapi_set
+------------------------------------------------------------------------------
| Description : Returns nsapi_set with nsapi added to it (1 << nsapi).
|
| Parameters  : nsapi               - NSAPI to add
|               nsapi_set           - nsapi_set to which to add NSAPI
+------------------------------------------------------------------------------
*/
U16 sm_add_nsapi_to_nsapi_set(int /*@alt U8@*/ nsapi, U16 nsapi_set)
{
  return (nsapi_set | sm_nsapi2nsapi_set(nsapi));
}

/*
+------------------------------------------------------------------------------
| Function    : sm_remove_nsapi_from_nsapi_set
+------------------------------------------------------------------------------
| Description : Returns nsapi_set with nsapi removed from it (1 << nsapi).
|
| Parameters  : nsapi               - NSAPI to remove
|               nsapi_set           - nsapi_set in which to remove NSAPI
+------------------------------------------------------------------------------
*/
U16 sm_remove_nsapi_from_nsapi_set(int /*@alt U8@*/ nsapi, U16 nsapi_set)
{
  return (nsapi_set & (0xffff ^ sm_nsapi2nsapi_set(nsapi)));
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_nsapi_in_nsapi_set
+------------------------------------------------------------------------------
| Description : Returns TRUE iff the input NSAPI (converted to nsapi_set) is
|               set in the input nsapi_set.
|
| Parameters  : nsapi               - NSAPI whose presence to check
|               nsapi_set           - nsapi_set to compare
+------------------------------------------------------------------------------
*/
BOOL sm_is_nsapi_in_nsapi_set(int /*@alt U8,U16@*/ nsapi, U16 nsapi_set)
{
  return ((nsapi_set & sm_nsapi2nsapi_set(nsapi)) != 0);
}

/*
+------------------------------------------------------------------------------
| Function    : sm_nsapi_to_index
+------------------------------------------------------------------------------
| Description : Returns array index corresponding to NSAPI (nsapi - 5)
|
| Parameters  : nsapi               - NSAPI value
+------------------------------------------------------------------------------
*/
U16 /*@alt int@*/ sm_nsapi_to_index(U16 /*@alt U8,int@*/nsapi)
{
  TRACE_ASSERT((T_NAS_nsapi)nsapi >= NAS_NSAPI_5 && nsapi <= NAS_NSAPI_15);
  return (nsapi - (U16)NAS_NSAPI_5);
}

/*
+------------------------------------------------------------------------------
| Function    : sm_index_to_nsapi
+------------------------------------------------------------------------------
| Description : Returns nsapi value corresponding to array index (index + 5)
|
| Parameters  : index               - index value
+------------------------------------------------------------------------------
*/
U16 /*@alt int@*/ sm_index_to_nsapi(U16 /*@alt U8,int@*/index)
{
  TRACE_ASSERT(index < SM_MAX_NSAPI_OFFSET);
  return (index + (U16)NAS_NSAPI_5);
}

/*
+------------------------------------------------------------------------------
| Function    : sm_get_pdp_context_status
+------------------------------------------------------------------------------
| Description : Get the network status of all NSAPIs.  A bit is set in the
|               nsapi_set, iff the context corresponding to the NSAPI is
|               not in network state INACTIVE.
|
| Parameters  : None
+------------------------------------------------------------------------------
*/
U16 sm_get_pdp_context_status(void)
{
  return sm_data.sm_context_activation_status;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_get_current_rat
+------------------------------------------------------------------------------
| Description : Returns the RAT in which SM is currently active
|
| Parameters  : None
+------------------------------------------------------------------------------
*/
T_PS_rat /*@alt U8@*/sm_get_current_rat(void)
{
  return sm_data.sm_current_rat;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_current_rat
+------------------------------------------------------------------------------
| Description : Sets the RAT in which SM is currently active
|
| Parameters  : rat                 - Active RAT (GSM / UMTS)
+------------------------------------------------------------------------------
*/
void sm_set_current_rat(T_PS_rat rat)
{
  if (rat == PS_RAT_GSM || rat == PS_RAT_UMTS_FDD) {
    sm_data.sm_current_rat = rat;
  } else {
    (void)TRACE_ERROR("Tried to set unknown RAT! (This is OK for EDGE)");
  }
}

/*
+------------------------------------------------------------------------------
| Function    : sm_get_current_nw_release
+------------------------------------------------------------------------------
| Description : Returns the core network release of the network in which SM
|               is currently active
|
| Parameters  : None
+------------------------------------------------------------------------------
*/
T_PS_sgsn_rel /*@alt U8@*/ sm_get_current_nw_release(void)
{
  return sm_data.sm_current_nw_release;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_suspended
+------------------------------------------------------------------------------
| Description : Returns TRUE if SM is suspended, i.e. has received an
|               MMPM_SUSPEND_IND primitive from MM.
|
| Parameters  : None
+------------------------------------------------------------------------------
*/
BOOL sm_is_suspended(void)
{
  return sm_data.sm_suspended;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_attached
+------------------------------------------------------------------------------
| Description : Returns TRUE if SM is attached, i.e. has received an
|               MMPM_ATTACH_IND primitive from MM.
|
| Parameters  : None
+------------------------------------------------------------------------------
*/
BOOL sm_is_attached(void)
{
  return sm_data.sm_attached;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_secondary
+------------------------------------------------------------------------------
| Description : Returns TRUE if secondary flag is set for the context.
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
BOOL sm_is_secondary(struct T_SM_CONTEXT_DATA *context)
{
  return (context->flags & (U8)SM_CONTEXT_FLAG_SECONDARY_CONTEXT) != (U8)0;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_secondary
+------------------------------------------------------------------------------
| Description : Set secondary flag for the input context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
void sm_set_secondary(struct T_SM_CONTEXT_DATA *context)
{
  context->flags |= (U8)SM_CONTEXT_FLAG_SECONDARY_CONTEXT;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_started_during_suspend
+------------------------------------------------------------------------------
| Description : Set started during suspend flag for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
void sm_set_started_during_suspend(struct T_SM_CONTEXT_DATA *context)
{
  if (sm_is_suspended()) {
    context->flags |= (U8)SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND;
  } else {
    context->flags &= 0xff ^ (U8)SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND;
  }
}

/*
+------------------------------------------------------------------------------
| Function    : sm_clear_started_during_suspend
+------------------------------------------------------------------------------
| Description : Clear started during suspend flag for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
void sm_clear_started_during_suspend(struct T_SM_CONTEXT_DATA *context)
{
  context->flags &= 0xff ^ (U8)SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_started_during_suspend
+------------------------------------------------------------------------------
| Description : Return TRUE if started during suspend flag is set for the
|               context.
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
BOOL sm_is_started_during_suspend(struct T_SM_CONTEXT_DATA *context)
{
  return (context->flags & (U8)SM_CONTEXT_FLAG_STARTED_DURING_SUSPEND) != (U8)0;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_mark_context_for_deallocation
+------------------------------------------------------------------------------
| Description : Set pending deallocation flag for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
void sm_mark_context_for_deallocation(struct T_SM_CONTEXT_DATA *context)
{
  context->flags |= (U8)SM_CONTEXT_FLAG_PENDING_DEALLOCATION;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_context_pending_deallocation
+------------------------------------------------------------------------------
| Description : Returns TRUE if pending deallocation flag is set for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
BOOL sm_is_context_pending_deallocation(struct T_SM_CONTEXT_DATA *context)
{
  return (context->flags & (U8)SM_CONTEXT_FLAG_PENDING_DEALLOCATION) != (U8)0;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_context_pending_reactivation
+------------------------------------------------------------------------------
| Description : Set or clear pending reactivation flag for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
void sm_set_context_pending_reactivation(struct T_SM_CONTEXT_DATA *context, BOOL flag)
{
  if (flag)
  {
    context->flags |= (U8)(U8)SM_CONTEXT_FLAG_PENDING_REACTIVATION;
  } else {
    context->flags &= 0xff ^ (U8)(U8)SM_CONTEXT_FLAG_PENDING_REACTIVATION;
  }
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_context_pending_reactivation
+------------------------------------------------------------------------------
| Description : Returns TRUE if pending reactivation flag is set for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
BOOL sm_is_context_pending_reactivation(struct T_SM_CONTEXT_DATA *context)
{
  return (context->flags & (U8)SM_CONTEXT_FLAG_PENDING_REACTIVATION) != (U8)0;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_aci_update_required
+------------------------------------------------------------------------------
| Description : Returns TRUE if one of the flags affecting the SMREG interface
|               have changed/are set.
|
| Parameters  : update_flags        - Update flags
+------------------------------------------------------------------------------
*/
BOOL sm_is_aci_update_required(T_SM_UPDATE_FLAGS update_flags)
{
  if ((int)(update_flags & SM_UPDATE_QOS)           != 0 ||
      (int)(update_flags & SM_UPDATE_QOS_DOWNGRADE) != 0 ||
      (int)(update_flags & SM_UPDATE_ADDRESS)       != 0 ||
      (int)(update_flags & SM_UPDATE_COMP_PARAMS)   != 0) {
    return TRUE;
  }
  return FALSE;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_user_plane_update_required
+------------------------------------------------------------------------------
| Description : Returns TRUE if one of the flags affecting the SM interface
|               have changed/are set.
|
| Parameters  : update_flags        - Update flags
+------------------------------------------------------------------------------
*/
BOOL sm_is_user_plane_update_required(T_SM_UPDATE_FLAGS update_flags)
{
  if ((int)(update_flags & SM_UPDATE_QOS)                 != 0 ||
      (int)(update_flags & SM_UPDATE_COMP_PARAMS)         != 0 ||
      (int)(update_flags & SM_UPDATE_SAPI_RADIO_PRIO_PFI) != 0) {
    return TRUE;
  }
  return FALSE;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_pfi_included
+------------------------------------------------------------------------------
| Description : Set PFI included flag for the context
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
void sm_set_pfi_included(struct T_SM_CONTEXT_DATA *context, BOOL flag)
{
  if (flag)
  {
    context->flags |= (U8)SM_CONTEXT_FLAG_PFI_PRESENT;
  } else {
    context->flags &= 0xff ^ (U8)SM_CONTEXT_FLAG_PFI_PRESENT;
  }
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_pfi_included
+------------------------------------------------------------------------------
| Description : Return TRUE if PFI included flag is set for the context.
|
| Parameters  : context             - Context data
+------------------------------------------------------------------------------
*/
BOOL sm_is_pfi_included(struct T_SM_CONTEXT_DATA *context)
{
  return (context->flags & (U8)SM_CONTEXT_FLAG_PFI_PRESENT) != (U8)0;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_is_llc_sapi_valid
+------------------------------------------------------------------------------
| Description : Return TRUE if the LLC SAPI provided is valid, FALSE otherwise.
|
| Parameters  : llc_sapi            - LLC SAPI
|               ti                  - TI for context
+------------------------------------------------------------------------------
*/
BOOL sm_is_llc_sapi_valid(U8 llc_sapi, U8 ti)
{
  /* This check is only valid in non-UMTS-single mode configurations */
#if !defined(TI_UMTS) || defined(TI_DUAL_MODE)
  T_CAUSE_ps_cause          cause;

  if ( (llc_sapi == PS_SAPI_3) ||
       (llc_sapi == PS_SAPI_5) ||
       (llc_sapi == PS_SAPI_9) ||
       (llc_sapi == PS_SAPI_11) )
  {
    /* LLC SAPI is OK.  Return TRUE. */
    return TRUE;
  } else {
    /* LLC SAPI has a reserved value. Send a status message. */
    cause.ctrl_value       = CAUSE_is_from_nwsm;
    cause.value.nwsm_cause = (U16)CAUSE_NWSM_INVALID_MANDATORY_ELEMENT;
    send_msg_sm_status(ti, &cause);
    return FALSE;
  } 
#else
  /* In UMTS single mode, this check is disabled */
  return TRUE;
#endif
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_current_nw_release
+------------------------------------------------------------------------------
| Description : Sets the core network release of the network in which SM
|               is currently active
|
| Parameters  : sgsn_rel            - Network release (pre-R99 / R99)
+------------------------------------------------------------------------------
*/
void sm_set_current_nw_release(T_PS_sgsn_rel sgsn_rel)
{
  if (sgsn_rel == PS_SGSN_98_OLDER || sgsn_rel == PS_SGSN_99_ONWARDS) {
    sm_data.sm_current_nw_release = sgsn_rel;
  } 
  else { /*The Berlin way*/
    /*If SGSN release is unknown set the value to R98*/
    (void)TRACE_ERROR("Tried to set unknown core network release. \
                         Setting R97 as default !");
    sm_data.sm_current_nw_release = PS_SGSN_98_OLDER;
  }
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_aci_cause
+------------------------------------------------------------------------------
| Description : Sets the cause value for a context. Used during retransmissions
|               etc.
|
| Parameters  : context             - context data
|               ctrl_cause          - cause originator
|               cause               - vause value
+------------------------------------------------------------------------------
*/
void sm_set_aci_cause(struct T_SM_CONTEXT_DATA *context,
		  T_CAUSE_ctrl_value ctrl_cause, U16 cause)
{
  (void)TRACE_EVENT_P2("sm_set_aci_cause(ctrl=%d, cause=%04x)", (int)ctrl_cause, cause);
  TRACE_ASSERT(context != NULL);
  /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */
  context->aci_cause.ctrl_value       = ctrl_cause;
  context->aci_cause.value.nwsm_cause = cause;
  /*lint +e613 (Possible use of null pointer 'context' in left argument to operator '->') */
}

/*
+------------------------------------------------------------------------------
| Function    : sm_get_aci_cause
+------------------------------------------------------------------------------
| Description : Gets the cause value for a context. Used during retransmissions
|               etc.
|
| Parameters  : context             - context data
+------------------------------------------------------------------------------
*/
/*@observer@*/
T_CAUSE_ps_cause *sm_get_aci_cause(struct T_SM_CONTEXT_DATA *context)
{
  TRACE_ASSERT(context != NULL);
  /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */
  return &context->aci_cause;
}

/*
+------------------------------------------------------------------------------
| Function    : sm_set_nw_cause
+------------------------------------------------------------------------------
| Description : Sets the cause value for a context. Used during retransmissions
|               etc.
|
| Parameters  : context             - context data
|               ctrl_cause          - cause originator
|               cause               - vause value
+------------------------------------------------------------------------------
*/
void sm_set_nw_cause(struct T_SM_CONTEXT_DATA *context,
		  T_CAUSE_ctrl_value ctrl_cause, U16 cause)
{
  TRACE_ASSERT(context != NULL);
  /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */
  context->nw_cause.ctrl_value       = ctrl_cause;
  context->nw_cause.value.nwsm_cause = cause;
  /*lint +e613 (Possible use of null pointer 'context' in left argument to operator '->') */
}

/*
+------------------------------------------------------------------------------
| Function    : sm_get_nw_cause
+------------------------------------------------------------------------------
| Description : Gets the cause value for a context. Used during retransmissions
|               etc.
|
| Parameters  : context             - context data
+------------------------------------------------------------------------------
*/
/*@observer@*/
T_CAUSE_ps_cause *sm_get_nw_cause(struct T_SM_CONTEXT_DATA *context)
{ 
TRACE_ASSERT(context != NULL);
/*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */
#ifdef DEBUG
  if (context->nw_cause.ctrl_value != CAUSE_is_from_nwsm &&
      context->nw_cause.ctrl_value != CAUSE_is_from_sm) {
    (void)TRACE_EVENT_P2("sm_get_nw_cause(): ERROR! Cause element not "
			 "initialized or not from SM (ctrl=%d, cause=%d)",
		   context->nw_cause.ctrl_value, context->nw_cause.value.nwsm_cause);
  }
#endif
  return &context->nw_cause;
/*lint +e613 (Possible use of null pointer 'context' in left argument to operator '->') */
}

/*==== END OF FILE ==========================================================*/