view src/g23m-gprs/grr/grr_psif.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 219afcfc6250
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GPRS (8441)
|  Modul   :  GRR
+----------------------------------------------------------------------------- 
|  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 module implements local functions for service PSI of
|             entity GRR.
+----------------------------------------------------------------------------- 
*/ 

#ifndef GRR_PSIF_C
#define GRR_PSIF_C
#endif

#define ENTITY_GRR

#ifdef _SIMULATION_

/*
 * Report warning 4005 as an error.
 * 
 * There are identical macro definitons in the GRR message and the RRGRR SAP 
 * document which should be aligned at all the time
 * (e.g. GPRS_RXLEV_ACCESS_MIN_INVALID, GPRS_MS_TXPWR_MAX_CCH, etc.)
 */
#pragma warning( error : 4005 )

#endif /* #ifdef _SIMULATION_ */

/*==== 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 "ccdapi.h"     /* to get CCD API */
#include "cnf_grr.h"    /* to get cnf-definitions */
#include "mon_grr.h"    /* to get mon-definitions */
#include "prim.h"       /* to get the definitions of used SAP and directions */
#include "message.h"
#include "grr.h"        /* to get the global entity definitions */
#include "grr_f.h"
#include "grr_psif.h"   /* */
#include "grr_ctrls.h"  /* */
#include "grr_css.h"   /* signals exchanged between PSI and CS*/
#include "grr_meass.h"   /* signals exchanged between PSI and MEAS*/

#include <string.h>    /* for memcpy */
#include <stdio.h>     /* for memcpy */
#include "grr_em.h"     /*for Engineering mode*/

/*==== DIAGNOSTICS ==========================================================*/

/*==== CONST ================================================================*/
#define PBCCH_NOT_PRESENT    0x0           /* PBCCH not present in the cell  */
#define PBCCH_PRESENT        0x1           /* PBCCH present in the cell      */
/*==== LOCAL VARS ===========================================================*/
LOCAL void psi_reset_psi_pos  ( void );
#ifndef _TARGET_
LOCAL void psi_fill_rel_pos(UBYTE *src, UBYTE max_src, UBYTE *psi_nr, UBYTE *pos_array);
#endif /*_TARGET_*/
/*==== PRIVATE FUNCTIONS ====================================================*/

LOCAL void psi_reset_complete_acq ( void );
LOCAL void psi_reset_psi1 (void );
LOCAL void psi_reset_psi2 (void );
LOCAL void psi_reset_psi3 (void );
LOCAL void psi_reset_psi3bis (void );
#if defined (REL99) AND defined (TI_PS_FF_EMR)
LOCAL void psi_reset_psi3ter (void );
#endif
LOCAL void psi_reset_psi4 (void );
LOCAL void psi_reset_psi5 (void );
#ifdef REL99
LOCAL void psi_reset_psi8 (void);
#endif
LOCAL void psi_reset_psi13 (void );
LOCAL void psi_init_states_of_psi ( void );
LOCAL void psi_init_rfl_psi2(void);
LOCAL void psi_init_cell_alloc(void);
LOCAL void psi_init_gprs_ms_alloc(BOOL psi2_only);

LOCAL void psi_copy_si13_params(T_D_SYS_INFO_13* si13);
LOCAL void psi_copy_psi13_params(T_PSI_13* psi13);
LOCAL BOOL psi_check_change_field (UBYTE psi_change_field);
LOCAL UBYTE psi_compare_change_mark(UBYTE received_change_mark, UBYTE stored_change_mark);

LOCAL BOOL psi_is_pbcch_des_different(T_PSI_13* psi13);

/*
 * Private functions for handling of PSI3 and PSI3BIS messages. 
 * Reading of those messages in not ordered sequence.
 */
/*
 * Storing
 */
LOCAL UBYTE psi_store_ncell_param  ( T_ncell_par      *p_ncell_par, 
                                     UBYTE             c_ncell_par,
                                     UBYTE             v_ncell_par,
                                     T_INFO_TYPE       type,
                                     UBYTE             instance       );

LOCAL void psi_store_ncell_param2  ( T_PSI_3_BIS      *psi3bis,
                                     UBYTE             number         );
LOCAL BOOL psi_store_cs_param2     ( T_NC_LIST        *nc_list,
                                     T_ncell_par2_set *cs_par2,
                                     UBYTE             instance,
                                     UBYTE            *number,
                                     USHORT           *freq,
                                     USHORT            freq_diff,
                                     UBYTE             same_ra_scell,
                                     UBYTE             cell_ba,
                                     UBYTE             bcc            );

/*
 * Restoring 
 */
LOCAL void psi_restore_ncell_param ( void                             );

#ifdef REL99
LOCAL void psi_update_bss_sgsn_rel ( T_D_SYS_INFO_13  *si13, 
                                     BOOL              pbcch_status   );
#endif

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

/*
+------------------------------------------------------------------------------
| Function    : psi_compare_change_mark()
+------------------------------------------------------------------------------
| Description : The function psi_compare_change_mark() .... compares the change_mark values
|               and indicates the incrementatiton value
|
| Parameters  : UBYTE received_change_mark, UBYTE stored_change_mark
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE psi_compare_change_mark(UBYTE received_change_mark, UBYTE stored_change_mark)
{
  UBYTE incremented_value = 0;

  if(received_change_mark NEQ stored_change_mark)
  {
    UBYTE dummy = (stored_change_mark + 1)%8;
    if(dummy EQ received_change_mark)
      incremented_value = 1;
    else
      incremented_value = 2;
  }
  return incremented_value;
}/* psi_compare_change_mark*/
/*
+------------------------------------------------------------------------------
| Function    : psi_stop_psi_reading()
+------------------------------------------------------------------------------
| Description : The function psi_stop_psi_reading() .... stops to read PSI messages
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_stop_psi_reading( ACQ_TYPE acq_type_in_idle)
{
  TRACE_FUNCTION( "psi_stop_psi_reading" );
  psc_db->acq_type = acq_type_in_idle;
  if(grr_is_pbcch_present())
  {
    PALLOC(mphp_scell_pbcch_req, MPHP_SCELL_PBCCH_STOP_REQ);
    PSEND(hCommL1,mphp_scell_pbcch_req);
  }
}/* psi_stop_psi_reading*/

/*
+------------------------------------------------------------------------------
| Function    : psi_check_acq_state
+------------------------------------------------------------------------------
| Description : The function psi_check_acq_state() .... checks the state of the acquisition
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL T_ACQ_STATE_RET psi_check_acq_state ( void )
{
  UBYTE n;
  T_ACQ_STATE_RET return_val = ACQ_RUNNING;

  TRACE_FUNCTION( "psi_check_acq_state" );

  switch(psc_db->acq_type)
  {
    case PARTIAL:
      return_val = ACQ_PART_OK;
      for(n = 0; n <MAX_PSI; n++)
      {
        if(psc_db->state_of_PSI[n].state EQ NEEDED)
        {
          /* 
           * partial acquisition not completed 
           */
          return_val = ACQ_RUNNING;
        }
      }
      if(return_val EQ ACQ_PART_OK)
      {
        psi_stop_10sec(); /* partial acquisition completed */
        psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/
        psc_db->psi1_params.first_psi1 = FALSE;
#ifdef REL99
        /* Partial acquisition is complete. Send CBCH info
         * to RR if needed. 
         */
        if(psc_db->send_cbch_info_ind)
        {
           sig_psi_ctrl_cbch_info_ind();
           psc_db->send_cbch_info_ind = FALSE;
        }
#endif
      }
      break;
    case COMPLETE:
      return_val = ACQ_COMP_OK;
      /*
       * Check whether reading process completed or not
       */
      for(n = 0; n <MAX_PSI; n++)
      {
        if(psc_db->state_of_PSI[n].state EQ NEEDED)
        {
          /* 
           * acquisition of some PSI not completed 
           */
          {
            if(n EQ 3)
            {
              TRACE_EVENT("acq. incomplete PSI3bis missing!");
            }
#if defined (REL99) AND defined (TI_PS_FF_EMR)
            else if(n EQ 4)
            {
              TRACE_EVENT("acq. incomplete PSI3ter  missing!");                
            }
            else if(n EQ 7)
            {
              TRACE_EVENT("acq. incomplete PSI8  missing!");                
            }
            else
            {
              TRACE_EVENT_P1("acq. incomplete PSI%d missing!", ((n>3)?n-1:n+1));               
            }
#else
            else
            {
              TRACE_EVENT_P1("acq. incomplete PSI%d missing!", ((n>3)?n:n+1));               
            }
#endif
          }
          return_val = ACQ_RUNNING;
          break; /* break for loop*/
        }
      }
      if(return_val EQ ACQ_COMP_OK) 
      {
        /*
         * Start timer for 10 sec. if running
         */
        TRACE_EVENT("Acq. complete");
        vsi_t_stop(GRR_handle, T_COMP_PSI);
        psi_stop_10sec(); /* acquisition of all PSI  completed */
        psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/
        psc_db->psi1_params.first_psi1 = FALSE;
      }
      break;
    case PERIODICAL_PSI1_READING:
      psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/
      return_val = ACQ_PERIOD_OK;
      break;
    case FULL_PSI_IN_NEW_CELL:
      return_val = ACQ_NPSI_OK;
      psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/
      /*
       * E.g. read all PSI in the reselected cell
       * Check whether reading process completed or not
       */
      for(n = 0; n <MAX_PSI; n++)
      {
        if(psc_db->state_of_PSI[n].state EQ NEEDED)
        {
          /* 
           * acquisition of some PSI not completed 
           */
          return_val = ACQ_RUNNING;
          psc_db->acq_type = FULL_PSI_IN_NEW_CELL;
          break; /* break for loop*/
        }
      }
      if(n>MAX_PSI)
        psc_db->psi1_params.first_psi1 = FALSE;
      break;
    case NONE:
      /* nothing to do: we may received a PSI message without sending a request
       *                e.g. on PCCCH (PPCH: paging channel or paging group)
       */
      break;
    default:
      break;
  }
  return return_val;
} /* psi_check_acq_state() */


/*
+------------------------------------------------------------------------------
| Function    : psi_reset_complete_acq
+------------------------------------------------------------------------------
| Description : The function psi_reset_complete_acq() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_reset_complete_acq ( void )
{
  TRACE_FUNCTION( "psi_reset_complete_acq" );
  psc_db->acq_type = COMPLETE;
  
  psc_db->complete_acq.needed = TRUE;
  psc_db->complete_acq.psi1_ok = FALSE;
  psc_db->complete_acq.psi2_ok = FALSE;
  psc_db->complete_acq.made_at_least_one_attempt = FALSE;
}/* psi_reset_complete_acq*/

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi1
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi1() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi1 ( void )
{
  TRACE_FUNCTION( "psi_reset_psi1" );

  psc_db->psi1_params.pbcch_change_mark = NOT_SET;
  psc_db->psi1_params.psi_change_field = NOT_SET;
  psc_db->psi1_params.psi_cnt_lr = 0;
  psc_db->psi1_params.psi_cnt_hr = 0;
  psc_db->psi1_params.psi1_repeat_period = NOT_SET;
  psc_db->psi1_params.first_psi1 = TRUE;
}/* psi_reset_psi1*/

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi2
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi2() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_reset_psi2 ( void )
{
  UBYTE n;
  TRACE_FUNCTION( "psi_reset_psi2" );
  /* reset psi2 parameters*/
  psc_db->psi2_params.psi2_change_mark = NOT_SET; /*not set*/
  psc_db->psi2_params.psi2_count = NOT_SET; /*not set*/

  for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI2 + 1; n++)
    psc_db->psi2_params.instances[n] = FALSE;

#ifdef REL99
  psc_db->v_add_psi = FALSE;
#endif
  psi_init_rfl_psi2();
  psi_init_cell_alloc();
  psi_init_gprs_ms_alloc(TRUE);

} /* psi_reset_psi2 */

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi3
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi3() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi3 ( void )
{
  TRACE_FUNCTION( "psi_reset_psi3" );
  /* reset psi3 parameters*/
  psc_db->psi3_params.psi3_change_mark = NOT_SET;
  psc_db->psi3_params.psi3_bis_count = NOT_SET;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
  grr_init_nc_list( &psc_db->nc_cw.list );
#endif
} /* psi_reset_psi3 */

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi3bis
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi3bis() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi3bis ( void )
{
  UBYTE n;
  TRACE_FUNCTION( "psi_reset_psi3bis" );

  psc_db->psi3bis_params.psi3bis_change_mark = NOT_SET;
  psc_db->psi3bis_params.psi3bis_index = 0;

  for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI3BIS + 1; n++)
  psc_db->psi3bis_params.instances[n] = FALSE;

  grr_init_nc_list( &psc_db->nc_cw.list );
} /* psi_reset_psi3bis */

#if defined (REL99) AND defined (TI_PS_FF_EMR)
/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi3ter
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi3ter() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi3ter ( void )
{
  UBYTE n;
  TRACE_FUNCTION( "psi_reset_psi3ter" );

  psc_db->psi3ter_params.psi3ter_change_mark = NOT_SET;
  psc_db->psi3ter_params.prev_psi3ter_index = 0;
  psc_db->psi3ter_params.psi3ter_index = 0;

  for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI3TER + 1; n++)
  psc_db->psi3ter_params.instances[n] = FALSE;
  
  psc_db->enh_cw.gprs_rept_prio_desc.num_cells = 0;
#ifdef TI_PS_FF_RTD
  /* Rtd values has to be reset to not available */
  for( n = 0; n < MAX_NR_OF_NCELL; n++ )
    psc_db->rtd[n] = RTD_NOT_AVAILABLE;
#endif /* #ifdef TI_PS_FF_RTD */


} /* psi_reset_psi3ter */
#endif


/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi4
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi4() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi4 ( void )
{
  UBYTE n;
  TRACE_FUNCTION( "psi_reset_psi4" );
  /* reset psi_reset_psi4 parameters*/
  psc_db->psi4_params.psi4_index = 0;
  psc_db->psi4_params.psi4_change_mark = NOT_SET;

  for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI4 + 1; n++)
  psc_db->psi4_params.instances[n] = FALSE;


} /* psi_reset_psi4 */


/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi5
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi5() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi5 ( void )
{
  UBYTE i;

  TRACE_FUNCTION( "psi_reset_psi5" );
  /* reset psi_reset_psi5 parameters*/
  psc_db->psi5_params.psi5_index = 0;
  psc_db->psi5_params.psi5_change_mark = NOT_SET;
  
  for( i = 0; i < MAX_NR_OF_INSTANCES_OF_PSI5; i++ )
  {
    psc_db->psi5_params.idx[i].start = RRGRR_INVALID_IDX;
    psc_db->psi5_params.idx[i].stop  = RRGRR_INVALID_IDX;
    psc_db->psi5_params.instances[i] = FALSE;
  }
  /*
   * used for checking the consistency of PSI5. instances[0]: number of instances
   */
  psc_db->psi5_params.instances[MAX_NR_OF_INSTANCES_OF_PSI5] = FALSE;

  grr_init_nc_param( &psc_db->nc_cw.param, TRUE );
  grr_init_xmeas_struct( &psc_db->ext_psi5 );
#if defined (REL99) AND defined (TI_PS_FF_EMR)
  grr_init_enh_param(&psc_db->enh_cw, FALSE);
  grr_init_enh_param(&grr_data->psi.enh_param, FALSE);
#endif
} /* psi_reset_psi5 */

#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi8
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi8() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi8 ( void )
{
  UBYTE n;
  TRACE_FUNCTION( "psi_reset_psi8" );
  /* reset psi_reset_psi8 parameters*/
  psc_db->psi8_params.psi8_index = 0;
  psc_db->psi8_params.psi8_change_mark = NOT_SET;

  for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI8 + 1; n++)
   psc_db->psi8_params.instances[n] = FALSE;
  
  psc_db->send_cbch_info_ind = FALSE;
  psc_db->v_cbch_chan_desc = FALSE;
} /* psi_reset_psi8 */
#endif

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi13
+------------------------------------------------------------------------------
| Description : The function psi_reset_psi13() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_reset_psi13 ( void )
{
  TRACE_FUNCTION( "psi_reset_psi13" );

  grr_init_nc_param( &psc_db->nc_cw.param, TRUE );

} /* psi_reset_psi13 */

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_all
+------------------------------------------------------------------------------
| Description : The function psi_reset_all() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reset_all ( void )
{
  TRACE_FUNCTION( "psi_reset_all" );


  /* reset complete acq.*/
  psi_reset_complete_acq();

  /* reset PSI1 parameters */
  psi_reset_psi1();

  /* reset psi2 parameters*/
  psi_reset_psi2();

  /* reset psi3 parameters*/
  psi_reset_psi3();

  /* reset psi3bis parameters*/
  psi_reset_psi3bis();

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  /* reset psi3ter parameters*/
  psi_reset_psi3ter();
#endif

  /* reset psi4 parameters*/
  psi_reset_psi4();

  /* reset psi5 parameters*/
  psi_reset_psi5();

#ifdef REL99
  /* reset psi8 parameters*/
  psi_reset_psi8();
#endif

  /* reset psi13 parameters*/
  psi_reset_psi13();

  /* */
  psc_db->send_psi_status = FALSE;


  /* init the states of the PSI parameters*/
  psi_init_states_of_psi();

  psi_reset_si_entries();

} /* psi_reset_all() */



/*
+------------------------------------------------------------------------------
| Function    : psi_stop_10sec
+------------------------------------------------------------------------------
| Description : The function psi_stop_10sec() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_stop_10sec ( void )
{
  TRACE_FUNCTION( "psi_stop_10sec" );

  vsi_t_stop(GRR_handle,T_10_SEC);
} /* psi_stop_10sec() */



/*
+------------------------------------------------------------------------------
| Function    : psi_start_10sec
+------------------------------------------------------------------------------
| Description : The function psi_start_10sec() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_start_10sec ( void )
{
  TRACE_FUNCTION( "psi_start_10sec" );
  
  if(grr_data->psi.is_start_of_10_sec_allowed)
    vsi_t_start(GRR_handle,T_10_SEC, T_10_SEC_VALUE);
} /* psi_start_10sec() */



/*
+------------------------------------------------------------------------------
| Function    : psi_partial_acq
+------------------------------------------------------------------------------
| Description : The function psi_partial_acq() performs partial acquisition
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_partial_acq ( void )
{
  UBYTE psi_reading_type;
  UBYTE dummy=0;

  TRACE_FUNCTION( "psi_partial_acq" );
  
  psi_reading_type = PSI_IN_HR_AND_LR;

  psc_db->acq_type = PARTIAL;

  if(  psc_db->state_of_PSI[PSI2].state EQ NEEDED)
  {
    psi_reading_type = READ_PSI2;
    psi_reset_psi2();
    dummy++;
    TRACE_EVENT("PSI 2 needed");
  }
  
  if(  psc_db->state_of_PSI[PSI3].state EQ NEEDED)
  {
    psi_reading_type = READ_PSI3_3BIS;
    psi_reset_psi3();
    psi_reset_psi3bis();

#if defined (REL99) AND defined (TI_PS_FF_EMR)
    psi_reset_psi3ter();
#endif

    dummy++;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    TRACE_EVENT("PSI3/3bis/3ter  needed");
#else
    TRACE_EVENT("PSI3/3bis needed");
#endif
  }

  if(  psc_db->state_of_PSI[PSI4].state EQ NEEDED)
  {
    psi_reading_type = READ_PSI4;
    psi_reset_psi4();
    dummy++;
    TRACE_EVENT("PSI 4 needed");
  }

  if(  psc_db->state_of_PSI[PSI5].state EQ NEEDED)
  {
    psi_reading_type = READ_PSI5;
    psi_reset_psi5();
    dummy++;
    TRACE_EVENT("PSI 5 needed");
  }

#ifdef REL99
  if(  psc_db->state_of_PSI[PSI8].state EQ NEEDED)
  {
    psi_reading_type = READ_PSI8;
    psi_reset_psi8();
    dummy++;
    TRACE_EVENT("PSI 8 needed");
  }
#endif

  if(dummy > 1)
    psi_reading_type = PSI_IN_HR_AND_LR;

  psi_receive_psi(psi_reading_type);
} /* psi_partial_acq() */


/*
+------------------------------------------------------------------------------
| Function    : psi_init_states_of_psi
+------------------------------------------------------------------------------
| Description : The function psi_init_states_of_psi() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL  void psi_init_states_of_psi ( void )
{
  psc_db->state_of_PSI[PSI1].state     = NEEDED;
  psc_db->state_of_PSI[PSI2].state     = NEEDED;
  psc_db->state_of_PSI[PSI3].state     = NEEDED;
  psc_db->state_of_PSI[PSI3bis].state  = NEEDED;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
  psc_db->state_of_PSI[PSI3ter].state  = NEEDED;
#endif
  psc_db->state_of_PSI[PSI4].state     = NEEDED;
  psc_db->state_of_PSI[PSI5].state     = NEEDED;
#ifdef REL99
  psc_db->state_of_PSI[PSI8].state     = NEEDED;
#endif
  psc_db->state_of_PSI[PSI13].state    = NEEDED;

}/* psi_init_states_of_psi() */

/*
+------------------------------------------------------------------------------
| Function    : psi_init_rfl_psi2
+------------------------------------------------------------------------------
| Description : The function psi_init_rfl_psi2() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_init_rfl_psi2(void)
{
  UBYTE n;

  /*
   * please note that only the RFL_NUMBERs defined 
   * in the PSI2 will be marked as invalid
   */
  for (n = 0; n < MAX_RFL; n++)
  {
    psc_db->rfl[n].num = NOT_SET;
  }
}/* psi_init_rfl_psi2() */
/*
+------------------------------------------------------------------------------
| Function    : psi_init_cell_alloc
+------------------------------------------------------------------------------
| Description : The function psi_init_cell_alloc() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_init_cell_alloc(void)
{
  UBYTE n;
  /*TRACE_EVENT("psi_init_cell_alloc");*/
  psc_db->v_cell_alloc = FALSE;
  for (n = 0; n < MAX_CELL_ALLOC; n++)
    psc_db->cell_alloc[n].rfl_num = NOT_SET;
}/* psi_init_cell_alloc() */

/*
+------------------------------------------------------------------------------
| Function    : psi_init_gprs_ms_alloc
+------------------------------------------------------------------------------
| Description : The function psi_init_gprs_ms_alloc() ....
|
| Parameters  : BOOL psi2_only
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_init_gprs_ms_alloc(BOOL psi2_only)
{
  UBYTE n;
  if(psi2_only)
  {
    TRACE_EVENT("remove only PSI2 entries in GPRS_MA");
  }
  else
  {
    TRACE_EVENT("remove all entries in GPRS_MA");
  }

  for (n = 0; n < MAX_GPRS_MS_ALLOC; n++)
  {
    if(psi2_only)
    {
      if(
          (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num NEQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC ) 
            AND  /* ignore MA_NUMBER with 14 or 15: 0..13 in PSI2*/
          (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num NEQ MA_NUMBER_4_ASSIGNMENT )
        )
      {
        psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = NOT_SET;
      }
    }
    else
    {
      psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = NOT_SET;
    }
  }

  /*
   * When deleting the MA defined in the assignment message,
   * the corresponding RFL list should be deleted, too.
   */
  psc_db->gprs_ms_alloc_in_assignment.ma_num = NOT_SET;
  psc_db->rfl[MAX_RFL].num                   = NOT_SET;
}/* psi_init_gprs_ms_alloc() */

 /*
+------------------------------------------------------------------------------
| Function    : psi_init
+------------------------------------------------------------------------------
| Description : The function psi_init() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_init ( void )
{
  TRACE_FUNCTION( "psi_init" );

  psi_init_params();
  psi_reset_psi_pos( );

  INIT_STATE(PSI, PSI_NULL);

} /* psi_init() */



/*
+------------------------------------------------------------------------------
| Function    : psi_complete_acq
+------------------------------------------------------------------------------
| Description : The function psi_complete_acq() ....
|
| Parameters  : UBYTE acq_type: COMPLETE (in serving cell) or FULL_PSI_IN_NEW_CELL
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_complete_acq ( ACQ_TYPE acq_type )
{
  TRACE_FUNCTION( "psi_complete_acq" );
  /*
   * Start timer for 10 sec.
   */
  vsi_t_start(GRR_handle,T_COMP_PSI, T_10_SEC_VALUE);
  
  psi_receive_psi(READ_COMPLETE);

  psi_reset_all();

  psc_db->acq_type = acq_type;
  
  psc_db->state_of_PSI[PSI13].state = RECEIPT_OK; /* we do not need to read PSI13 again*/

} /* psi_complete_acq() */



/*
+------------------------------------------------------------------------------
| Function    : psi_send_psi_status
+------------------------------------------------------------------------------
| Description : The function psi_send_psi_status() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_send_psi_status (void )
{
  TRACE_FUNCTION( "psi_send_psi_status" );

  /* SZML-PSI/003 */

} /* psi_send_psi_status() */



/*
+------------------------------------------------------------------------------
| Function    : psi_stop_30sec
+------------------------------------------------------------------------------
| Description : The function psi_stop_30sec() ....
|
| Parameters  : BOOL start_again: whether the timer should be started again or not
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_stop_30sec (BOOL start_again )
{
  TRACE_FUNCTION( "psi_stop_30sec" );

  vsi_t_stop(GRR_handle,T_30_SEC);
  if(start_again)
  {
    /*
    TRACE_EVENT("30 sec. running");
    */
    vsi_t_start(GRR_handle,T_30_SEC, T_30_SEC_VALUE);
  }
  else
  {
    TRACE_EVENT("30 sec. stopped");
  }
} /* psi_stop_30sec() */



/*
+------------------------------------------------------------------------------
| Function    : psi_start_30sec
+------------------------------------------------------------------------------
| Description : The function psi_start_30sec() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_start_30sec (void )
{
  TRACE_FUNCTION( "psi_start_30sec" );
  /*
  TRACE_EVENT("30 sec. running");
  */
  vsi_t_start(GRR_handle,T_30_SEC, T_30_SEC_VALUE);
} /* psi_start_30sec() */



/*
+------------------------------------------------------------------------------
| Function    : psi_start_60sec
+------------------------------------------------------------------------------
| Description : The function psi_start_60sec() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_start_60sec ( void )
{
  TRACE_FUNCTION( "psi_start_60sec" );
  /*
  TRACE_EVENT("60 sec. running");
  */
  vsi_t_start(GRR_handle,T_60_SEC, T_60_SEC_VALUE);
} /* psi_start_60sec() */


/*
+------------------------------------------------------------------------------
| Function    : psi_stop_60sec
+------------------------------------------------------------------------------
| Description : The function psi_stop_60sec () ....
|
| Parameters  : BOOL start_again
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_stop_60sec ( BOOL start_again )
{
  TRACE_FUNCTION( "psi_stop_60sec " );

  vsi_t_stop(GRR_handle,T_60_SEC);
  if(start_again)
  {
    /*
    TRACE_EVENT("60 sec. running");
    */
    vsi_t_start(GRR_handle,T_60_SEC, T_60_SEC_VALUE);
  }
  else
  {
    TRACE_EVENT("60 sec. stopped");
  }

} /* psi_stop_60sec () */

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_ma_from_psi13
+------------------------------------------------------------------------------
| Description : The function psi_copy_ma_from_psi13() ....
|
| Parameters  : T_gprs_ms_alloc* ms_alloc: pointer to T_gprs_ms_alloc
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_copy_ma_from_psi13(T_gprs_ms_alloc_ie* ms_alloc)
{
  UBYTE n;
  MCAST(si13,D_SYS_INFO_13); /* T_D_SYS_INFO_13  */
  
  TRACE_FUNCTION( "psi_copy_ma_from_psi13 " );

  if(D_SYS_INFO_13 NEQ si13->msg_type)
  {  /* PSI13 was received */
    for(n = 0; n < MAX_GPRS_MS_ALLOC; n++)
    {
      if( (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC) ||
          (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ NOT_SET) )
      {
        psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = MA_NUMBER_4_PSI13_OR_CELL_ALLOC;
        memcpy(&(psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie),
                ms_alloc, sizeof(T_gprs_ms_alloc_ie));
        n = MAX_GPRS_MS_ALLOC; /* break for loop*/
      }
    }
  }
  else
  {  /* SI13 was received */
    UBYTE i;
    T_gprs_ma *gprs_ma = (T_gprs_ma*)ms_alloc;
    for(n = 0; n < MAX_GPRS_MS_ALLOC; n++)
    {
      if( (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC) ||
          (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ NOT_SET) )
      {
        memset(&(psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie), 0, 
                                                  sizeof(T_gprs_ms_alloc_ie));
        psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = 
                                              MA_NUMBER_4_PSI13_OR_CELL_ALLOC;
        psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.hsn = 
                                                                 gprs_ma->hsn;
        if(gprs_ma->v_rfln)
        {
          psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.v_rfl_num_list
                                                                       = TRUE;
          psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.c_rfl_num_list
                                                            = gprs_ma->c_rfln;
          for(i = 0;i < gprs_ma->c_rfln;i++)
          {
            psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.rfl_num_list[i].rfl_num
                                                           = gprs_ma->rfln[i];
          }
        }
        psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.flag = 
                                                                 gprs_ma->hop;
        if(gprs_ma->hop)
        {
          if(gprs_ma->v_arfcn_idx)
          {
            psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.v_arfcn_index_list
                                                                       = TRUE;
            psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.c_arfcn_index_list
                                                       = gprs_ma->c_arfcn_idx;
            for(i = 0;i < gprs_ma->c_arfcn_idx;i++)
            {
              psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.arfcn_index_list[i].arfcn_index
                                                      = gprs_ma->arfcn_idx[i];
            }
          }
        }
        else
        {
          psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.v_ma_struct
                                                                       = TRUE;
          psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.ma_struct.ma_len
                                                         = gprs_ma->allo_len6;
          psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.ma_struct.c_ma_map
                                                       = gprs_ma->c_allo_bmp6;
          for(i = 0;i < gprs_ma->c_allo_bmp6;i++)
          {
            psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.ma_struct.ma_map[i]
                                                      = gprs_ma->allo_bmp6[i];
          }
        }
        break;
      }
    }
  }
}/*psi_copy_ma_from_psi13*/

/*
+------------------------------------------------------------------------------
| Function    : psi_process_si13()
+------------------------------------------------------------------------------
| Description : The function psi_process_si13()....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL T_SI13_RET psi_process_si13( T_D_SYS_INFO_13 *si13)
{
  BOOL pbcch_was_present;
  T_SI13_RET ret_value = SI13_OK;
#ifdef REL99 
  UBYTE current_nw_rel = psc_db->network_rel;
#endif

  TRACE_FUNCTION( "psi_process_si13" );

  if(!si13->si13_rest_oct.v_si13_info)
  {
    TRACE_ERROR( "No restoctects present in SI13: reread si13" );
    ret_value = SI13_REREAD;
  }
  else
  {

#ifdef REL99
    /* Update the BSS release when the 1st SI13 message is received in case of 
     * PBCCH's PRESENCE. 
     * The correct BSS release will be updated after receiving PSIs
     */
    if(si13->si13_rest_oct.si13_info.flag1)
    {
      /* PBCCH is present in the cell */
      /* This is the 1st SI13 message */
      if(psc_db->psi13_params.bcch_change_mark EQ NOT_SET)
      {
        /* Update the BSS and the SGSN releases */
        psi_update_bss_sgsn_rel(si13, PBCCH_PRESENT);
      }
    }
    else
    {
      /* Update the BSS and SGSN releases every time the SI13 message is received 
       * in case of PBCCH's ABSENCE.
       */
      psi_update_bss_sgsn_rel(si13, PBCCH_NOT_PRESENT);

      if(psc_db->network_rel NEQ current_nw_rel)
      {
        TRACE_EVENT_P2("((SI13)BSS Network release changed from %d to %d <0 - REL_97, 1 - REL_99, 2 - REL_04>", 
          current_nw_rel, psc_db->network_rel);
      }
    }
#endif

    pbcch_was_present = grr_is_pbcch_present();
    /*
     * Copy PBCCH or non PBCCH desc. and change field
     */
    if( !pbcch_was_present AND si13->si13_rest_oct.si13_info.v_pbcch_des )
    {
      /* No PBCCH description was present in the GPRS_DATA_BASE or PBCCH was released:
       * SI13 message contains PBCCH description, so we have to start a complete acq of
       * PSI messages.
       */
      if(psc_db->psi13_params.bcch_change_mark EQ NOT_SET)
      {
        psi_copy_si13_params(si13);
      }

      psc_db->psi13_params.bcch_change_mark = si13->si13_rest_oct.si13_info.bcch_cm;
      ret_value = SI13_COMPLETE_PSI;
    }
    else
    {
      psi_copy_si13_params(si13);

      /* 
       * There is no PBCCH description present in the SI13 message and there can be
       * no PBCCH description in the GPRS_DATA_BASE
       */  
      if(psc_db->psi13_params.bcch_change_mark NEQ NOT_SET)
      {
        /*
         * This is not the first SI13 message.
         * Check BCCH_CHANGE_MARK
         */
        {
          UBYTE incremented_value =

            psi_compare_change_mark
            (
            si13->si13_rest_oct.si13_info.bcch_cm,
            psc_db->psi13_params.bcch_change_mark
            );

          if(incremented_value EQ 1)      /*partial acq*/
          {
            if(psi_is_update_needed(si13->si13_rest_oct.si13_info.si_cf))
            {
              ret_value = SI13_PARTIAL_SI;
            }
          }
          else if(incremented_value > 1) /* incremented_value > 1: complete acq*/
          {
            ret_value = SI13_COMPLETE_SI;
          }
        }
      }
      psc_db->psi13_params.bcch_change_mark = si13->si13_rest_oct.si13_info.bcch_cm;
    }
  }
  psc_db->state_of_PSI[PSI13].state = RECEIPT_OK;
  grr_set_pg_nmo();
  TRACE_EVENT_P1("SI13 processed: %d", ret_value);
  return ret_value;
} /* psi_process_si13() */

/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi13
+------------------------------------------------------------------------------
| Description : The function psi_process_psi13() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI13_RET psi_process_psi13 ( T_PSI_13 * psi13 )
{
  T_PSI13_RET ret_val = PSI13_OK;

  TRACE_FUNCTION( "psi_process_psi13" );
  
  if(grr_is_pbcch_present())
  {
    /*
     * PBCCH description already exists: we have to compare PBCCH parameters
     */
    if(psi_is_pbcch_des_different(psi13))
    {
      /* 
       * PBCCH no longer available
       * or PBCCH description is differnt from the saved one in the MS
       */
      if(psi13->flag)
      {
        ret_val =  PSI13_COMPLETE_PSI;
      }
      else
      {
        ret_val =  PSI13_PBCCH_RELEASED;
      }
    }
    else
    {
      /* 
       * PBCCH description is the same
       * Copy at least SI13_CHANGE_MARK and GPRS Mobile Allocation
       */
      psi_copy_psi13_params(psi13);
#ifdef REL99
      /* PSI13 message has been received when PBCCH is present.
       * CBCH information may have to be updated if hopping is 
       * allowed.
       */
      if(psc_db->v_cbch_chan_desc AND !psc_db->cbch_chan_desc.freq_par.v_arfcn)
      {
        sig_psi_ctrl_cbch_info_ind();       
      }
#endif
      /*
       * Check BCCH_CHANGE_MARK
       */
      {
        UBYTE incremented_value = psi_compare_change_mark(psi13->bcch_change_ma, psc_db->psi13_params.bcch_change_mark);
        psc_db->psi13_params.bcch_change_mark = psi13->bcch_change_ma;

        if(incremented_value EQ 1)      /*partial acq*/
        {
          if(psi_is_update_needed(psi13->si_change_ma))
          {
            ret_val = PSI13_PARTIAL_SI;
          }
        }
        else if(incremented_value > 1) /* incremented_value > 1: complete acq*/
        {
          ret_val = PSI13_COMPLETE_SI;
        }
      }
    }
  }
  else
  {
    /*
     * No PBCCH description present in the GPRS_DATA_BASE:
     * and we received a PSI13 in BCCH_TRANSFER state
     * So we have to check whether this message contains a
     * PBCCH description or not. If YES, complete acq. of PSI
     * messages should be started. If NO, BCCH_CHANGE_MARK should be compared
     */
    if(psi13->flag)
    {
      ret_val = PSI13_PBCCH_ESTABLISHED;    
    }
    else
    {
      /*
       * Copy PBCCH or non PBCCH desc. and change field
       */
      psi_copy_psi13_params(psi13);

      {
        UBYTE incremented_value = psi_compare_change_mark(psi13->bcch_change_ma, psc_db->psi13_params.bcch_change_mark);
        psc_db->psi13_params.bcch_change_mark = psi13->bcch_change_ma;

        if(incremented_value EQ 1)      /*partial acq*/
        {
          if(psi_is_update_needed(psi13->si_change_ma))
          {
            ret_val = PSI13_PARTIAL_SI;
          }
        }
        else if(incremented_value > 1) /* incremented_value > 1: complete acq*/
        {
          ret_val = PSI13_COMPLETE_SI;
        }
      }
    }
  }

#ifdef REL99
    /* Update the SGSN release */
  if (psi13->v_release_99_str_psi_13)
  {
    psc_db->sgsn_rel = psi13->release_99_str_psi_13.sgsnr ? PS_SGSN_99_ONWARDS : PS_SGSN_98_OLDER;

   /* Update the SGSN release in the Common library context */
    cl_nwrl_set_sgsn_release(psc_db->sgsn_rel);
  }
#endif

  psc_db->state_of_PSI[PSI13].state = RECEIPT_OK;

  grr_set_pg_nmo();
  return ret_val;
} /* psi_process_psi13() */

/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi5
+------------------------------------------------------------------------------
| Description : The function psi_process_psi5() ....
|
| Parameters  : T_PSI_5 *psi5
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI5_RET psi_process_psi5 (T_PSI_5 *psi5 )
{
  BOOL  is_psi5_ok;
  UBYTE n;
  BOOL  cpy_prm_set;

  TRACE_FUNCTION( "psi_process_psi5" );

  /*
   * Check consistency
   */
  if(psc_db->psi5_params.psi5_change_mark EQ NOT_SET)
  {
    /*
     * Copy change mark etc.
     */
    psc_db->psi5_params.psi5_change_mark = psi5->psi5_cm;
    psc_db->psi5_params.psi5_count   = psi5->psi5_cnt;
    psc_db->psi5_params.instances[0] = psi5->psi5_cnt;/* number of instances */
  }
  else
  {
    /*
     * There is a valid change mark present in the database
     * Check consistency of COUNT and INDEX
     */
    if(
       (psc_db->psi5_params.psi5_count NEQ psi5->psi5_cnt)
       OR
       (psc_db->psi5_params.psi5_count < psi5->psi5_ind)
       OR
       (psc_db->psi5_params.psi5_change_mark NEQ psi5->psi5_cm)
       )
    {
      /*
       * Error situation read a new PSI5
       * The PSI5 change mark field is changed each time information has been updated
       * A new value indicates that the mobile
       * station shall re-read the information from the PSI5
       */

      TRACE_ERROR( "PSI5: inconsistent parameter" );
      psc_db->is_ext_psi5_valid = FALSE;
      return PSI5_REREAD;
    }

    /* psi5_change_markhas not changed, i.e.
     * PSI5 message has not changed, we already have a consistent set, so we
     * do not have to read the PSI5 message
     */
    if((psc_db->psi5_params.psi5_change_mark EQ psi5->psi5_cm) &&
          (psc_db->state_of_PSI[PSI5].state EQ RECEIPT_OK))
    {
      /* Message has not changed, we already have a consistent set, so we
       * do not have to read it
       */
      TRACE_EVENT( "PSI5: message has not changed" );
      return PSI5_OK;
    }
  }

  psc_db->psi5_params.psi5_index = psi5->psi5_ind;


  if( psc_db->psi5_params.instances[psi5->psi5_ind + 1] EQ FALSE )
  {
    if( grr_data->nc2_on )
    {
      if( 
          psi5->v_nc_meas_par AND 
          (
            psc_db->nc_cw.param.idx EQ NOT_SET        OR
            psc_db->nc_cw.param.idx <  psi5->psi5_ind          
          )
        )
      {
        /*
         * This is the first time that we want to save network controlled 
         * measurement parameters or the last index for NC parameters were
         * not bigger than the currently received one.
         *
         * Maybe more than one instance of PSI5, store data in temporary location.
         */
        grr_data->psi.v_nc_param = TRUE;

        grr_prcs_nc_param_struct 
               ( &grr_data->psi.nc_param, &psi5->nc_meas_par, psi5->psi5_ind );
      }

      if( psi5->v_xmeas_par )
      {
        cpy_prm_set = ( psc_db->ext_psi5.idx EQ NOT_SET        OR
                        psc_db->ext_psi5.idx <  psi5->psi5_ind    );

        grr_prcs_xmeas_struct ( &psc_db->ext_psi5,
                                &psi5->xmeas_par,
                                cpy_prm_set, 
                                psi5->psi5_ind,
                                &psc_db->psi5_params.idx[psi5->psi5_ind].start,
                                &psc_db->psi5_params.idx[psi5->psi5_ind].stop );
      }

#if defined (REL99) AND defined (TI_PS_FF_EMR)
      if(psi5->v_release_99_str_psi_5 AND psi5->release_99_str_psi_5.v_enh_rep_param_struct)
      {
        psc_db->psi5_params.v_enh_rep_param_struct = TRUE;
        grr_prcs_enh_param_cw_temp 
        ( &grr_data->psi.enh_param, &psi5->release_99_str_psi_5.enh_rep_param_struct, 
        psi5->psi5_ind );
      } 
#endif
    }
    /*
     * check whether PSI5 has been received completely or not
     */
    psc_db->psi5_params.instances[psi5->psi5_ind + 1] = TRUE;
    is_psi5_ok = TRUE;
    for(n = 0; n <= psc_db->psi5_params.instances[0]; n++ )
    {
      if(!(psc_db->psi5_params.instances[n + 1]))
      {
        is_psi5_ok = FALSE;/* consistent set of PSI5 not complete */
        break;
      }
    }

    TRACE_EVENT_P2( "PSI5: received with count = %d, index = %d ", 
                                    psi5->psi5_cnt, psi5->psi5_ind);

    if(is_psi5_ok)
    {
      psc_db->state_of_PSI[PSI5].state = RECEIPT_OK;

      /*
       * the NC parameter are stored temporarily and
       * now transferred to final location
       */
      if( grr_data->nc2_on )
      {
        grr_prcs_nc_param_final ( &psc_db->nc_cw.param,
                                  &grr_data->psi.v_nc_param,
                                  &grr_data->psi.nc_param );

        grr_sort_ext_lst_freq ( &psc_db->ext_psi5.em1.list,
                                MAX_NR_OF_INSTANCES_OF_PSI5,
                                &psc_db->psi5_params.idx[0] );

#if defined (REL99) AND defined (TI_PS_FF_EMR)
        if(rr_get_support_for_emr() AND psc_db->psi5_params.v_enh_rep_param_struct)
        {
          /*
           * the ENH parameter are stored temporarily and
           * now transferred to final location
           */
          memcpy(&(psc_db->enh_cw), &(grr_data->psi.enh_param),
            sizeof(T_GRR_ENH_PARA));
        }
        else
        {
          memset(&(psc_db->enh_cw), 0, sizeof(T_GRR_ENH_PARA));
          psc_db->enh_cw.rept_type = REPORT_TYPE_REP;
          psc_db->psi5_params.v_enh_rep_param_struct = FALSE;
        }
#endif
        /*
         * Inform MEAS that the Interference parameters are valid
         */
        psc_db->is_ext_psi5_valid = TRUE;

        return PSI5_MEAS_PARAM_VALID;
      }
    }
  }
  else
  {
    TRACE_EVENT_P2( "PSI5: already received with count = %d, index = %d",
                    psi5->psi5_cnt, psi5->psi5_ind );
  }

  return PSI5_OK;
} /* psi_process_psi5() */



/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi4
+------------------------------------------------------------------------------
| Description : The function psi_process_psi4() ....
|
| Parameters  : T_PSI_4 *psi4
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI4_RET psi_process_psi4 (T_PSI_4 *psi4 )
{
  UBYTE i,m,n;
  BOOL is_psi4_ok;
  TRACE_FUNCTION( "psi_process_psi4" );

  /*
   * Check consistency
   */
  if(psc_db->psi4_params.psi4_change_mark EQ NOT_SET)
  {
    /*
     * Copy change mark etc.
     */
    psc_db->psi4_params.psi4_change_mark = psi4->psi4_cm;
    psc_db->psi4_params.psi4_count   = psi4->psi4_cnt;
    psc_db->psi4_params.instances[0] = psi4->psi4_cnt;/* number of instances */
  }
  else
  {
    /*
     * There is a valid change mark present in the database
     * Check consistency of COUNT and INDEX
     */
    if(
       (psc_db->psi4_params.psi4_count NEQ psi4->psi4_cnt)
       OR
       (psc_db->psi4_params.psi4_count < psi4->psi4_ind)
       OR
       (psc_db->psi4_params.psi4_change_mark NEQ psi4->psi4_cm)
       )
    {
      /*
       * Error situation read a new PSI4
       * The PSI4 change mark field is changed each time information has been updated
       * A new value indicates that the mobile
       * station shall re-read the information from the PSI4
       */
      TRACE_ERROR( "PSI4: inconsistent parameters" );
      psc_db->number_of_valid_int_meas_channels = 0;
      return PSI4_REREAD;
    }

    /* psi4_change_markhas not changed, i.e.
     * PSI4 message has not changed, we already have a consistent set, so we
     * do not have to read the PSI4 message
     */
    if((psc_db->psi4_params.psi4_change_mark EQ psi4->psi4_cm) &&
          (psc_db->state_of_PSI[PSI4].state EQ RECEIPT_OK))
    {
      /* Message has not changed, we already have a consistent set, so we
       * do not have to read it
       */
      TRACE_EVENT( "PSI4: message has not changed" );
      return PSI4_OK;
    }
  }

  psc_db->psi4_params.psi4_index = psi4->psi4_ind;

  if( psc_db->psi4_params.instances[psi4->psi4_ind + 1] EQ FALSE )
  {
    /*
     * We assume that we receive PSI4 instances in the right order,
     * i.e. instance1, instance2, instance3, ..., instance8
     * This is ETSI-Requirement 05.02
     */  
    m = psc_db->number_of_valid_int_meas_channels;  
    if(m < MAX_CHAN_IMEAS)
    {
      /*
       * copy first channel list in the current instance
       */
      psc_db->int_meas_chan_list[m].v_arfcn = FALSE;
      psc_db->int_meas_chan_list[m].v_ma_num_maio = FALSE;

      if(psi4->chan_list_imeas.chan_group.v_arfcn)
      {
        psc_db->int_meas_chan_list[m].v_arfcn = TRUE;        /* valid-flag   for arfcn*/
        psc_db->int_meas_chan_list[m].arfcn = psi4->chan_list_imeas.chan_group.arfcn; /* ARFCN*/
      }
      else
      {
        psc_db->int_meas_chan_list[m].v_ma_num_maio = TRUE;
        psc_db->int_meas_chan_list[m].ma_num = psi4->chan_list_imeas.chan_group.ma_num_maio.ma_num;
        psc_db->int_meas_chan_list[m].maio = psi4->chan_list_imeas.chan_group.ma_num_maio.maio;
      }

      psc_db->int_meas_chan_list[m].ts_alloc = psi4->chan_list_imeas.chan_group.ts_alloc;

      m++;
      if(psi4->chan_list_imeas.v_chan_list2)
      {
        for(i=0; i < (psi4->chan_list_imeas.c_chan_list2) AND (m < MAX_CHAN_IMEAS); i++ )
        {
          /*
           * copy remaining channel list in the current instance
           */
          psc_db->int_meas_chan_list[m].v_arfcn = FALSE;
          psc_db->int_meas_chan_list[m].v_ma_num_maio = FALSE;

          if(psi4->chan_list_imeas.chan_list2[i].chan_group.v_arfcn)
          {
            psc_db->int_meas_chan_list[m].v_arfcn = TRUE;        /* valid-flag   for arfcn*/
            psc_db->int_meas_chan_list[m].arfcn = psi4->chan_list_imeas.chan_list2[i].chan_group.arfcn; /* ARFCN*/
          }
          else
          {
            psc_db->int_meas_chan_list[m].v_ma_num_maio = TRUE;
            psc_db->int_meas_chan_list[m].ma_num = psi4->chan_list_imeas.chan_list2[i].chan_group.ma_num_maio.ma_num;
            psc_db->int_meas_chan_list[m].maio = psi4->chan_list_imeas.chan_list2[i].chan_group.ma_num_maio.maio;
          }
          psc_db->int_meas_chan_list[m].ts_alloc = psi4->chan_list_imeas.chan_list2[i].chan_group.ts_alloc;
          m++;
        }
      }
    }
    else
    {
      TRACE_ERROR( "PSI4: list of INT meas. channels full" );
    }
    psc_db->number_of_valid_int_meas_channels = m;

    /*
     * check whether PSI4 has been received completely or not
     */
    psc_db->psi4_params.instances[psi4->psi4_ind + 1] = TRUE;
    is_psi4_ok = TRUE;
    for(n = 0; n <= psc_db->psi4_params.instances[0]; n++ )
    {
      if(!(psc_db->psi4_params.instances[n + 1]))
      {
        is_psi4_ok = FALSE;/* consistent set of PSI4 not complete */
        break;
      }
    }

    TRACE_EVENT_P2( "PSI4: received with count = %d, index = %d",
                    psi4->psi4_cnt, psi4->psi4_ind );

    if(is_psi4_ok)
    {
      psc_db->state_of_PSI[PSI4].state = RECEIPT_OK;
      return PSI4_INT_LIST_VALID;
    }
  }
  else
  {
    TRACE_EVENT_P2( "PSI4: already received with count = %d, index = %d",
                    psi4->psi4_cnt, psi4->psi4_ind );
  }


 
  return PSI4_OK;

} /* psi_process_psi4() */

#if defined (REL99) AND defined (TI_PS_FF_EMR)
/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi3ter
+------------------------------------------------------------------------------
| Description : The function psi_process_psi3ter() processes the IEs received 
|               in PSI3 ter message
|
| Parameters  : T_PSI_3_TER *psi3ter
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI3TER_RET psi_process_psi3ter (T_PSI_3_TER *psi3ter)
{
  BOOL is_psi3ter_ok;
#ifdef TI_PS_FF_RTD
  UBYTE n,rtd_index;
#else 
  UBYTE n;
#endif /* #ifdef TI_PS_FF_RTD */


  TRACE_FUNCTION( "psi_process_psi3ter" );

  if(psc_db->psi3ter_params.psi3ter_change_mark EQ NOT_SET)
  {
    if(  ( (psc_db->psi3_params.psi3_change_mark NEQ NOT_SET) AND
      (psi3ter->psi3_cm NEQ psc_db->psi3_params.psi3_change_mark) ) OR 
         ( (psc_db->psi3bis_params.psi3bis_change_mark NEQ NOT_SET) AND
      (psi3ter->psi3_cm NEQ psc_db->psi3bis_params.psi3bis_change_mark) )  )
    {
     /*
      * Error situation read new PSI3ter
      * The PSI3 change mark field is changed each time information has been updated
      * in any of the PSI3 to PSI3 ter messages. A new value indicates that the mobile
      * station shall re-read the information from the PSI3 to PSI3 ter messages.
      */
      TRACE_ERROR( "PSI3ter: inconsistent change mark, read PSI3 to PSI3ter");
      return PSI3TER_REREAD_PSI3_3BIS_3TER;
    }

    /*
     * Copy change mark etc.
     */
    psc_db->psi3ter_params.psi3ter_change_mark = psi3ter->psi3_cm;
    psc_db->psi3ter_params.psi3ter_count       = psi3ter->psi3ter_cnt;
    psc_db->psi3ter_params.instances[0]        = psi3ter->psi3ter_cnt; /* number of instances */
  }
  else
    /*
     * There is a valid change mark present in the database
     * Check consistency of COUNT and INDEX
     */
  {
    if(  (psc_db->psi3ter_params.psi3ter_change_mark NEQ psi3ter->psi3_cm) OR
      ( (psc_db->psi3_params.psi3_change_mark NEQ NOT_SET) AND
      (psc_db->psi3ter_params.psi3ter_change_mark NEQ
      psc_db->psi3_params.psi3_change_mark) ) OR
      ( (psc_db->psi3bis_params.psi3bis_change_mark NEQ NOT_SET) AND
      (psc_db->psi3ter_params.psi3ter_change_mark NEQ
      psc_db->psi3bis_params.psi3bis_change_mark) )  )
    {
      /*
       * Error situation read new PSI3ter
       * The PSI3 change mark field is changed each time information has been updated
       * in any of the PSI3 to PSI3 ter messages. A new value indicates that the mobile
       * station shall re-read the information from the PSI3 to PSI3 ter messages.
       */
      TRACE_ERROR( "PSI3ter: inconsistent change mark, read PSI3 to PSI3ter");
      return PSI3TER_REREAD_PSI3_3BIS_3TER;
    }
    if( (psc_db->psi3ter_params.psi3ter_count NEQ psi3ter->psi3ter_cnt) OR
        (psc_db->psi3ter_params.psi3ter_count < psi3ter->psi3ter_ind) )
    {
     TRACE_ERROR( "PSI3ter: inconsistent parameters, read PSI3ter");
     return PSI3TER_REREAD_PSI3TER;
    }
    
    if((psc_db->psi3ter_params.psi3ter_change_mark EQ psi3ter->psi3_cm) AND
      (psc_db->state_of_PSI[PSI3ter].state EQ RECEIPT_OK))
    {
      /* Message has not changed, we already have a consistent set, so we
       * do not have to read it
       */
      TRACE_EVENT("PSI3ter: message has not changed");
      return PSI3TER_OK;
    }
  } /* psi3ter_change_mark valid */

  psc_db->psi3ter_params.psi3ter_index = psi3ter->psi3ter_ind;
    
  if( psc_db->psi3ter_params.instances[psi3ter->psi3ter_ind + 1] EQ FALSE )
  {
    /*
     * Copy GPRS report priority parameters
     */
    /* GPRS Report priority can be received in only one instance since start 
    index is not given for mapping to BA as in RTD and BSIC mapping in SI */
    if( (psi3ter->rtd_rep_prio_trnc_grp.v_gprs_rep_prio_cell_desc EQ TRUE) AND
      (psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells NEQ 0) )
    {
      if(psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells > MAX_NR_OF_GSM_NC)
      {
        grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells =
          MAX_NR_OF_GSM_NC;
      }
      else
      {
        grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells = 
          psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells;
        
        /* Set default report prio for the remaining cells upto max of 96 cells */
        for(n = psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells;
            n < MAX_NR_OF_GSM_NC; n++)
        {
          grr_data->psi.enh_param.gprs_rept_prio_desc.rept_prio[n] = 
            NORMAL_PRIO;
        }
      }
      
      for (n = 0; n < grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells; n++)
      {
        grr_data->psi.enh_param.gprs_rept_prio_desc.rept_prio[n] = 
          psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.rep_prio[n];
      }      
    }

#ifdef TI_PS_FF_RTD
    /* Store the received RTD values into the temporary location */
    if(psi3ter->rtd_rep_prio_trnc_grp.v_real_time_diff EQ TRUE)
    {
      if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.v_rtd_struct_6bit EQ TRUE)
      {
        if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.v_cell_index_start_rtd EQ TRUE)
          rtd_index = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.cell_index_start_rtd;
        else
          rtd_index = RTD_DEFAULT_INDEX;
        if( rtd_index < MAX_NR_OF_NCELL )
        {
          grr_data->psi.rtd[rtd_index] = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.rtd6_struct.rtd_6bit;
          for(n=0;n<psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.c_rtd6_struct_opt_array AND rtd_index < MAX_NR_OF_NCELL - 1;n++)
          {
            rtd_index++;
            grr_data->psi.rtd[rtd_index] = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.rtd6_struct_opt_array[n].rtd_6bit;
          } /*for*/
        } /*if*/
      } /*if*/
      if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.v_rtd_struct_12bit EQ TRUE)
      {
        if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.v_cell_index_start_rtd EQ TRUE)
          rtd_index = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.cell_index_start_rtd;
        else
          rtd_index = RTD_DEFAULT_INDEX;
        if( rtd_index < MAX_NR_OF_NCELL )
        {
          grr_data->psi.rtd[rtd_index] = RTD_12BIT;
          grr_data->psi.rtd[rtd_index] |= psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.rtd12_struct.rtd_12bit;
          for(n=0;n<psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.c_rtd12_struct_opt_array AND rtd_index < MAX_NR_OF_NCELL - 1;n++)
          { 
            rtd_index++;
            grr_data->psi.rtd[rtd_index] = RTD_12BIT;
            grr_data->psi.rtd[rtd_index] |= psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.rtd12_struct_opt_array[n].rtd_12bit;
          } /*for*/
        }/*if*/
      } /*if*/
    } /*if*/
#endif /* #ifdef TI_PS_FF_RTD */

    TRACE_EVENT_P2( "PSI3ter: received with count = %d, index = %d",
                    psi3ter->psi3ter_cnt, psi3ter->psi3ter_ind );

    /*
     * check whether PSI3TER has been received completely or not
     */
    psc_db->psi3ter_params.instances[psi3ter->psi3ter_ind + 1] = TRUE;
    psc_db->psi3ter_params.prev_psi3ter_index = 
    psc_db->psi3ter_params.psi3ter_index;
    
    is_psi3ter_ok = TRUE;
    for(n = 0; n <= psc_db->psi3ter_params.instances[0]; n++ )
    {
      if(!(psc_db->psi3ter_params.instances[n + 1]))
      {
        is_psi3ter_ok = FALSE;/* consistent set of PSI3TER not complete */
        break;
      }
    }

    if(is_psi3ter_ok)
    {
      psc_db->state_of_PSI[PSI3ter].state = RECEIPT_OK;
      
      /* Copy the GPRS priority information to permanent storage */
      if(grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells NEQ 0)
      {
        for(n = 0; n <= grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells; n++)
        {
          psc_db->enh_cw.gprs_rept_prio_desc.rept_prio[n] = 
            grr_data->psi.enh_param.gprs_rept_prio_desc.rept_prio[n];
        }
        /* Initialize to 0 before receiving the next consistent set of PSI3 ter */
        grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells = 0;
      }
      else
      {
        /* Set report priority to NORMAL if not received */
        for(n = 0; n < MAX_NR_OF_GSM_NC; n++)
        {
          psc_db->enh_cw.gprs_rept_prio_desc.rept_prio[n] = NORMAL_PRIO;
        }
      }
#ifdef TI_PS_FF_RTD
      /* store the RTD values received in all instances of PSI3ter in permanent location */
      memcpy(&psc_db->rtd,&grr_data->psi.rtd,MAX_NR_OF_NCELL*sizeof(T_RTD_VALUE));
        /* reset the temporary storage to RTD value not available */
      for( n = 0; n < MAX_NR_OF_NCELL; n++ )
        grr_data->psi.rtd[n] = RTD_NOT_AVAILABLE;
#endif /* #ifdef TI_PS_FF_RTD */
        return PSI3TER_OK;

    }
  }
  else
  {
    TRACE_EVENT_P2( "PSI3ter: already received with count = %d, index = %d",
                    psi3ter->psi3ter_cnt, psi3ter->psi3ter_ind );
  }
  
  return PSI3TER_OK; 
} /* psi_process_psi3ter() */
#endif


/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi3bis
+------------------------------------------------------------------------------
| Description : The function psi_process_psi3bis() ....
|
| Parameters  : T_PSI_3_BIS *psi3bis
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI3BIS_RET psi_process_psi3bis (T_PSI_3_BIS *psi3bis)
{
  BOOL is_psi3bis_ok;
  UBYTE n;

  TRACE_FUNCTION( "psi_process_psi3bis" );

  /*
   * Each neighbour cell listed in PSI3 and in one or more instances
   * of PSI3bis is assigned an ascending index used for measurement reports.
   * The first neighbour cell in PSI3 has the lowest index  (= 0),
   * and the last neighbour cell in the highest indexed PSI3bis message has
   * the highest index. The total number of neighbour cells in the BA-GPRS
   * shall not exceed 32.
   * If a mobile station receives more than 32 cells in the BA-GPRS,
   * only the 32 cells with the lowest indexes shall be considered.
   */

  if(psc_db->psi3bis_params.psi3bis_change_mark EQ NOT_SET)
  {
    /*
     * Copy change mark etc.
     */
    psc_db->psi3bis_params.psi3bis_change_mark = psi3bis->psi3_cm;
    psc_db->psi3bis_params.psi3bis_count       = psi3bis->psi3bis_cnt;
    psc_db->psi3bis_params.instances[0]        = psi3bis->psi3bis_cnt; /* number of instances */
  }
  else
  {
    /*
     * There is a valid change mark present in the database
     * Check consistency of COUNT and INDEX
     */
    if(
       (psc_db->psi3bis_params.psi3bis_count NEQ psi3bis->psi3bis_cnt)
       OR
       (psc_db->psi3bis_params.psi3bis_count < psi3bis->psi3bis_ind)
       OR
       (psc_db->psi3bis_params.psi3bis_change_mark NEQ psi3bis->psi3_cm)
      )
    {
      /*
       * Error situation read a new PSI3bis
       * The PSI3 change mark field is changed each time information has been updated
       * in any of the PSI3 or PSI3 bis messages. A new value indicates that the mobile
       * station shall re-read the information from the PSI3 and all PSI3 bis messages.
       */
#if defined (REL99) AND defined (TI_PS_FF_EMR)
      TRACE_ERROR( "PSI3bis: inconsistent parameters, read PSI3 PSI3bis and PSI3ter");

      return PSI3BIS_REREAD_PSI3_3BIS_3TER;
#else
      TRACE_ERROR( "PSI3bis: inconsistent parameters, read PSI3 and PSI3bis");

      return PSI3BIS_REREAD_PSI3_3BIS;
#endif
    }

    if((psc_db->psi3bis_params.psi3bis_change_mark EQ psi3bis->psi3_cm) &&
          (psc_db->state_of_PSI[PSI3bis].state EQ RECEIPT_OK))
    {
      /* Message has not changed, we already have a consistent set, so we
       * do not have to read it
       */
      TRACE_EVENT("PSI3bis: message has not changed");
      return PSI3BIS_OK;
    }
    else if(psc_db->psi3bis_params.psi3bis_change_mark NEQ psi3bis->psi3_cm)
    {
      TRACE_ERROR("PSI3bis: message has changed");
      return PSI3BIS_REREAD_PSI3BIS;
    }

  } /* psi3bis_change_mark valid */

  psc_db->psi3bis_params.psi3bis_index = psi3bis->psi3bis_ind;
  
  if( psc_db->psi3bis_params.instances[psi3bis->psi3bis_ind + 1] EQ FALSE )
  {
    UBYTE number;

    /*
     * Copy NCELL parameters
     */
    number = 
      psi_store_ncell_param( &psi3bis->ncell_par_trnc_grp.ncell_par[0],
                             psi3bis->ncell_par_trnc_grp.c_ncell_par,
                             psi3bis->ncell_par_trnc_grp.v_ncell_par,
                             INFO_TYPE_PSI3BIS, 
                             psi3bis->psi3bis_ind );

    /*
     * Copy NCELL parameters 2
     */
    psi_store_ncell_param2( psi3bis, number );

    TRACE_EVENT_P2( "PSI3bis: received with count = %d, index = %d",
                    psi3bis->psi3bis_cnt, psi3bis->psi3bis_ind );

    /*
     * check whether PSI3BIS has been received completely or not
     */
    psc_db->psi3bis_params.instances[psi3bis->psi3bis_ind + 1] = TRUE;
    is_psi3bis_ok = TRUE;
    for(n = 0; n <= psc_db->psi3bis_params.instances[0]; n++ )
    {
      if(!(psc_db->psi3bis_params.instances[n + 1]))
      {
        is_psi3bis_ok = FALSE;/* consistent set of PSI3BIS not complete */
        break;
      }
    }

    if(is_psi3bis_ok)
    {
      psc_db->state_of_PSI[PSI3bis].state = RECEIPT_OK;
    
      if( psc_db->state_of_PSI[PSI3].state EQ RECEIPT_OK )
      {
        psi_restore_ncell_param( );

        return PSI3BIS_NCELL_VALID;
      }
      else
      {
        return PSI3BIS_OK;
      }
    }
  }
  else
  {
    TRACE_EVENT_P2( "PSI3bis: already received with count = %d, index = %d",
                    psi3bis->psi3bis_cnt, psi3bis->psi3bis_ind );
  }


  return PSI3BIS_OK;
} /* psi_process_psi3bis() */

/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi3
+------------------------------------------------------------------------------
| Description : The function psi_process_psi3() ....
|
| Parameters  : T_PSI_3 *psi3
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI3_RET psi_process_psi3 (T_PSI_3 *psi3 )
{
  T_PSI3_RET return_val = PSI3_OK;

  TRACE_FUNCTION( "psi_process_psi3" );

  /*
   * Check whether the cell has been barred or not. If YES, inform CTRL
   */
  if(psi3->scell_par.cell_ba)
  {
    /*Barred*/
    TRACE_EVENT( "PSI3: cell barred" );

    GRR_EM_SET_CELL_BARRED;

    return PSI3_CELL_BARRED;
  }
  
  psc_db->state_of_PSI[PSI3].state = RECEIPT_OK;

  if(psc_db->psi3_params.psi3_change_mark  NEQ NOT_SET)
  {
    /* compare change mark*/
    if(psc_db->psi3_params.psi3_change_mark EQ psi3->psi3_cm)
    {
      /*
       * Information of the PSI3 PSI3ter messages have  NOT been updated: return!!
       */
      TRACE_EVENT( "PSI3: messages PSI3 and PSI3bis have not changed" );
      return PSI3_OK;
    }
    /*
     * Information of the PSI3 message has been updated, so we have to re-read the parameters
     *
     * A new value indicates that the mobile station shall re-read the information from
     * the PSI3 - PSI3ter messages.
     */
    /*
     * Set the change mark parameter of psi3bis to NOT_SET. This causes that the PSI3BIS and
     * PSI3 ter instances to be read again
     */
    psc_db->psi3bis_params.psi3bis_change_mark = NOT_SET;
    psc_db->state_of_PSI[PSI3bis].state = NEEDED;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    psc_db->psi3ter_params.psi3ter_change_mark = NOT_SET;

    if(psc_db->v_add_psi AND psc_db->add_psi.psi3ter_broadcast)
    {
      psc_db->state_of_PSI[PSI3ter].state = NEEDED;   
    }
    else
    {
      psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; 
    }
#endif

    /*
     * Set the consistent set parameters to FALSE
     */
    psi_reset_psi3bis();
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    psi_reset_psi3ter();
#endif

    /* This field is coded as the binary representation of the PSI3 bis index
     * (in the PSI3 bis message) for the last (highest indexed) individual PSI3
     * bis message.Range: 0-15.
     */
    psc_db->psi3_params.psi3_bis_count = psi3->psi3bis_cnt;
    /*
     * Ncell parameter are invalid. We have to inform MEAS-Service
     */
    return_val = PSI3_NCELL_INVALID;
  }
  else
  {
    /*  This is the first time that we have received a PSI3 message*/
    psc_db->psi3_params.psi3_change_mark = psi3->psi3_cm;
    psc_db->psi3_params.psi3_bis_count   = psi3->psi3bis_cnt;
  }

  /* copy Serving Cell parameters        */
  psc_db->scell_par.cell_ba                          = psi3->scell_par.cell_ba;
  psc_db->scell_par.exc_acc                          = psi3->scell_par.exc_acc;
  psc_db->scell_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min 
                                                     = psi3->scell_par.gprs_rxlev_access_min;
  psc_db->scell_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch
                                                     = psi3->scell_par.txpwr_max_cch;
  grr_data->meas.pwr_offset                          = 0;

  psc_db->scell_par.cr_par_1.v_hcs_par               = psi3->scell_par.v_hcs_par;
  psc_db->scell_par.cr_par_1.hcs_par                 = psi3->scell_par.hcs_par;
  psc_db->scell_par.multi_band_rep                   = psi3->scell_par.multi_band_rep;

  /*copy General Cell Selection parameter */
  memcpy(&(psc_db->gen_cell_par), &(psi3->gen_cell_par),sizeof(T_gen_cell_par));

  /* process default values for General Cell Selection parameter */
  if( psc_db->gen_cell_par.v_t_resel EQ FALSE )
  {
    psc_db->gen_cell_par.v_t_resel = TRUE;
    psc_db->gen_cell_par.t_resel   = GRR_T_RESEL_DEFAULT;
  }

  if( psc_db->gen_cell_par.v_ra_re_hyst EQ FALSE )
  {
    psc_db->gen_cell_par.v_ra_re_hyst = TRUE;
    psc_db->gen_cell_par.ra_re_hyst   = psc_db->gen_cell_par.gprs_c_hyst;
  }

  /* copy Neighbor cell parameters*/
  psi_store_ncell_param( &psi3->ncell_par[0], psi3->c_ncell_par,
                         psi3->v_ncell_par, INFO_TYPE_PSI3, 0 );

  if( psc_db->state_of_PSI[PSI3].state    EQ RECEIPT_OK AND 
      psc_db->state_of_PSI[PSI3bis].state EQ RECEIPT_OK     )
  {
    psi_restore_ncell_param( );
    
    return_val = PSI3_NCELL_VALID;
  }
  
  TRACE_EVENT_P1( "PSI3: received with return value %d", return_val );
  
  grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE;

  return return_val;
} /* psi_process_psi3() */

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_rfl
+------------------------------------------------------------------------------
| Description : The function psi_copy_rfl() .... copy Reference Frequency List (RFL)
|
| Parameters  : T_PSI_2 *psi2: pointer to PSI2 message
|
+------------------------------------------------------------------------------
*/

LOCAL void  psi_copy_rfl(T_PSI_2 *psi2)
{

  UBYTE m, n;
  TRACE_FUNCTION( "psi_copy_rfl" );

  for(m = 0; m < psi2->psi_2_trnc_grp.c_rfl; m++)
  {
    for(n = 0; n < MAX_RFL; n++)
    {
      if( (psi2->psi_2_trnc_grp.rfl[m].rfl_num EQ psc_db->rfl[n].num) OR (psc_db->rfl[n].num EQ NOT_SET) )
      {
        psc_db->rfl[n].num       = psi2->psi_2_trnc_grp.rfl[m].rfl_num;
        /*
         * This function copies the frequencies into list. This function takes the arranging
         * of ARFCN into account cf. 12.10a GPRS Mobile Allocation in 04.60
         */
        grr_create_channel_list (&psi2->psi_2_trnc_grp.rfl[m], psc_db->rfl[n].list);
        /*
         * Exit from the for loop
         */
        n = MAX_RFL;
      }
    }
  }

}/* psi_copy_rfl*/

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_ma_from_psi2
+------------------------------------------------------------------------------
| Description : The function psi_copy_ma_from_psi2() .... copy GPRS Mobile Allocation (MA)
|
| Parameters  : T_PSI_2 *psi2: pointer to PSI2 message
|
+------------------------------------------------------------------------------
*/
LOCAL void  psi_copy_ma_from_psi2(T_PSI_2 *psi2)
{
  UBYTE m, n, copiedElements = 0;
  TRACE_FUNCTION( "psi_copy_ma_from_psi2" );

  for(m = 0; m < psi2->psi_2_trnc_grp.c_gprs_ms_alloc; m++)
  {
    if((psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num != MA_NUMBER_4_PSI13_OR_CELL_ALLOC ) && /* ignore MA_NUMBER with 14 or 15: 0..13 in PSI2*/
       (psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num != MA_NUMBER_4_ASSIGNMENT ))
    {
      for(n = 0; n < MAX_GPRS_MS_ALLOC; n++)
      {
        if( (psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num EQ psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num) ||
            (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ NOT_SET) )
        {
          psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num;
          memcpy(&(psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie),
                      &(psi2->psi_2_trnc_grp.gprs_ms_alloc[m].gprs_ms_alloc_ie),
                      sizeof(T_gprs_ms_alloc_ie));
          n = MAX_GPRS_MS_ALLOC; /* to break the for loop*/
          copiedElements++; /* for debug*/
        }
      }
    }
  }

  if(copiedElements < psi2->psi_2_trnc_grp.c_gprs_ms_alloc)
  {
    TRACE_ERROR("copiedElements < psi2->c_gprs_ms_alloc in" );
  }
}/* psi_copy_ma_from_psi2*/

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_ca
+------------------------------------------------------------------------------
| Description : The function psi_copy_ca() .... copy Cell Allocation (CA)
|
| Parameters  : T_PSI_2 *psi2: pointer to PSI2 message
|
+------------------------------------------------------------------------------
*/
LOCAL void  psi_copy_ca(T_PSI_2 *psi2)
{
  UBYTE m,n;
  TRACE_FUNCTION( "psi_copy_ca" );
  /*TRACE_EVENT("psi_copy_ca");
  TRACE_EVENT_P1("c_ca: %d", psi2->c_cell_alloc);
  */
  for(m = 0; m < psi2->psi_2_trnc_grp.c_cell_alloc; m++)
  {
    for(n = 0; n < MAX_CELL_ALLOC; n++)
    {
      if( (psi2->psi_2_trnc_grp.cell_alloc[m].rfl_num EQ psc_db->cell_alloc[n].rfl_num)
          || (psc_db->cell_alloc[n].rfl_num EQ NOT_SET) )
      {
        psc_db->cell_alloc[n].rfl_num = psi2->psi_2_trnc_grp.cell_alloc[m].rfl_num;
        n = MAX_CELL_ALLOC;
      }
    }
    psc_db->v_cell_alloc = TRUE;
  }
}/* psi_copy_ca*/

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_pccch
+------------------------------------------------------------------------------
| Description : The function psi_copy_pccch() .... copy PCCCH Description
|
| Parameters  : T_PSI_2 *psi2: pointer to PSI2 message
|
+------------------------------------------------------------------------------
*/
LOCAL void  psi_copy_pccch(T_PSI_2 *psi2)
{
  UBYTE m, n, i, ii, j;

  TRACE_FUNCTION( "psi_copy_pccch" );

  m = 0;
  for(n = 0; n < psi2->psi_2_trnc_grp.c_pccch_des; n++)
  {
      if(psi2->psi_2_trnc_grp.pccch_des[n].v_nh_pccch_c AND (m < MAX_PCCCH_DES))
      {
        /* 
         * Non hopping parameters
         */
        for(j = 0; j < psi2->psi_2_trnc_grp.pccch_des[n].c_nh_pccch_c; j++)
        {
          ii = 128;
          for(i = 0; i < 8; i++)
          {
            if( ((psi2->psi_2_trnc_grp.pccch_des[n].nh_pccch_c[j].ts_alloc & ii ) EQ ii) ) /* to get the timeslot number */
            {
              psc_db->paging_group.pccch[m].is_static = TRUE;
              psc_db->paging_group.pccch[m].tsc    = psi2->psi_2_trnc_grp.pccch_des[n].tsc;
              psc_db->paging_group.pccch[m].arfcn = psi2->psi_2_trnc_grp.pccch_des[n].nh_pccch_c[j].arfcn;
              psc_db->paging_group.pccch[m].tn = i;/* timeslot number*/
              m++;
              if( m >= MAX_PCCCH_DES )
                break;
            }
            ii = ii/2;
          }
        }
      }

      if(psi2->psi_2_trnc_grp.pccch_des[n].v_ma_h_s1 AND (m < MAX_PCCCH_DES))
      {
        /* 
         * Hopping parameters
         */        
        for(j = 0; j < psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.c_h_pccch_c; j++)
        {
          
          ii = 128;
          for(i = 0; i < 8; i++)
          {
            if( ((psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.h_pccch_c[j].ts_alloc & ii ) EQ ii) ) /* to get the timeslot number */
            {
              psc_db->paging_group.pccch[m].is_static = FALSE;              
              psc_db->paging_group.pccch[m].ma_num    = psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.ma_num;
              psc_db->paging_group.pccch[m].tsc       = psi2->psi_2_trnc_grp.pccch_des[n].tsc;
              psc_db->paging_group.pccch[m].maio      = psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.h_pccch_c[j].maio;
              psc_db->paging_group.pccch[m].tn        = i;/* timeslot number*/
              m++;
              if( m >= MAX_PCCCH_DES )
                break;
            }
            ii = ii/2;
          }
        }
      }
      psc_db->paging_group.kc = m; /*number of timeslots carrying PCCCH*/
  }
}/* psi_copy_pccch*/

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_cell_id
+------------------------------------------------------------------------------
| Description : The function psi_copy_cell_id() ....
|
| Parameters  : T_PSI_2 *psi2: pointer to PSI2 message strcuture
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_copy_cell_id(T_PSI_2 *psi2)
{
  TRACE_FUNCTION( "psi_copy_cell_id" );

  psc_db->cell_info_for_gmm.cell_info.cell_env.rai.plmn.v_plmn = TRUE;

  if( psi2->psi_2_trnc_grp.cell_id.loc_area_ident.c_mnc EQ 2 )
  {
    /* Internally G23 uses always 3-digit-MNC */
    psi2->psi_2_trnc_grp.cell_id.loc_area_ident.c_mnc  = SIZE_MNC;
    psi2->psi_2_trnc_grp.cell_id.loc_area_ident.mnc[2] = 0xf;
  }

  memcpy( psc_db->cell_info_for_gmm.cell_info.cell_env.rai.plmn.mcc,
          psi2->psi_2_trnc_grp.cell_id.loc_area_ident.mcc, SIZE_MCC );

  memcpy( psc_db->cell_info_for_gmm.cell_info.cell_env.rai.plmn.mnc,
          psi2->psi_2_trnc_grp.cell_id.loc_area_ident.mnc, SIZE_MNC );

  psc_db->cell_info_for_gmm.cell_info.cell_env.rai.lac = psi2->psi_2_trnc_grp.cell_id.loc_area_ident.lac;
  psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = psi2->psi_2_trnc_grp.cell_id.rac;
  psc_db->cell_info_for_gmm.cell_info.cell_env.cid     = psi2->psi_2_trnc_grp.cell_id.cell_id_ie;

}/* psi_copy_cell_id*/

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_non_gprs_opt
+------------------------------------------------------------------------------
| Description : The function psi_copy_non_gprs_opt() ....
|
| Parameters  : T_PSI_2 *psi2: pointer to PSI2 message strcuture
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_copy_non_gprs_opt(T_PSI_2 *psi2)
{
  TRACE_FUNCTION( "psi_copy_non_gprs_opt" );

  psc_db->v_non_gprs_opt = TRUE;
  /* copy parameters*/
  memcpy(&(psc_db->non_gprs_opt), &(psi2->psi_2_trnc_grp.non_gprs_opt), sizeof(T_non_gprs_opt));


}/* psi_copy_non_gprs_opt*/
/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi2
+------------------------------------------------------------------------------
| Description : The function psi_process_psi2() ....
|
| Parameters  : T_PSI_2 *psi2
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI2_RET psi_process_psi2 (T_PSI_2 *psi2 )
{
  UBYTE n=0;

  TRACE_FUNCTION( "psi_process_psi2" );

  if(psc_db->psi2_params.psi2_change_mark EQ NOT_SET)
  {
    /* This is the first PSI2 message*/
    psc_db->psi2_params.psi2_change_mark = psi2->psi2_cm;
    psc_db->psi2_params.psi2_count   = psi2->psi2_cnt;
    psc_db->psi2_params.instances[0] = psi2->psi2_cnt;/* number of instances */
  }
  else
  {
    /* Check consistency of COUNT and INDEX*/
    if(
       (psc_db->psi2_params.psi2_count NEQ psi2->psi2_cnt)
       OR
       (psc_db->psi2_params.psi2_count < psi2->psi2_ind)
       OR
       (psc_db->psi2_params.psi2_change_mark NEQ psi2->psi2_cm)
      )
    {
      /* Error situation read a new PSI2*/
      TRACE_EVENT( "PSI2: inconsistent parameters" );
      return PSI2_REREAD;
    }

    /* There was a valid psi2_change_mark: compare change_mark values*/
    if((psc_db->psi2_params.psi2_change_mark EQ psi2->psi2_cm) AND
      (psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK))
    {
      /* PSI2 message has not changed, we already have a consistent set, so we
       * do not have to read the PSI2 message
       */
      TRACE_EVENT( "PSI2: message has not changed" );
      return PSI2_OK;
    }
  } /* psi2_change_mark set */


  if( psc_db->psi2_params.instances[psi2->psi2_ind + 1] EQ FALSE )
  {
    psc_db->psi2_params.instances[psi2->psi2_ind + 1] = TRUE;

    /*check consistency */
    psc_db->complete_acq.psi2_ok = TRUE;
    for(n = 0; n <= psc_db->psi2_params.instances[0]; n++ )
    {
      if(!(psc_db->psi2_params.instances[n + 1]))
      {
        psc_db->complete_acq.psi2_ok = FALSE;/* consistent set of PSI2 not complete */
        break;
      }
    }

    psc_db->state_of_PSI[PSI2].state = (psc_db->complete_acq.psi2_ok) ? RECEIPT_OK : NEEDED;

    if(psi2->psi_2_trnc_grp.v_cell_id)
    {
      /* copy cell identification*/
      psi_copy_cell_id(psi2);
    }

    if(psi2->psi_2_trnc_grp.v_non_gprs_opt)
    {
      /* copy non GPRS cell options*/
      psi_copy_non_gprs_opt(psi2);
    }

    /*
     * copy Reference Frequency List (RFL)
     */
    psi_copy_rfl(psi2);

    /*
     * copy Cell Allocation (CA)
     */
    psi_copy_ca(psi2);

    /*
     * copy GPRS Mobile Allocation (MA)
     */
    psi_copy_ma_from_psi2(psi2);

    /*
     * copy PCCCH Description
     */
    psi_copy_pccch(psi2);
#ifdef REL99
    if(psi2->psi_2_trnc_grp.v_release_99_str_psi_2 AND psi2->psi_2_trnc_grp.release_99_str_psi_2.v_add_psi)
    {
      psc_db->add_psi = psi2->psi_2_trnc_grp.release_99_str_psi_2.add_psi;
      psc_db->v_add_psi = TRUE;
      
      if(!psi2->psi_2_trnc_grp.release_99_str_psi_2.add_psi.Psi8_broadcast)
      {
        psc_db->state_of_PSI[PSI8].state = NOT_SEND;  
        psc_db->v_cbch_chan_desc = FALSE;
        
        /* as this is r-99 network, and PBCCH is present
        * CBCH info should be sent to RR. As psi8 is
        * not present, it will deactivated.
        */
        psc_db->send_cbch_info_ind = TRUE;
      }
      
      /* Process psi3ter broadcast indicator */
      if(!psi2->psi_2_trnc_grp.release_99_str_psi_2.add_psi.psi3ter_broadcast)
      {
        psc_db->state_of_PSI[PSI3ter].state = NOT_SEND;  
      }
    }

    if(psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK)
    {
      /* A consistent set of PSI2 has been received. */
      /* Additional PSI Messages information element is within truncation
      notation. If it wasn't received at all, then we should assume 0, 
      hence mark PSI3 ter and PSI 8 as "NOT_SEND"                   */
      if(!psc_db->v_add_psi)
      {
        psc_db->state_of_PSI[PSI8].state = NOT_SEND;          
        psc_db->v_cbch_chan_desc = FALSE;
        if(psc_db->network_rel)
        {
          
        /* as this is r-99 network, and PBCCH is present
        * CBCH info should be sent to RR. As psi8 is
        * not present, it will deactivated.
          */
          psc_db->send_cbch_info_ind = TRUE;
        }
        
        psc_db->state_of_PSI[PSI3ter].state = NOT_SEND;          
      }
      /* PSI2 has got updated. CBCH channel description
      * could depend of PSI2 in case hopping is allowed
      */
      if(psc_db->v_cbch_chan_desc AND !psc_db->cbch_chan_desc.freq_par.v_arfcn)
      {
        psc_db->send_cbch_info_ind = TRUE;                 
      }
    }
#endif
    TRACE_EVENT_P2( "PSI2: received with count = %d, index = %d",
                    psi2->psi2_cnt, psi2->psi2_ind );
  }
  else
  {
    TRACE_EVENT_P2( "PSI2: already received with count = %d, index = %d",
                    psi2->psi2_cnt, psi2->psi2_ind );
  }



  return PSI2_OK;
} /* psi_process_psi2() */

#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi8
+------------------------------------------------------------------------------
| Description : This function stores the contents of PSI 8 for further 
|               processing. 
|               In R-99, PSI8 contains CBCH configuration. If PSI8 is not
|               broadcast or if none of the instances of PSI8 contain 
|               CBCH information, then SMSCB is not active in the cell. 
|
|               CBCH is handled in ALR entity and is configured through RR entity.
|               This message contains CBCH channel description. If cbch 
|               channel description indicates hopping, then to decode 
|               frequency parameters to extract the frequencies for mobile allocation,
|               prior receipt of PSI 2(all instances) and
|               optionally SI13 messages is essential.
|               Hence PSI 8 frequency parameters is not decoded here. It is
|               stored in psc data blase and is decoded before giving
|               RRGRR_CBCH_INFO_IND to RR entity. RRGRR sap messages are 
|               sent from service CTRL.
| Parameters  : T_PSI_4 *psi4
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI8_RET psi_process_psi8 (T_PSI_8 *psi8 )
{
  UBYTE n;
  BOOL is_psi8_ok;
  TRACE_FUNCTION( "psi_process_psi8" );

  /*
   * Check consistency
   */
  if(psc_db->psi8_params.psi8_change_mark EQ NOT_SET)
  {
    /*
     * Copy change mark etc.
     */
    psc_db->psi8_params.psi8_change_mark = psi8->psi8_cm;
    psc_db->psi8_params.psi8_count   = psi8->psi8_cnt;
    psc_db->psi8_params.instances[0] = psi8->psi8_cnt;/* number of instances */
    psc_db->v_cbch_chan_desc = FALSE;
  }
  else
  {
    /*
     * There is a valid change mark present in the database
     * Check consistency of COUNT and INDEX
     */
    if(
       (psc_db->psi8_params.psi8_count NEQ psi8->psi8_cnt)
       OR
       (psc_db->psi8_params.psi8_count < psi8->psi8_ind)
       OR
       (psc_db->psi8_params.psi8_change_mark NEQ psi8->psi8_cm)
       )
    {
      /*
       * Error situation; read a new PSI4
       * The PSI4 change mark field is changed each time information has been updated
       * A new value indicates that the mobile
       * station shall re-read the information from the PSI4
       */
      TRACE_ERROR( "PSI8: inconsistent parameters" );
      psc_db->v_cbch_chan_desc = FALSE;
      return PSI8_REREAD;
    }

    /* psi8_change_markh as not changed, i.e.
     * PSI8 message has not changed, we already have a consistent set, so we
     * do not have to read the PSI4 message
     */
    if((psc_db->psi8_params.psi8_change_mark EQ psi8->psi8_cm) &&
          (psc_db->state_of_PSI[PSI8].state EQ RECEIPT_OK))
    {
      /* Message has not changed, we already have a consistent set, so we
       * do not have to read it
       */
      TRACE_EVENT( "PSI8: message has not changed" );
      return PSI8_OK;
    }
  }

  psc_db->psi8_params.psi8_index = psi8->psi8_ind;

  if( psc_db->psi8_params.instances[psi8->psi8_ind + 1] EQ FALSE )
  {
     /* Store CBCH channel description. To decode Frequency Parameters,
      * it is necessary to receive all instances of PSI2 message.
      * Hence defer decoding of hopping frequency list till 
      * end of acquisition.
      */
     if(psi8->v_cbch_chan_desc)
       {
          memcpy(&(psc_db->cbch_chan_desc),&(psi8->cbch_chan_desc),sizeof(T_cbch_chan_desc));
          psc_db->v_cbch_chan_desc = TRUE;
       }
    /*
     * check whether PSI8 has been received completely or not
     */
    psc_db->psi8_params.instances[psi8->psi8_ind + 1] = TRUE;
    is_psi8_ok = TRUE;
    for(n = 0; n <= psc_db->psi8_params.instances[0]; n++ )
    {
      if(!(psc_db->psi8_params.instances[n + 1]))
      {
        is_psi8_ok = FALSE;/* consistent set of PSI8 not complete */
        break;
      }
    }

    TRACE_EVENT_P2( "PSI8: received with count = %d, index = %d",
                    psi8->psi8_cnt, psi8->psi8_ind );

    if(is_psi8_ok)
    {
      if(psc_db->state_of_PSI[PSI8].state NEQ RECEIPT_OK)
        {
          /* A new copy of PSI8 has been received. 
           * RRGRR_CBCH_INFO_IND has to be sent after 
           * all instances of PSI2 have been received when 
           * acquisition is PARTIAL, and in case of COMPLETE
           *  acquisition after access to the cell is enabled.
           */
          psc_db->state_of_PSI[PSI8].state = RECEIPT_OK;
          psc_db->send_cbch_info_ind = TRUE;
          return PSI8_OK;
        }
    }
  }
  else
  {
    TRACE_EVENT_P2( "PSI8: already received with count = %d, index = %d",
                    psi8->psi8_cnt, psi8->psi8_ind );
  }

  return PSI8_OK;

} /* psi_process_psi8() */
#endif

/*
+------------------------------------------------------------------------------
| Function    : psi_check_change_field
+------------------------------------------------------------------------------
| Description : The function psi_check_change_field() ....
|
| Parameters  : UBYTE psi_change_field; return TRUE: acq needed, FALSE: not needed
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL psi_check_change_field (UBYTE psi_change_field)
{
  BOOL return_value = FALSE;
  TRACE_FUNCTION( "psi_check_change_field" );

  switch(psi_change_field)
  {
    case UPDATE_UNS_PSI: /*Update of unspecified PSI message(s);*/
      psc_db->state_of_PSI[PSI2].state = NEEDED;
      psc_db->state_of_PSI[PSI3].state = NEEDED;
      psc_db->state_of_PSI[PSI3bis].state = NEEDED;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
      psc_db->state_of_PSI[PSI3ter].state = NEEDED;
#endif
      psc_db->state_of_PSI[PSI4].state = NEEDED;
      psc_db->state_of_PSI[PSI5].state = NEEDED; /*??*/
#ifdef REL99
      /* It is necessary to set PSI 8 to needed here. In case 
       * PSI 8 is not broadcast in the cell, this value \
       * would be sent to NOT_SEND when PSI 2 is received
       */
      psc_db->state_of_PSI[PSI8].state = NEEDED;
#endif
      /*psc_db->state_of_PSI[13] = NEEDED;*/
      return_value = TRUE;
      break;
    case UPDATE_UNKNOWN: /* Unknown*/
      return_value = FALSE;
      break;
    case UPDATE_PSI2: /* PSI2 updated*/
      psc_db->state_of_PSI[PSI2].state = NEEDED;
      return_value = TRUE;
      break;
    case UPDATE_PSI3: /* PSI3/PSI3bis/PSI3ter updated*/
      psc_db->state_of_PSI[PSI3].state = NEEDED;
      psc_db->state_of_PSI[PSI3bis].state = NEEDED;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
      if(psc_db->v_add_psi AND psc_db->add_psi.psi3ter_broadcast)
      {
        psc_db->state_of_PSI[PSI3ter].state = NEEDED;   
      }
      else
      {
         psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; 
      }
#endif
      return_value = TRUE;
      break;
    case UPDATE_PSI4: /* PSI4 updated*/
      psc_db->state_of_PSI[PSI4].state = NEEDED;
      return_value = TRUE;
      break;
    case UPDATE_PSI5: /* PSI5 updated*/
      psc_db->state_of_PSI[PSI5].state = NEEDED;
      return_value = TRUE;
      break;
#ifdef REL99
    case UPDATE_PSI8:
      psc_db->state_of_PSI[PSI8].state = NEEDED;
      return_value = TRUE;
      break;
#endif
    default: /* All other values shall be interpreted as 'Update of unknown SI message type'.*/
      return_value = FALSE;
      break;
  }
  return return_value;
} /* psi_check_change_field() */

/*
+------------------------------------------------------------------------------
| Function    : psi_process_psi1
+------------------------------------------------------------------------------
| Description : The function psi_process_psi1() ....
|
| Parameters  : T_PSI_1 *psi1
|
+------------------------------------------------------------------------------
*/
GLOBAL T_PSI1_RET psi_process_psi1 (T_PSI_1 *psi1 )
{
  T_PSI1_RET return_val = PSI1_OK;
#ifdef REL99
  UBYTE current_nw_rel  = psc_db->network_rel;
#endif
  
  TRACE_FUNCTION( "psi_process_psi1" );

  if(psi1->pccch_org_par.bs_pcc_rel)
  {
    /*
     * last PDCH carrying PCCCH and PBCCH will be released shortly, receive si13
     */
    return_val = PSI1_PBCCH_RELEASED;
  }
  else if( grr_is_pbcch_present( ) EQ FALSE )
  {
    return_val = PSI1_PBCCH_ESTABLISHED;
  }
  else
  {
    psc_db->state_of_PSI[PSI1].state = RECEIPT_OK;
    psc_db->complete_acq.psi1_ok = TRUE; /*PSI1 has been received*/

    /* copy repeat period*/
    psc_db->psi1_params.psi1_repeat_period = psi1->psi1_rep_per + 1;

    /* copy repetition rates */
    psc_db->psi1_params.psi_cnt_lr = psi1->psi_cnt_lr;
    if(psi1->v_psi_cnt_hr)
    {
      psc_db->psi1_params.psi_cnt_hr = psi1->psi_cnt_hr + 1;
    }
    else
    {
      psc_db->psi1_params.psi_cnt_hr = 0;/*default*/
    }


    psc_db->psi1_params.psi_status_supported = (psi1->psi_status_ind EQ 1) ? TRUE : FALSE;
    psc_db->measurement_order = psi1->meas_order; /*PSI5 is present in the cell or not*/

    if(!psc_db->measurement_order)
      psc_db->state_of_PSI[PSI5].state = RECEIPT_OK;

    /* Process PRACH parameters*/
    psi_process_prach(&(psi1->prach_ctrl_par));

    /*copy pccch org params*/
    psc_db->pccch.bs_pcc_rel    = psi1->pccch_org_par.bs_pcc_rel;
    psc_db->pccch.bs_pbcch_blks = psi1->pccch_org_par.bs_pbcch_blks;
    psc_db->pccch.bs_pag_blks   = CLIP_BS_PAG_BLKS_RES( psi1->pccch_org_par.bs_pag_blks );
    psc_db->pccch.bs_prach_blks = CLIP_BS_PRACH_BLKS( psi1->pccch_org_par.bs_prach_blks );

    /*copy GPRS cell options*/
    psc_db->v_gprs_cell_opt                      = TRUE;
    psc_db->cell_info_for_gmm.cell_info.net_mode = psi1->gprs_cell_opt.nmo;
    psc_db->gprs_cell_opt.nmo                    = psi1->gprs_cell_opt.nmo;
    psc_db->gprs_cell_opt.t3168                  = psi1->gprs_cell_opt.t3168;
    psc_db->gprs_cell_opt.t3192                  = psi1->gprs_cell_opt.t3192;
    psc_db->gprs_cell_opt.drx_t_max              = psi1->gprs_cell_opt.drx_t_max;
    psc_db->gprs_cell_opt.ab_type                = psi1->gprs_cell_opt.ab_type;
    psc_db->gprs_cell_opt.ctrl_ack_type          = psi1->gprs_cell_opt.ctrl_ack_type;
    psc_db->gprs_cell_opt.bs_cv_max              = psi1->gprs_cell_opt.bs_cv_max;
                                                
    memcpy(&(psc_db->gprs_cell_opt), &(psi1->gprs_cell_opt), sizeof(T_gprs_cell_opt));

    /*if(psi1->gprs_cell_opt.v_pan_struct)
    {
      psc_db->gprs_cell_opt.pan_struct.inc  = psi1->gprs_cell_opt.pan_struct.inc;
      psc_db->gprs_cell_opt.pan_struct.dec  = psi1->gprs_cell_opt.pan_struct.dec;
      psc_db->gprs_cell_opt.pan_struct.pmax = ( psi1->gprs_cell_opt.pan_struct.pmax + 1 ) * 4;
      psc_db->gprs_cell_opt.v_pan_struct    = 1;
    }*/
    if(psi1->gprs_cell_opt.v_gprs_ext_bits)
    {
      memcpy(&(psc_db->gprs_cell_opt.gprs_ext_bits), &(psi1->gprs_cell_opt.gprs_ext_bits), sizeof(T_gprs_ext_bits));
      psc_db->gprs_cell_opt.v_gprs_ext_bits = 1;
    }

    /*Global power control parameters*/
    grr_store_g_pwr_par( &psi1->g_pwr_par );

    /* check whether the PSI4 is broadcast or not*/
    if(!psc_db->g_pwr_par.imeas_chan_list)
      psc_db->state_of_PSI[PSI4].state = RECEIPT_OK;


    TRACE_EVENT_P2( "PSI1: database change mark: %d, message change mark: %d",
                    psc_db->psi1_params.pbcch_change_mark, 
                    psi1->pbcch_change_ma );

    if(psc_db->psi1_params.first_psi1)
    {
      psc_db->psi1_params.pbcch_change_mark = psi1->pbcch_change_ma; /* set the new change mark value*/
    }
    else
    {
      UBYTE incremented_value = psi_compare_change_mark(psi1->pbcch_change_ma, psc_db->psi1_params.pbcch_change_mark);
      psc_db->psi1_params.pbcch_change_mark = psi1->pbcch_change_ma; /* set the new change mark value*/

      if(incremented_value EQ 1)/*partial acq*/
      {
        if(psi_check_change_field(psi1->psi_change_field))
        {
          return_val = PSI1_PARTIAL_ACQ;
        }
      }
      else if(incremented_value > 1) /* incremented_value more than 1: complete acq*/
      {
        return_val = PSI1_COMPLETE_ACQ;
      }
    }

#ifdef REL99
    /* Update the BSS release from PSI1 instead of SI13, when PBCCH is present */ 
    /* Update the SGSN release */
    if (psi1->v_release_99_str_psi_1)
    {
      psc_db->network_rel = BSS_NW_REL_99;
      psc_db->sgsn_rel = psi1->release_99_str_psi_1.sgsnr ? PS_SGSN_99_ONWARDS : PS_SGSN_98_OLDER;
#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
      psc_db->band_indicator = psi1->release_99_str_psi_1.band_indicator;
#endif
    }
    else
    {
      psc_db->sgsn_rel = PS_SGSN_98_OLDER;
#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
      psc_db->band_indicator = NOT_PRESENT_8BIT;
#endif
    }

#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
    /*
     * Update std depending on the band indicator
     */
    att_update_std_band_indicator ( psc_db->band_indicator ); 
#endif

    /* Please note that there is no check for (psi1->release_99 EQ FALSE) and 
     * then setting the psc_db->network_rel to BSS_NW_REL_97 as sometimes the
     * the R99 or R4 network may not broadcast the optional R99 IEs. At that 
     * time, the network release is assigned wrongly if the above check exists.
     */
    if(psc_db->network_rel NEQ current_nw_rel)
    {
      TRACE_EVENT_P2("(PSI1)BSS Network release changed from %d to %d <0 - REL_97, 1 - REL_99, 2 - REL_04>", 
        current_nw_rel, psc_db->network_rel);
    }

    /* Update the SGSN release in the Common library context */
    cl_nwrl_set_sgsn_release(psc_db->sgsn_rel);
#endif

  }
  TRACE_EVENT_P1( "PSI1: received with return value %d", return_val );
  grr_set_pg_nmo();
  return return_val;
} /* psi_process_psi1() */


/*
+------------------------------------------------------------------------------
| Function    : psi_receive_psi
+------------------------------------------------------------------------------
| Description : The function psi_receive_psi() ....
|
| Parameters  : BOOL read_all
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_receive_psi ( UBYTE  psi_reading_type)
{
  TRACE_FUNCTION( "psi_receive_psi" );
  
  if(grr_data->psi.is_pbcch_req_allowed)  
  {
    /*
     * Prepare MPHP_SCELL_PBCCH_REQ to receive psi
     */
    PALLOC(mphp_scell_pbcch_req, MPHP_SCELL_PBCCH_REQ);
    psi_prepare_scell_pbcch_req(mphp_scell_pbcch_req, psi_reading_type);    
    PSEND(hCommL1,mphp_scell_pbcch_req);
    grr_data->psi.is_pbcch_req_needed =FALSE;
  }
  else
  {
    TRACE_EVENT("PBCCH request needed after release of TBF, stop of RR tasks, etc.");
    grr_data->psi.is_pbcch_req_needed =TRUE;
    /*
     * store the reading_type in case of needed in/after release procedure
     */
    grr_data->psi.reading_type=psi_reading_type;  
  }
} /* psi_receive_psi() */


/*
+------------------------------------------------------------------------------
| Function    : psi_process_prach
+------------------------------------------------------------------------------
| Description : The function psi_process_prach() ....
|
| Parameters  : T_prach_ctrl_par *prach: pointer to PRACH control parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_process_prach ( T_prach_ctrl_par *prach )
{
  TRACE_FUNCTION( "psi_process_prach" );

  psc_db->v_prach = TRUE;

  memcpy(&(psc_db->prach), prach, sizeof(T_prach_ctrl_par));

  TRACE_EVENT_P5("ac_class: %d max_ret %d %d %d %d", 
    prach->ac_class,         
    prach->max_retrans[0],
    prach->max_retrans[1], 
    prach->max_retrans[2], 
    prach->max_retrans[3]); 
  TRACE_EVENT_P2("s_prach: %d tx_int:%d", prach->s_prach, prach->tx_int);
  if(prach->v_pers_lev)
  {
    TRACE_EVENT_P4("pers: %d %d %d %d",
      prach->pers_lev.plev[0],
      prach->pers_lev.plev[1],
      prach->pers_lev.plev[2],
      prach->pers_lev.plev[3]);
  }


} /* psi_process_prach() */


/*
+------------------------------------------------------------------------------
| Function    : psi_reset_si_entries
+------------------------------------------------------------------------------
| Description : The function psi_reset_si_entries() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reset_si_entries ( void )
{
  TRACE_FUNCTION( "psi_reset_si_entries" );

  psc_db->psi13_params.bcch_change_mark = NOT_SET;
  psc_db->psi13_params.si13_change_mark = NOT_SET;

} /* psi_reset_si_entries() */

/*
+------------------------------------------------------------------------------
| Function    : psi_acq_state_of_si
+------------------------------------------------------------------------------
| Description : The function psi_acq_state_of_si() ....
|               This function is ONLY called after processing SI13 message
| Parameters  : T_si_states  si_states: contains the state of the SI messages
|               needed for checking for packet access allowance
|
+------------------------------------------------------------------------------
*/
GLOBAL T_ACQ_STATE_RET psi_acq_state_of_si ( T_si_states  si_states)
{
  T_ACQ_STATE_RET ret_value = ACQ_RUNNING;

  TRACE_FUNCTION( "psi_acq_state_of_si" );

  switch(psc_db->acq_type)
  {
    case PARTIAL:
        ret_value = ACQ_PART_OK;
      break;
    case COMPLETE:
      if((si_states.si3_state EQ SI3_RECEIVED) AND (si_states.si13_state EQ SI13_RECEIVED))
      {
        if((si_states.si1_state EQ SI1_NOT_SEND) OR (si_states.si1_state EQ SI1_RECEIVED))
        {
          ret_value = ACQ_COMP_OK;
        }
      }
      break;
    case PERIODICAL_SI13_READING:
      ret_value = ACQ_PERIOD_OK;
      break;
    default:
      break;
  }
  return ret_value;
} /* psi_acq_state_of_si() */


/*
+------------------------------------------------------------------------------
| Function    : psi_is_update_needed
+------------------------------------------------------------------------------
| Description : The function psi_is_update_needed() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL psi_is_update_needed ( UBYTE si_change_field )
{
  TRACE_FUNCTION( "psi_is_update_needed" );

  switch(si_change_field)
  {
    case UNSPECIFIED_SI:
    case UPDATE_SI1:
    case UPDATE_SI2_SI2BIS_OR_SI2TER:
    case UPDATE_SI3_SI4_SI7_OR_SI8:
    case UPDATE_SI9:
      return TRUE;
    default:
      return FALSE;
  }
} /* psi_is_update_needed() */

/*
+------------------------------------------------------------------------------
| Function    : psi_update_data_to_request
+------------------------------------------------------------------------------
| Description : The function psi_update_data_to_request updates the static
|                   and  hopping frequencies and other parameters to request PSI
|                   data. This function is called after receiving SI13 or PSI13 or PSI1
|
| Parameters  : UBYTE init_needed: checks whether initialization is needed or not
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_update_data_to_request( UBYTE init_needed)
{
  T_MPHP_SCELL_PBCCH_REQ *ptr_prim;
  
  TRACE_FUNCTION( "psi_update_data_to_request" );

  ptr_prim = &psc_db->scell_pbcch;

  if(init_needed)
  {
    TRACE_EVENT("Init Needed");
    memset(&psc_db->pccch, 0, sizeof(T_pccch_org_par)); /*initial*/
    psc_db->psi1_params.psi_cnt_hr = 0; /* initial*/
    psc_db->psi1_params.psi_cnt_lr = 0; /* initial*/
  }

  /*
   * set values for mphp_scell_pbcch_req
   */
  ptr_prim->pb              = psc_db->pbcch.pbcch_des.pb;             /*<   Power reduction value          */
  ptr_prim->bs_pbcch_blks   = psc_db->pccch.bs_pbcch_blks;            /*<   Number of PBCCH per multiframe */
  ptr_prim->psi1_rep_period = psc_db->psi1_params.psi1_repeat_period; /*<   PSI1 repeat period             */
  ptr_prim->p_ch_des.tsc    = psc_db->pbcch.pbcch_des.tsc;            /*<  Training sequence code         */
  ptr_prim->p_ch_des.tn     = psc_db->pbcch.pbcch_des.tn;             /*<  timeslot number */

  if  (psc_db->pbcch.pbcch_des.v_arfcn 
        OR 
        (
          (psc_db->pbcch.pbcch_des.flag EQ 0)
          AND /* use bcch.arfcn*/
          (psc_db->pbcch.pbcch_des.flag2 EQ 0)
        )
       )
  {
    ptr_prim->p_ch_des.p_chan_sel.hopping       = 0;
    ptr_prim->p_ch_des.p_chan_sel.p_rf_ch.arfcn = (psc_db->pbcch.pbcch_des.v_arfcn )
                                                  ?grr_g23_arfcn_to_l1(psc_db->pbcch.pbcch_des.arfcn)
                                                  :grr_g23_arfcn_to_l1(psc_db->pbcch.bcch.arfcn);                      

    TRACE_EVENT_P8("Up_s: pbcch:%d per:%d hr:%d lr:%d pb:%d tsc:%d tn:%d arfcn:%d",
      psc_db->pccch.bs_pbcch_blks,
      psc_db->psi1_params.psi1_repeat_period,
      psc_db->psi1_params.psi_cnt_hr,
      psc_db->psi1_params.psi_cnt_lr,
      psc_db->pbcch.pbcch_des.pb,
      psc_db->pbcch.pbcch_des.tsc,
      psc_db->pbcch.pbcch_des.tn,
      ptr_prim->p_ch_des.p_chan_sel.p_rf_ch.arfcn);        
  }
  else
  {
    grr_create_freq_list(  MA_NUMBER_4_PSI13_OR_CELL_ALLOC,
                           psc_db->pbcch.pbcch_des.maio,
                          &ptr_prim->p_ch_des.p_chan_sel,
                          &ptr_prim->p_freq_list );

    TRACE_EVENT_P8("Up_h1: pbcch:%d per:%d hr:%d lr:%d pb:%d tsc:%d tn:%d maio:%d",
      psc_db->pccch.bs_pbcch_blks,
      psc_db->psi1_params.psi1_repeat_period,
      psc_db->psi1_params.psi_cnt_hr,
      psc_db->psi1_params.psi_cnt_lr,
      psc_db->pbcch.pbcch_des.pb,
      psc_db->pbcch.pbcch_des.tsc,
      psc_db->pbcch.pbcch_des.tn,
      psc_db->pbcch.pbcch_des.maio);



  }
} /* psi_update_data_to_request() */

/*
+------------------------------------------------------------------------------
| Function    : psi_is_access_class_changed
+------------------------------------------------------------------------------
| Description : This function checks the access class control parameter and
|               return TRUE/FALSE value
|
| Parameters  : void; return BOOL: TRUE: access class changed; FALSE: nothing has changed
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL psi_is_access_class_changed(void)
{
  USHORT dummy1, dummy2, access_changed;

  TRACE_FUNCTION("psi_is_access_class_changed");

  access_changed = FALSE;
  /* check the access control class and inform the service: CTRL
   * check access class control for authorized classes 0 to 9 and
   * check access class control for authorized classes 11 to 15 and
   */
  dummy1 = grr_data->ms.access_ctrl_class & 0x3FF;
  dummy2 = grr_data->ms.access_ctrl_class & 0xF800;

  if(
      ((dummy1 & ~psc_db->prach.ac_class) > 0) /* 0 to 9*/
      OR
      ((dummy2 & ~psc_db->prach.ac_class) > 0) /* 11 to 15*/
    )
  {
    /*
     * The MS belongs to one of the authorized access classes
     */
    if(psc_db->cell_info_for_gmm.access_status NEQ GPRS_ACCESS_ALLOWED)
    {
      /*
       * Access was NOT allowed, so we have to inform GMM
       */
      access_changed = TRUE;
      psc_db->cell_info_for_gmm.access_status = GPRS_ACCESS_ALLOWED;
    }
  }
  else
  {
    /*
     * Access barred
     */
    if(psc_db->cell_info_for_gmm.access_status NEQ GPRS_ACCESS_BARRED)
    {
      /*
       * Access was ALLOWED, so we have to inform GMM
       */
      access_changed = TRUE;
      psc_db->cell_info_for_gmm.access_status = GPRS_ACCESS_BARRED;
    }
  }

  if( access_changed )
  {
    TRACE_EVENT( "Access class changed" );

    grr_set_cell_info_service( );
  }

  return( access_changed );
}/* psi_is_access_class_changed*/

/*
+------------------------------------------------------------------------------
| Function    : psi_init_params
+------------------------------------------------------------------------------
| Description : The function psi_init_params() ....
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_init_params ( void )
{
#if defined (TI_PS_FF_RTD) AND defined (REL99)
  UBYTE n;
#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */

  TRACE_FUNCTION( "psi_init_params" );

  grr_data->psi.is_pbcch_req_needed =FALSE; /*PBCCH req. waiting for perform*/
  grr_data->psi.is_pbcch_req_allowed =TRUE; /*PBCCH req. allowed due to transition rules or not*/
#if defined (TI_PS_FF_RTD) AND defined (REL99)
  for( n = 0; n < MAX_NR_OF_NCELL; n++ )
        grr_data->psi.rtd[n] = RTD_NOT_AVAILABLE;
#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */

  psi_reset_all();

  psi_init_rfl_psi2(); /* set the Reference Frequency List parameters to initial values */
  psi_init_cell_alloc(); /* init cell allocation structure */
  psi_init_gprs_ms_alloc(FALSE); /* init GPRS Mobile Allocations struct */

} /* psi_init_params() */


/*
+------------------------------------------------------------------------------
| Function    : psi_stop_timer
+------------------------------------------------------------------------------
| Description : The function stops psi timers if they are running
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_stop_timer ( void )
{
  TRACE_FUNCTION( "psi_stop_timer" );
  
  vsi_t_stop(GRR_handle,T_10_SEC);

  vsi_t_stop(GRR_handle,T_30_SEC);

  vsi_t_stop(GRR_handle,T_60_SEC);
  
  vsi_t_stop(GRR_handle,T_COMP_PSI);
  
} /* psi_stop_timer() */

/*
+------------------------------------------------------------------------------
| Function    : psi_is_access_allowed
+------------------------------------------------------------------------------
| Description : The function checks whether the access to the network is allowed 
|               or not
|
| Parameters  : BOOL: TRUE if access allowed, otherwise FALSE
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL psi_is_access_allowed(void)
{
  TRACE_FUNCTION("psi_is_access_allowed");
  /* 
   * Check whether access is enabled or not: Access is allowed
   * if PSI acquisition is completed or PSI1&PSI2 was read with 
   * success AND psi status is suppoerted by the network
   */
#ifdef _SIMULATION_
  if(
     psc_db->psi1_params.psi_status_supported
      AND
     psc_db->complete_acq.psi1_ok 
      AND 
     psc_db->complete_acq.psi2_ok
    )
    return TRUE;
#endif /* #ifdef _SIMULATION_ */

  return FALSE;
}/*psi_is_access_allowed */

/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi2
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI2
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi2(void)
{
  TRACE_FUNCTION("psi_reread_psi2");

  psc_db->state_of_PSI[PSI2].state = NEEDED;
  psi_partial_acq();
  psi_reset_psi2();
  psi_start_10sec();
}/* psi_reread_psi2*/


/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi3_and_3bis
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI3 nad PSI3bis
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi3_and_3bis(void)
{
  TRACE_FUNCTION("psi_reread_psi3_and_3bis");

  psc_db->state_of_PSI[PSI3bis].state = NEEDED;
  psc_db->state_of_PSI[PSI3].state = NEEDED;
  psi_partial_acq();

  /*
   * Reset PSI3 and PSI3BIS paramter
   */
  psi_reset_psi3bis();
  psi_reset_psi3();
  psi_start_10sec();
}/* psi_reread_psi3_and_3bis*/


/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi3bis
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI3bis
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi3bis(void)
{
  TRACE_FUNCTION("psi_reread_psi3bis");

  /*
   * Message has changed, reset all values and read new consistent message set
   */
  psc_db->state_of_PSI[PSI3bis].state = NEEDED;
  psi_partial_acq();

  psi_reset_psi3bis();
  psi_start_10sec();
}/* psi_reread_psi3bis*/

#if defined (REL99) AND defined (TI_PS_FF_EMR)
/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi3ter
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI3ter
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi3ter(void)
{
  TRACE_FUNCTION("psi_reread_psi3ter");

  /*
   * Message has changed, reset all values and read new consistent message set
   */
  psc_db->state_of_PSI[PSI3ter].state = NEEDED;
  psi_partial_acq();

  psi_reset_psi3ter();
  psi_start_10sec();
}/* psi_reread_psi3ter*/

/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi3_3bis_3ter
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI3 to PSI3ter
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi3_3bis_3ter(void)
{
  TRACE_FUNCTION("psi_reread_psi3_3bis_3ter");

  if(psc_db->v_add_psi AND psc_db->add_psi.psi3ter_broadcast)
  {
    psc_db->state_of_PSI[PSI3ter].state = NEEDED;   
  }
  else
  {
    psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; 
  }

  psc_db->state_of_PSI[PSI3bis].state = NEEDED;
  psc_db->state_of_PSI[PSI3].state = NEEDED;
  psi_partial_acq();

  /*
   * Reset PSI3 to PSI3ter parameters
   */
  /* psi_reset_psi3quater(); */
  psi_reset_psi3ter();
  psi_reset_psi3bis();
  psi_reset_psi3();
  psi_start_10sec();
}/* psi_reread_psi3_3bis_3ter */

#endif


/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi4
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI4
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi4(void)
{
  TRACE_FUNCTION("psi_reread_psi4");

  psc_db->state_of_PSI[PSI4].state = NEEDED;
  psi_partial_acq();

  /*
   * Reset PSI4
   */
  psi_reset_psi4();
  psi_start_10sec();
}/* psi_reread_psi4*/

/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi5
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI5
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi5(void)
{
  TRACE_FUNCTION("psi_reread_psi5");

  psc_db->state_of_PSI[PSI5].state = NEEDED;
  psi_partial_acq();

  /*
   * Reset PSI5
   */
  psi_reset_psi5();
  psi_start_10sec();
}/* psi_reread_psi5*/

#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : psi_reread_psi8
+------------------------------------------------------------------------------
| Description : The function starts the reading process of PSI8
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_reread_psi8(void)
{
  TRACE_FUNCTION("psi_reread_psi8");

  psc_db->state_of_PSI[PSI8].state = NEEDED;
  psi_partial_acq();

  /*
   * Reset PSI8
   */
  psi_reset_psi8();
  psi_start_10sec();
}/* psi_reread_psi8*/
#endif

/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi1
+------------------------------------------------------------------------------
| Description : The function handles PSI1 message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_1*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi1(T_PSI_1 * psi1)
{
  TRACE_FUNCTION("psi_handle_psi1");
  switch(psi_process_psi1(psi1))
  {    
    case PSI1_PBCCH_RELEASED:
      SET_STATE( PSI, PSI_NULL );
      psi_initiate_pbcch_switching( PSI_DC_PBCCH_RELEASED );
      return; /* sorry: dirty solution */
    case PSI1_PBCCH_ESTABLISHED:
      SET_STATE( PSI, PSI_NULL );
      psi_initiate_pbcch_switching( PSI_DC_PBCCH_ESTABLISHED );
      return; /* sorry: another dirty solution */
    case PSI1_OK:
      if( psc_db->measurement_order EQ FALSE )
      {
        sig_psi_ctrl_meas_param_invalid_psi5( );
      }

      /* update readin parameters of psi */
      psi_update_data_to_request(INIT_NOT_NEEDED);
      /*
       * check the state of the acquisition
       */
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Check whether access to the network is allowed or not,
           * in case of having complete acq
           */
          if(psi_is_access_allowed() AND (psc_db->acq_type EQ COMPLETE))
          {
            psc_db->psi1_params.first_psi1 = FALSE;
            psi_stop_psi_reading(NONE);
            psi_stop_10sec(); /* Stop this timer, if running */
#ifdef _SIMULATION_
            vsi_t_stop(GRR_handle,T_COMP_PSI);
#endif
            /*
             * restart 30 sec:e.g. wait 30 sec for reread PSI1
             */
            psi_stop_30sec(TRUE);

            /* 
             * Access to the network is allowed
             */
            psi_send_access_enable_if_needed();            
          }
          else if(psi_is_access_allowed() AND (psc_db->acq_type EQ FULL_PSI_IN_NEW_CELL))
          {
            /*
             * Access to the new re-selected cell is allowed
             */
            psc_db->psi1_params.first_psi1 = FALSE;
            psi_stop_psi_reading(NONE);
            /*
             * restart 30 sec:e.g. wait 30 sec for reread PSI1
             */
            psi_stop_30sec(TRUE);
            sig_psi_ctrl_ncell_psi_read( TRUE);      
          }
          else
          {
            /*
             * Acq. is running, check whether we received the PSI1 message
             * for the first time or not.
             * if the PSI1 message is received for the first time, restart to read PBCCH blocks,
             * because of reading new parameters in PSI1 message,e.g. PCCCH parameters
             */
            if(
               psc_db->psi1_params.first_psi1 
                AND 
               ((psc_db->acq_type EQ COMPLETE) OR (psc_db->acq_type EQ FULL_PSI_IN_NEW_CELL))
              )
            {
              psi_stop_30sec(TRUE);/*restart 30 sec*/
              psi_receive_psi(READ_COMPLETE);
            }
          }
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
#ifdef _TARGET_
          TRACE_EVENT("PSI1->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
#if defined (REL99) AND defined (TI_PS_FF_EMR)
          psc_db->network_pg_mode = psi1->page_mode;
#endif
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_60sec(TRUE);/*restart 60 sec*/
          psi_stop_30sec(TRUE);/*restart 30 sec*/
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        case ACQ_PERIOD_OK:
          /*
           * Periodical pSI1 reading is O.K.
           */
          psi_stop_60sec(TRUE);/*restart 60 sec*/
          psi_stop_30sec(TRUE);/*restart 30 sec*/
          psi_stop_psi_reading(NONE);
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI1");
          break;
      }/* switch acq_state*/
      break;
    case PSI1_COMPLETE_ACQ:
      psi_initiate_read_complete_psi( INIT_NOT_NEEDED );
      break;
    case PSI1_PARTIAL_ACQ:
      /* update psi data*/
      psi_stop_60sec(TRUE);/*restart 60 sec*/
      psi_stop_30sec(TRUE);/*restart 30 sec*/
      psi_update_data_to_request( INIT_NOT_NEEDED);
      psi_partial_acq();
      /*TRACE_EVENT("Complete instead partial");
      psi_receive_psi(READ_COMPLETE);*/
      psc_db->send_psi_status = TRUE; /* this parameters has meaning if the network supports PSI STATUS */
      psi_start_10sec();
      break;
  }/* switch process_psi1*/
  if(psi_is_access_class_changed() AND !psc_db->psi1_params.first_psi1)
  {
    /*
     * Implies the CTRL to send CELL_IND
     */
    sig_psi_ctrl_access_changed();
  }
  if(psc_db->acq_type NEQ COMPLETE)
  {
    psc_db->psi1_params.first_psi1 = FALSE;
  }

}/* psi_handle_psi1*/

/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi2
+------------------------------------------------------------------------------
| Description : The function handles PSI2 message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_2*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi2(T_PSI_2 * psi2)
{
  TRACE_FUNCTION("psi_handle_psi2");
  switch(psi_process_psi2(psi2))
  {
    case PSI2_OK:
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Check whether access to the network is allowed or not,
           * in case of having complete acq
           */
          if(psi_is_access_allowed() AND (psc_db->acq_type EQ COMPLETE))
          {
            psi_stop_psi_reading(NONE);
            psi_stop_10sec(); /* Stop this timer, if running */
#ifdef _SIMULATION_
            vsi_t_stop(GRR_handle,T_COMP_PSI);
#endif
            /* 
             * Access to the network is allowed
             */
            psi_send_access_enable_if_needed();
          }
          else if(psi_is_access_allowed() AND (psc_db->acq_type EQ FULL_PSI_IN_NEW_CELL))
          {
            /*
             * Access to the new re-selected cell is allowed
             */
            psi_stop_psi_reading(NONE);
            sig_psi_ctrl_ncell_psi_read( TRUE );      
          }
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * TimeSlot number may have changed, so we have to restart PCCCH reading
           */
          TRACE_EVENT("PSI2->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
#if defined (REL99) AND defined (TI_PS_FF_EMR)
          psc_db->network_pg_mode = psi2->page_mode;
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI2");
          break;
      }/*switch check_acq*/
      break;
    case PSI2_REREAD:
      /* 
       * Error situation read a new PSI2
       */
      psi_reread_psi2();
      break;
  }
}/* psi_handle_psi2*/
/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi3
+------------------------------------------------------------------------------
| Description : The function handles PSI3 message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_3*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi3(T_PSI_3 * psi3)
{
  TRACE_FUNCTION("psi_handle_psi3");
  switch(psi_process_psi3(psi3))
  {
    case PSI3_NCELL_VALID:
      /*
       * Inform MEAS that the NCELL parameters are valid
       */
      sig_psi_ctrl_ncell_param_valid();
      
      /*lint -fallthrough*/
    
    case PSI3_OK:
      /*
       * check the acquisition state: it is only for having a complete set of information
       */
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Nothing to do
           */
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
#ifdef _TARGET_
          TRACE_EVENT("PSI3->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
#if defined (REL99) AND defined (TI_PS_FF_EMR)
          psc_db->network_pg_mode = psi3->page_mode;
#endif
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI3");
          break;
      }/*switch check_acq*/
      break;
    case PSI3_NCELL_INVALID:
      grr_init_nc_list( &psc_db->nc_cw.list );
      sig_psi_ctrl_ncell_param_invalid();
      break;
    case PSI3_CELL_BARRED:
      sig_psi_ctrl_access_barred();
      break;
  }/* switch psi_process_psi3*/
}/*psi_handle_psi3*/
/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi3bis
+------------------------------------------------------------------------------
| Description : The function handles PSI3_BIS message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_3_BIS*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi3bis(T_PSI_3_BIS * psi3bis)
{
  TRACE_FUNCTION("psi_handle_psi3bis");
  switch(psi_process_psi3bis(psi3bis))
  {
    case PSI3BIS_REREAD_PSI3BIS:
      psi_reread_psi3bis();
      /*
       * Ncell parameter are invalid. We have to inform MEAS-Service
       */
      grr_init_nc_list( &psc_db->nc_cw.list );
      sig_psi_ctrl_ncell_param_invalid();
      break;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    case PSI3BIS_REREAD_PSI3_3BIS_3TER:
      psi_reread_psi3_3bis_3ter();
#else
    case PSI3BIS_REREAD_PSI3_3BIS:
      psi_reread_psi3_and_3bis();
#endif
      /*
       * Ncell parameter are invalid. We have to inform MEAS-Service
       */
      grr_init_nc_list( &psc_db->nc_cw.list );
      sig_psi_ctrl_ncell_param_invalid();
      break;

    case PSI3BIS_NCELL_VALID:
      /*
       * Inform MEAS that the NCELL parameters are valid
       */
      sig_psi_ctrl_ncell_param_valid();
      
      /*lint -fallthrough*/
    
    case PSI3BIS_OK:
      /*
       * check the acquisition state: it is only for having a complete set of information
       */
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Nothing to do
           */
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
#ifdef _TARGET_
          TRACE_EVENT("PSI3bis->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
#if defined (REL99) AND defined (TI_PS_FF_EMR)
          psc_db->network_pg_mode = psi3bis->page_mode;
#endif
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI3bis");
          break;
      }/*switch check_acq*/
    break;
  }/* switch process_psi3bis*/

}/*psi_handle_psi3bis*/

#if defined (REL99) AND defined (TI_PS_FF_EMR)
/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi3ter
+------------------------------------------------------------------------------
| Description : The function handles PSI3_TER message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_3_TER*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi3ter(T_PSI_3_TER * psi3ter)
{
  TRACE_FUNCTION("psi_handle_psi3ter");
  switch(psi_process_psi3ter(psi3ter))
  {
    case PSI3TER_REREAD_PSI3TER:
      psi_reread_psi3ter();
      break;
    case PSI3TER_REREAD_PSI3_3BIS_3TER:
      psi_reread_psi3_3bis_3ter();
      break;
    case PSI3TER_OK:
      /*
       * check the acquisition state: it is only for having a complete set of information
       */
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Nothing to do
           */
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
#ifdef _TARGET_
          TRACE_EVENT("PSI3ter->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
          psc_db->network_pg_mode = psi3ter->page_mode;
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI3bis");
          break;
      }/*switch check_acq*/
    break;
  }/* switch process_psi3ter*/

}/*psi_handle_psi3ter*/

#endif



/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi4
+------------------------------------------------------------------------------
| Description : The function handles PSI4 message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_4*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi4(T_PSI_4 * psi4)
{
  TRACE_FUNCTION("psi_handle_psi4");
  switch(psi_process_psi4(psi4))
  {
    case PSI4_REREAD:
      psi_reread_psi4();
      /*
       * Interference channel list is invalid. We have to inform MEAS-Service
       */
      sig_psi_ctrl_int_list_invalid();
      break;
    case PSI4_INT_LIST_VALID:
      /*
       * Inform MEAS that the Interference parameters are valid
       */
      sig_psi_ctrl_int_list_valid();
      
      /*lint -fallthrough*/

    case PSI4_OK:
      /*
       * check the acquisition state: it is only for having a complete set of information
       */
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Nothing to do
           */
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
#ifdef _TARGET_
          TRACE_EVENT("PSI4->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
#if defined (REL99) AND defined (TI_PS_FF_EMR)
          psc_db->network_pg_mode = psi4->page_mode;
#endif
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI4");
          break;
      }/*switch check_acq*/
      break;
  }
}/* psi_handle_psi4*/

#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : psi_handle_psi8
+------------------------------------------------------------------------------
| Description : The function handles PSI8 message on both PBCCH and PACCH channels
|
| Parameters  : T_PSI_8*
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_handle_psi8(T_PSI_8 * psi8)
{
  TRACE_FUNCTION("psi_handle_psi8");
  switch(psi_process_psi8(psi8))
  {
    case PSI8_REREAD:
      psi_reread_psi8();
      break;
    case PSI8_OK:
      /*
       * check the acquisition state: it is only for having a complete set of information
       */
      switch(psi_check_acq_state())
      {
        case ACQ_RUNNING:
          /*
           * Nothing to do
           */
          break;
        case ACQ_PART_OK:
          psi_stop_psi_reading(NONE);
#ifdef _TARGET_
          TRACE_EVENT("PSI8->NEW_PCCCH");
          sig_psi_ctrl_new_pccch();
          psc_db->network_pg_mode = psi8->page_mode;
#endif
          break;
        case ACQ_COMP_OK:
          psi_stop_psi_reading(NONE);
          /* 
           * Access to the network is allowed
           */
          psi_send_access_enable_if_needed();
          break;
        default:
          TRACE_ERROR("Unexpected acq_ret in PSI8");
          break;
      }/*switch check_acq*/
      break;
  }
}/* psi_handle_psi8*/
#endif

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_si13_params
+------------------------------------------------------------------------------
| Description : The function copies si13 parameters into sc_db
|
| Parameters  : T_D_SYS_INFO_13*
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_copy_si13_params(T_D_SYS_INFO_13* si13)
{ 
  TRACE_FUNCTION("psi_copy_si13_params");

  /* 
   * Copy SI13_CHANGE_MARK and GPRS Mobile Allocation
   */
  if(si13->si13_rest_oct.si13_info.flag)
  {
    psc_db->psi13_params.si13_change_mark = si13->si13_rest_oct.si13_info.si13_cm;
    psi_copy_ma_from_psi13((T_gprs_ms_alloc_ie*)&(si13->si13_rest_oct.si13_info.gprs_ma));
  }
  
  grr_set_pbcch( si13->si13_rest_oct.si13_info.v_pbcch_des );

  if(si13->si13_rest_oct.si13_info.v_pbcch_des)
  {
    /*
     * PBCCH description present in the SI13 message
     */

    psc_db->psi1_params.psi1_repeat_period = si13->si13_rest_oct.si13_info.psi1_period + 1;
    /* pbcch description in database and in SI13 is different!!!*/
    psc_db->pbcch.pbcch_des.pb = si13->si13_rest_oct.si13_info.pbcch_des.pb;
    psc_db->pbcch.pbcch_des.tsc = si13->si13_rest_oct.si13_info.pbcch_des.tsc;
    psc_db->pbcch.pbcch_des.tn = si13->si13_rest_oct.si13_info.pbcch_des.tn;

    if((si13->si13_rest_oct.si13_info.pbcch_des.flag EQ FALSE) AND (si13->si13_rest_oct.si13_info.pbcch_des.flag2 EQ FALSE))
    {
      psc_db->pbcch.pbcch_des.flag = FALSE;
    }
    else
    {
      psc_db->pbcch.pbcch_des.flag = TRUE;
    }

    psc_db->pbcch.pbcch_des.v_arfcn = si13->si13_rest_oct.si13_info.pbcch_des.v_arfcn;
    psc_db->pbcch.pbcch_des.arfcn = si13->si13_rest_oct.si13_info.pbcch_des.arfcn;
    psc_db->pbcch.pbcch_des.v_maio = si13->si13_rest_oct.si13_info.pbcch_des.v_maio;
    psc_db->pbcch.pbcch_des.maio = si13->si13_rest_oct.si13_info.pbcch_des.maio;
  }
  else
  {
    /*
     * No PBCCH description present in the SI13 message
     */

    /*
     * Copy non PBCCH parameters: RAC, SPGC_CCCH_SUP, PRIORITY_ACCESS_THR,
     * NETWORK_CONTROL_ORDER
     */
    /* Set RAC value */
    psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = si13->si13_rest_oct.si13_info.rac;

    psc_db->net_ctrl.spgc_ccch_supp.nw_supp = si13->si13_rest_oct.si13_info.spgc;
    psc_db->net_ctrl.priority_access_thr = si13->si13_rest_oct.si13_info.prio_acc_thr;

    /*
     * Copy NC measurement parameter
     */ 
    {
      T_nc_meas_par nc_meas_par;

      nc_meas_par.ctrl_order = si13->si13_rest_oct.si13_info.nco;
      nc_meas_par.v_nc_meas_per       = FALSE;
      /*
       * SI13 doesnt carry the nc meas parameters. So we should not reset/change the 
       * parameters after receiving every SI13 periodic reading.
       */
      if( (nc_meas_par.ctrl_order EQ NCMEAS_NC2) OR (nc_meas_par.ctrl_order EQ NCMEAS_NC1) )
      {
        if ( (psc_db->nc_cw.param.rep_per_i NEQ NC_REP_PER_I_DEFAULT )  AND 
             (psc_db->nc_cw.param.rep_per_t NEQ NC_REP_PER_T_DEFAULT) AND 
               (psc_db->nc_cw.param.non_drx_per NEQ NC_NON_DRX_PER_DEFAULT) AND
               (psc_db->nc_cw.param.ctrl_order NEQ NC_NC0) AND 
               (psc_db->nc_cw.param.idx NEQ NOT_SET) )
        {
          nc_meas_par.nc_meas_per.non_drx_per = psc_db->nc_cw.param.non_drx_per;
          nc_meas_par.nc_meas_per.rep_per_i   = psc_db->nc_cw.param.rep_per_i ;
          nc_meas_par.nc_meas_per.rep_per_t   = psc_db->nc_cw.param.rep_per_t; 
          nc_meas_par.v_nc_meas_per = TRUE;
        }
      }

      /*
       * Only one instance of SI13, store data in final location.
       */
      grr_prcs_nc_param_struct ( &psc_db->nc_cw.param, &nc_meas_par, 0 );
    }

    /*
     * Copy GPRS cell options
     */
    psc_db->v_gprs_cell_opt = TRUE;
    /*
     * SZML-PSI/001
     */
    memcpy(&(psc_db->gprs_cell_opt), &(si13->si13_rest_oct.si13_info.gprs_cell_opt), sizeof(T_gprs_cell_opt));

    if(si13->si13_rest_oct.si13_info.gprs_cell_opt.nmo EQ GMMRR_NET_MODE_III)
    {
      TRACE_EVENT("NMO III in network ----> GMMRR_NET_MODE_II");
      psc_db->cell_info_for_gmm.cell_info.net_mode =  GMMRR_NET_MODE_II;
    }
    else
    {
      psc_db->cell_info_for_gmm.cell_info.net_mode = si13->si13_rest_oct.si13_info.gprs_cell_opt.nmo;
    }
    

    /*
     * Copy power control parameters
     */
    {
      T_si13_info *si13_info = &si13->si13_rest_oct.si13_info;

      psc_db->v_g_pwr_par = TRUE;

      psc_db->g_pwr_par.alpha           = CLIP_ALPHA( si13_info->alpha );
      psc_db->g_pwr_par.t_avg_w         = CLIP_T_AVG( si13_info->t_avg_w );
      psc_db->g_pwr_par.t_avg_t         = CLIP_T_AVG( si13_info->t_avg_t );
      psc_db->g_pwr_par.pb              = 0;
      psc_db->g_pwr_par.pc_meas_chan    = si13_info->pc_meas_chan;
      psc_db->g_pwr_par.imeas_chan_list = FALSE;
      psc_db->g_pwr_par.n_avg_i         = si13_info->n_avg_i;

      grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE;
    }
  }
}/* psi_copy_si13_params */



/*
+------------------------------------------------------------------------------
| Function    : psi_is_pbcch_des_different
+------------------------------------------------------------------------------
| Description : The function checks whether PBCCH description of the received 
|               PSI13 message is different from the stored one
|
| Parameters  : T_PSI_13*; TRUE: If desc. are different FALSE: same
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL psi_is_pbcch_des_different(T_PSI_13* psi13)
{
  TRACE_FUNCTION("psi_is_pbcch_des_different");
  if(!psi13->flag) /* No PBCCH description present: PBCCH no longer available*/
    return TRUE;

  /* compare PBCCH descriptions*/
  if((psc_db->pbcch.pbcch_des.pb EQ psi13->psi1_pbcch_info.pbcch_des.pb) AND
     (psc_db->pbcch.pbcch_des.tsc EQ psi13->psi1_pbcch_info.pbcch_des.tsc) AND
     (psc_db->pbcch.pbcch_des.tn EQ psi13->psi1_pbcch_info.pbcch_des.tn))
  {
    /* compare BCCH carrier-flag, if exists*/
    if(psc_db->pbcch.pbcch_des.flag NEQ psi13->psi1_pbcch_info.pbcch_des.flag)
      return TRUE;

    /* compare non-hopping carrier, if exists: ARFCN*/
    if(
      (psc_db->pbcch.pbcch_des.v_arfcn NEQ psi13->psi1_pbcch_info.pbcch_des.v_arfcn) 
       OR
      (psc_db->pbcch.pbcch_des.arfcn NEQ psi13->psi1_pbcch_info.pbcch_des.arfcn)
      )
        return TRUE;

    /* Compare hopping carrier, if exists: MAIO*/
    if(
      (psc_db->pbcch.pbcch_des.v_maio NEQ psi13->psi1_pbcch_info.pbcch_des.v_maio) 
       OR
      (psc_db->pbcch.pbcch_des.maio NEQ psi13->psi1_pbcch_info.pbcch_des.maio)
      )
        return TRUE;
  }
  else
  {
    return TRUE;
  }
  return FALSE;
}/* psi_is_pbcch_des_different*/

/*
+------------------------------------------------------------------------------
| Function    : psi_copy_psi13_params
+------------------------------------------------------------------------------
| Description : The function copies psi13 parameters into sc_db
|
| Parameters  : T_PSI_13*
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_copy_psi13_params(T_PSI_13* psi13)
{
  TRACE_FUNCTION("psi_copy_psi13_params");

  /* 
   * Handle SI13_CHANGE_MARK and GPRS Mobile Allocation
   */
  if(psi13->v_si13_cm_gprs_alloc)
  {
    psc_db->psi13_params.si13_change_mark = psi13->si13_cm_gprs_alloc.si13_cm;
    psi_copy_ma_from_psi13(&(psi13->si13_cm_gprs_alloc.gprs_ms_alloc_ie));
  }

  grr_set_pbcch( psi13->flag );

  if(psi13->flag)
  { 
    /*
     * PBCCH description present in the PSI13 message
     */

    psc_db->psi1_params.psi1_repeat_period = psi13->psi1_pbcch_info.psi1_rep_per + 1;
    memcpy(&(psc_db->pbcch.pbcch_des), &(psi13->psi1_pbcch_info.pbcch_des), sizeof(T_pbcch_des));
  }
  else
  { 
    /* 
     * No PBCCH description present in the PSI13 message
     */

    /*
     * Copy non PBCCH parameters: RAC, SPGC_CCCH_SUP, PRIORITY_ACCESS_THR
     */
    /* Set RAC value */
    psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = psi13->pbcch_n_pres.rac;

    psc_db->net_ctrl.spgc_ccch_supp.nw_supp = psi13->pbcch_n_pres.spgc_ccch_sup;
    psc_db->net_ctrl.priority_access_thr = psi13->pbcch_n_pres.prio_acc_thr;

    /*
     * Copy NC measurement parameter
     */ 
    {
      T_nc_meas_par nc_meas_par;

      nc_meas_par.ctrl_order = psi13->pbcch_n_pres.ctrl_order;
      nc_meas_par.v_nc_meas_per       = FALSE;

      /*
       * Only one instance of PSI13, store data in final location.
       */
      grr_prcs_nc_param_struct ( &psc_db->nc_cw.param, &nc_meas_par, 0 );
    }

    /*
     * Copy GPRS cell options
     */
    psc_db->v_gprs_cell_opt = TRUE;
    /*
     * SZML-PSI/002
     */
    memcpy(&(psc_db->gprs_cell_opt), &(psi13->pbcch_n_pres.gprs_cell_opt), sizeof(T_gprs_cell_opt));
    psc_db->cell_info_for_gmm.cell_info.net_mode = psi13->pbcch_n_pres.gprs_cell_opt.nmo;
  
    /* 
     * Copy power control parameters
     */
    {
      T_psi13_pwr_par *pwr_par = &psi13->pbcch_n_pres.psi13_pwr_par;

      psc_db->v_g_pwr_par = TRUE;
    
      psc_db->g_pwr_par.alpha           = CLIP_ALPHA( pwr_par->alpha);
      psc_db->g_pwr_par.t_avg_w         = CLIP_T_AVG( pwr_par->t_avg_w );
      psc_db->g_pwr_par.t_avg_t         = CLIP_T_AVG( pwr_par->t_avg_t );
      psc_db->g_pwr_par.pb              = 0;
      psc_db->g_pwr_par.pc_meas_chan    = pwr_par->pc_meas_chan;
      psc_db->g_pwr_par.imeas_chan_list = FALSE;
      psc_db->g_pwr_par.n_avg_i         = pwr_par->n_avg_i;

      grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE;
    }
  }
} /* psi_copy_psi13_params */

/*
+------------------------------------------------------------------------------
| Function    : psi_send_access_enable_if_needed
+------------------------------------------------------------------------------
| Description : The function sends signal to CTRL to indicate that the access 
|               is enabled
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_send_access_enable_if_needed()
{
  TRACE_FUNCTION("psi_send_access_enable_if_needed");

  if(!psc_db->is_access_enabled)
  {
    psc_db->is_access_enabled = TRUE;

    sig_psi_ctrl_access_enabled( );
  }
#ifdef _TARGET_
  else if(grr_is_pbcch_present())
  {
    /*
     * Inform CTRL about new pccch, if there is a new one exists. 
     * It may be the PBCCH and/or PCCCH description has been
     * changed, so that PCCCH reading should be started again.
     * If not this is not a big problem. This is done to avoid 
     * saving PCCCH description in database to compare whether
     * it has been changed or not.
     */
    TRACE_EVENT("Access enabled, PCCCH may have changed");
    sig_psi_ctrl_new_pccch();
  }
#endif /* _TARGET_ */

#ifdef REL99
  TRACE_EVENT_P2 ("pbbch %d, cbch_info %d", grr_is_pbcch_present(), psc_db->send_cbch_info_ind);
  if(grr_is_pbcch_present() AND psc_db->send_cbch_info_ind)
  {
    sig_psi_ctrl_cbch_info_ind();
    psc_db->send_cbch_info_ind = FALSE;
  }
#endif

}/*psi_send_access_enable_if_needed */

/*
+------------------------------------------------------------------------------
| Function    : psi_initiate_read_complete_si
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_initiate_read_complete_si ( void )
{
  TRACE_FUNCTION( "psi_initiate_read_complete_si" );

  psi_stop_60sec( TRUE );
  psi_stop_30sec( TRUE );
  sig_psi_ctrl_access_disabled( PSI_DC_OTHER );

} /* psi_initiate_read_complete_si */

/*
+------------------------------------------------------------------------------
| Function    : psi_initiate_read_complete_psi
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_initiate_read_complete_psi ( UBYTE init_needed )
{
  TRACE_FUNCTION( "psi_initiate_read_complete_psi" );

  TRACE_EVENT( "PBCCH present" );

  psi_stop_60sec( TRUE );
  psi_stop_30sec( TRUE );
  psi_update_data_to_request( init_needed );
  sig_psi_ctrl_access_disabled( PSI_DC_READ_PSI );

} /* psi_initiate_read_complete_psi */

/*
+------------------------------------------------------------------------------
| Function    : psi_initiate_pbcch_switching
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_initiate_pbcch_switching ( T_PSI_DISABLE_CAUSE dc )
{
  TRACE_FUNCTION( "psi_initiate_pbcch_switching" );

  if( psc_db->acq_type NEQ NONE )
  {
    psi_stop_psi_reading(NONE);
  }

  sig_psi_ctrl_access_disabled( dc );
  psi_stop_timer();
  psi_init_params();      
  grr_set_pbcch( FALSE );

} /* psi_initiate_pbcch_switching */

/*
+------------------------------------------------------------------------------
| Function    : psi_store_ncell_param
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
LOCAL UBYTE psi_store_ncell_param ( T_ncell_par *p_ncell_par, 
                                    UBYTE        c_ncell_par,
                                    UBYTE        v_ncell_par,
                                    T_INFO_TYPE  type,
                                    UBYTE        instance )
{
  UBYTE  i, j;
  UBYTE  number    = 0;
  USHORT last_freq;

  TRACE_FUNCTION( "psi_store_ncell_param" );

  if( !v_ncell_par )
  {
    switch ( type )
    {
      case( INFO_TYPE_PSI3 ):
        TRACE_EVENT( "No ncell parameters in PSI3" );                  
        break;
      
      case( INFO_TYPE_PSI3BIS ): 
        TRACE_EVENT( "No ncell parameters in PSI3BIS" );               
        break;
      
      default:
        TRACE_EVENT( "Unexpected neighbour cell information source" ); 
        break;
    }

    return( number ); /* no ncell parameters */
  }

  switch ( type )
  {
    case( INFO_TYPE_PSI3 ):
    case( INFO_TYPE_PSI3BIS ): 
      break;
      
    default:
      TRACE_EVENT( "Unexpected neighbour cell information source" ); 
      return( number );
  }

  for( i = 0; i < c_ncell_par; i++ )
  {
    last_freq = 0;

    if( grr_store_cs_param
          ( &psc_db->nc_cw.list,
            TRUE,
            &p_ncell_par[i].cs_par,
            type,
            instance,
            &number,
            &last_freq,
            p_ncell_par[i].start_freq,
            p_ncell_par[i].bsic ) EQ FALSE )
    {
      TRACE_EVENT( "psi_store_ncell_param: NC_CW list full" );

      return( number );
    }

    for( j = 0; j < p_ncell_par[i].n_rest; j++ )
    {
      if( grr_store_cs_param
            ( &psc_db->nc_cw.list,
              TRUE,
              &p_ncell_par[i].ncell_par_rest[j].cs_par,
              type,
              instance,
              &number, 
              &last_freq,
              p_ncell_par[i].ncell_par_rest[j].freq_diff_struct.freq_diff,
              p_ncell_par[i].ncell_par_rest[j].bsic ) EQ FALSE )
      {
        TRACE_EVENT( "psi_store_ncell_param: NC_CW list full" );

        return( number );
      }
    }
  }

  return( number );
}/* psi_store_ncell_param */

/*
+------------------------------------------------------------------------------
| Function    : psi_store_ncell_param2
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
LOCAL void psi_store_ncell_param2 ( T_PSI_3_BIS *psi3bis, UBYTE number )
{
  T_ncell_par2_s1 *p_sub_1;
  T_ncell_par2_s2 *p_sub_2;
 
  USHORT last_freq;
  UBYTE  i, j, cell_params_ptr, x, y, n;
  
  TRACE_FUNCTION( "psi_store_ncell_param2" );

  if( !psi3bis->ncell_par_trnc_grp.v_ncell_par2 )
  {
    return;
  }

  for( i = 0;
       i < psi3bis->ncell_par_trnc_grp.c_ncell_par2;
       i++ )
  {
    for( n = 0;
         n < psi3bis->ncell_par_trnc_grp.ncell_par2[i].c_ncell_par2_des;
         n++ )
    {
      cell_params_ptr = psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_des[n].para_ptr;

      if( cell_params_ptr > psi3bis->ncell_par_trnc_grp.ncell_par2[i].c_ncell_par2_set )
      {
        TRACE_ERROR( "cell_params_ptr > psi3bis->ncell_par2[i].c_ncell_par2_set" );

        return;
      }

      for( j = 0; 
           j < psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_des[n].c_ncell_par2_s1;
           j++ )
      {
        last_freq = 0;
        p_sub_1   = &psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_des[n].ncell_par2_s1[j];

        if( psi_store_cs_param2
              ( &psc_db->nc_cw.list, 
                &psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_set[cell_params_ptr],
                psi3bis->psi3bis_ind, 
                &number,
                &last_freq,
                p_sub_1->start_freq,
                p_sub_1->same_ra_scell,
                p_sub_1->cell_ba,
                p_sub_1->bcc ) EQ FALSE )
        {
          TRACE_EVENT( "psi_store_ncell_param2: NC_CW list full" );
  
          return;
        }

        if( p_sub_1->n_r_cells NEQ 0 )
        {
          y = p_sub_1->c_ncell_par2_s2;

          for( x = 0; x < y; x++ )
          {
            p_sub_2 = &p_sub_1->ncell_par2_s2[x];

            if( psi_store_cs_param2
                  ( &psc_db->nc_cw.list, 
                    &psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_set[cell_params_ptr],
                    psi3bis->psi3bis_ind,
                    &number,
                    &last_freq,
                    p_sub_2->freq_diff_struct.freq_diff,
                    p_sub_2->same_ra_scell,
                    p_sub_2->cell_ba,
                    p_sub_2->bcc ) EQ FALSE )
            {
              TRACE_EVENT( "psi_store_ncell_param2: NC_CW list full" );
  
              return;
            }
          }
        }
      }
    }
  }
} /* psi_store_ncell_param2 */

/*
+------------------------------------------------------------------------------
| Function    : psi_store_cs_param2
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
LOCAL BOOL psi_store_cs_param2 ( T_NC_LIST        *nc_list,
                                 T_ncell_par2_set *cs_par2,
                                 UBYTE             instance,
                                 UBYTE            *number,
                                 USHORT           *freq,
                                 USHORT            freq_diff,
                                 UBYTE             same_ra_scell,
                                 UBYTE             cell_ba,
                                 UBYTE             bcc )
{
  T_INFO_SRC    info_src = 0;
  T_ncell_info *ncell_info;

  TRACE_FUNCTION( "psi_store_cs_param2" );

  NC_SET_TYPE    ( info_src, INFO_TYPE_PSI3BIS );
  NC_SET_INSTANCE( info_src, instance          );
  NC_SET_NUMBER  ( info_src, *number           );

  ncell_info = grr_get_next_ncell_param( MAX_NR_OF_NCELL,
                                         nc_list,
                                         info_src );

  if( ncell_info EQ NULL )
  {
    return( FALSE );
  }

  number++;
  nc_list->number++;

  *freq = ( *freq + freq_diff ) % 1024;

  ncell_info->info_src = info_src;
  ncell_info->arfcn    = *freq;

  if( cs_par2->v_ncc )
  {
    ncell_info->bsic = bcc | ( cs_par2->ncc << 3 );
  }
  else
  {
    ncell_info->bsic = bcc | ( psc_db->pbcch.bcch.bsic & BSIC_NCC_MASK );
  }

  ncell_info->v_cr_par             = TRUE;
  ncell_info->cr_par.same_ra_scell = same_ra_scell;
  ncell_info->cr_par.exc_acc       = cs_par2->exc_acc;
  ncell_info->cr_par.cell_ba       = cell_ba;

#if !defined (NTRACE)
  if( grr_data->cs.v_crp_trace EQ TRUE )
  {
    TRACE_EVENT_P2( "psi_store_cs_param2: cell barred status %d %d",
                    ncell_info->arfcn, ncell_info->cr_par.cell_ba );
  }
#endif /* #if !defined (NTRACE) */



  SET_GPRS_RXLEV_ACCESS_MIN
    ( ncell_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min,
      cs_par2->v_gprs_rxlev_access_min, cs_par2->gprs_rxlev_access_min );

  SET_GPRS_MS_TXPWR_MAX_CCH
    ( ncell_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch,
      cs_par2->v_txpwr_max_cch, cs_par2->txpwr_max_cch );
      
  SET_GPRS_TEMP_OFFSET
    ( ncell_info->cr_par.cr_offset.gprs_temp_offset,
      TRUE, cs_par2->gprs_temp_offset );

  SET_GPRS_PENALTY_TIME
    ( ncell_info->cr_par.cr_offset.gprs_penalty_time,
      TRUE, cs_par2->gprs_penalty_time );

  SET_GPRS_RESEL_OFF
    ( ncell_info->cr_par.gprs_resel_off,
      TRUE, cs_par2->gprs_resel_off );

  ncell_info->cr_par.cr_par_1.v_hcs_par = 
    ( cs_par2->v_gprs_hcs_thr AND cs_par2->v_gprs_prio_class );

  SET_GPRS_HCS_THR
    ( ncell_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr,
      cs_par2->v_gprs_hcs_thr, cs_par2->gprs_hcs_thr );

  SET_GPRS_PRIO_CLASS
    ( ncell_info->cr_par.cr_par_1.hcs_par.gprs_prio_class,
      cs_par2->v_gprs_prio_class, cs_par2->gprs_prio_class );

  grr_store_si13_pbcch_location( &ncell_info->cr_par,
                                 cs_par2->v_si13_pbcch,
                                 &cs_par2->si13_pbcch );

  return( TRUE );

}/* psi_store_cs_param2 */

/*
+------------------------------------------------------------------------------
| Function    : psi_restore_ncell_param
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
LOCAL void psi_restore_ncell_param ( void )
{
  UBYTE         idx_curr   = 0;
  T_ncell_info *info_prev  = NULL;
  T_ncell_info *info_curr;
  T_INFO_SRC    info_src   = 0;
  
  TRACE_FUNCTION( "psi_restore_ncell_param" );

  /* update change mark value */
  psc_db->nc_cw.list.chng_mrk.curr++;

  while( ( info_curr = grr_get_next_bigger_ncell_param
                                 ( &psc_db->nc_cw.list, info_src ) ) NEQ NULL )
  {
    grr_restore_cs_param( info_curr, info_prev, idx_curr );

    info_src  = info_curr->info_src;
    info_prev = info_curr;
    
    idx_curr++;
  }
}/* psi_restore_ncell_param */


/*
+------------------------------------------------------------------------------
| Function    : psi_prepare_scell_pbcch_req
+------------------------------------------------------------------------------
| Description : The function psi_prepare_scell_pbcch_req() prepares the mphp_
|               scell_pbcch_req
|
| Parameters  : T_MPHP_SCELL_PBCCH_REQ *mphp_scell_pbcch_req
|                                        UBYTE  psi_reading_type
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_prepare_scell_pbcch_req(T_MPHP_SCELL_PBCCH_REQ *mphp_scell_pbcch_req, 
                                        UBYTE  psi_reading_type)
{ 
#ifndef _TARGET_

  UBYTE i, j;

#endif /* #ifndef _TARGET_ */

  UBYTE hr, lr, *psi_nr;
  UBYTE *pos_array;
  
  TRACE_FUNCTION( "psi_prepare_scell_pbcch_req" );


  memcpy(mphp_scell_pbcch_req,&psc_db->scell_pbcch,sizeof(T_MPHP_SCELL_PBCCH_REQ));

  psi_nr = &mphp_scell_pbcch_req->psi_nr;
  pos_array = mphp_scell_pbcch_req->relative_pos_array;

  *psi_nr = 0;
  memset(pos_array, 0, MAX_RELATIVE_POS);

  hr = psc_db->psi1_params.psi_cnt_hr;
  lr = psc_db->psi1_params.psi_cnt_lr;


  TRACE_EVENT_P1("psi_reading_type:%d", psi_reading_type);

  switch(psi_reading_type)
  {
    case READ_COMPLETE: 
      /* attempt to receive messages shall be made each time 
       * the message is scheduled on the broadcast channel.
       */
      mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/
      /*
       * mphp_scell_pbcch_req->relative_pos_array has no meaning, 
       * if we want to receive all PSI
       */
      psi_reset_psi_pos();
      break;
    case READ_PSI1_IN_PSI1_REPEAT_PERIODS:
      /* attempt to receive PSI1 each time 
       * the message is scheduled on the broadcast channel 
       * with psi1_repeat_periods (only once in a multiframe, e.g. in PBCCH->B0)
       */

      /* mphp_scell_pbcch_req->relative_pos_array will contain only one element,
       * because of mphp_scell_pbcch_req.psi_nr = 1
       */        
      mphp_scell_pbcch_req->psi_nr = 1;
      
      /*Read PSI1 only in BO in psi1 repeat period
       */
      mphp_scell_pbcch_req->relative_pos_array[0] = 0; 
      break;
    case PSI_IN_HR: /* PSI in high repetition rate*/
      if(!hr) /* no HR */
      {
        TRACE_ERROR("no HR, read all");
        mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/
      }
      else
      {
#ifdef _TARGET_
        mphp_scell_pbcch_req->psi_nr = 0;
#else
        mphp_scell_pbcch_req->psi_nr = 0;
        i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0;

        while(hr > 0)
        {
          mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr;
          if(mphp_scell_pbcch_req->psi_nr EQ 19)
            break;/* break condition*/
          mphp_scell_pbcch_req->psi_nr++;
          hr--;
        }
#endif
      }
      break;
    case PSI_IN_LR:  /* PSI in low repetition rate */
      if(!lr) /* no LR */
      {
        TRACE_ERROR("no LR, read all");
        mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/
      }
      else
      {
#ifdef _TARGET_
        mphp_scell_pbcch_req->psi_nr = 0;
#else
        mphp_scell_pbcch_req->psi_nr = 0;
        i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0;

        while(lr > 0)
        {
          mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr + lr;
          if(mphp_scell_pbcch_req->psi_nr EQ 19)
            break;/* break condition*/
          mphp_scell_pbcch_req->psi_nr++;
          lr--;
        }
#endif
      }
      break;
    case PSI_IN_HR_AND_LR:   /* PSI in high and low repetition rate*/
      if(!(lr + hr)) /* no LR+HR */
      {
        TRACE_ERROR("no HR+LR, read all");
        mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/
      }
      else
      {
#ifdef _TARGET_
        mphp_scell_pbcch_req->psi_nr = 0;
#else
        mphp_scell_pbcch_req->psi_nr = 0;
        i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 2 : 1;
        for(j=0; j<(lr + hr);j++)
        {
          mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + j;
          if(mphp_scell_pbcch_req->psi_nr EQ 19)
            break;/* break condition*/
          mphp_scell_pbcch_req->psi_nr++;        
        }
#endif
      }
      break;
    case   READ_PSI1_AND_IN_HR:
      /* PSI in high repetition rate and PSI1*/
#ifdef _TARGET_
      mphp_scell_pbcch_req->psi_nr = 0;
#else
      mphp_scell_pbcch_req->psi_nr = 0;
      mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 0;
      i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0;
      if(i EQ 1)
      {
        mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 1;        
      }

      while(hr > 0)
      {
        mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr;
        if(mphp_scell_pbcch_req->psi_nr EQ 19)
          break;/* break condition*/
        mphp_scell_pbcch_req->psi_nr++;
        hr--;
      }
#endif
      break;
    case   READ_PSI1_AND_IN_LR:/* PSI in low repetition rate and PSI1*/
#ifdef _TARGET_
        mphp_scell_pbcch_req->psi_nr = 0;
#else
      mphp_scell_pbcch_req->psi_nr = 0;
      mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 0;
      i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0;
      if(i EQ 1)
      {
        mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 1;        
      }
      
      while(lr > 0)
      {
        mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr + lr;
        if(mphp_scell_pbcch_req->psi_nr EQ 19)
          break;/* break condition*/
        mphp_scell_pbcch_req->psi_nr++;
        lr--;
      }
#endif
      break;
    case  READ_PSI2:
#ifdef _TARGET_
      mphp_scell_pbcch_req->psi_nr = 0;
#else
      psi_fill_rel_pos(grr_data->psi.psi2_pos, MAX_NR_OF_INSTANCES_OF_PSI2, psi_nr, pos_array);
#endif
      break;
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    case  READ_PSI3TER:
    case  READ_PSI3_3BIS_3TER:
#endif
    case  READ_PSI3_3BIS:
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    case  READ_PSI3BIS:
#endif
#ifdef _TARGET_
      mphp_scell_pbcch_req->psi_nr = 0;
#else
#if defined (REL99) AND defined (TI_PS_FF_EMR)
      psi_fill_rel_pos(grr_data->psi.psi3_set_pos, 
      MAX_NR_OF_INSTANCES_OF_PSI3TER + MAX_NR_OF_INSTANCES_OF_PSI3 + 
      MAX_NR_OF_INSTANCES_OF_PSI3BIS, psi_nr, pos_array);
#else
      psi_fill_rel_pos(grr_data->psi.psi3bis_pos, 
      MAX_NR_OF_INSTANCES_OF_PSI3 + MAX_NR_OF_INSTANCES_OF_PSI3BIS, 
      psi_nr, pos_array);
#endif /* #ifdef REL99 AND TI_PS_FF_EMR */
#endif /* ifdef _TARGET_ */
      break;
    case  READ_PSI4:
#ifdef _TARGET_
      mphp_scell_pbcch_req->psi_nr = 0;
#else
      psi_fill_rel_pos(grr_data->psi.psi4_pos, MAX_NR_OF_INSTANCES_OF_PSI4, psi_nr, pos_array);
#endif
      break;
    case  READ_PSI5:
#ifdef _TARGET_
      mphp_scell_pbcch_req->psi_nr = 0;
#else
      psi_fill_rel_pos(grr_data->psi.psi5_pos, MAX_NR_OF_INSTANCES_OF_PSI5, psi_nr, pos_array);
#endif
      break;
#ifdef REL99
    case  READ_PSI8:
#ifdef _TARGET_
      mphp_scell_pbcch_req->psi_nr = 0;
#else
      psi_fill_rel_pos(grr_data->psi.psi8_pos, MAX_NR_OF_INSTANCES_OF_PSI8, psi_nr, pos_array);
#endif
      break;
#endif
    default:
      TRACE_ERROR ("default in psi_prepare_scell_pbcch_req");
      break;
  }
  TRACE_EVENT_P7("psi_nr:%d blks:%d pb:%d per:%d pos[0]:%d pos[1]:%d pos[2]:%d",
          mphp_scell_pbcch_req->psi_nr,
          mphp_scell_pbcch_req->bs_pbcch_blks,
          mphp_scell_pbcch_req->pb,    
          mphp_scell_pbcch_req->psi1_rep_period,
          mphp_scell_pbcch_req->relative_pos_array[0],
          mphp_scell_pbcch_req->relative_pos_array[1],
          mphp_scell_pbcch_req->relative_pos_array[2]);  
  TRACE_EVENT_P4("tn:%d tsc:%d hop:%d arfcn:%d",
          mphp_scell_pbcch_req->p_ch_des.tn,
          mphp_scell_pbcch_req->p_ch_des.tsc,
          mphp_scell_pbcch_req->p_ch_des.p_chan_sel.hopping,
          mphp_scell_pbcch_req->p_ch_des.p_chan_sel.p_rf_ch.arfcn);
  TRACE_EVENT_P5("f_cnt:%d f1:%d f2:%d f3:%d f4:%d",
          mphp_scell_pbcch_req->p_freq_list.p_rf_chan_cnt,
          mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[0],
          mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[1],
          mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[2],
          mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[3]);    




} /* psi_prepare_scell_pbcch_req */


/*
+------------------------------------------------------------------------------
| Function    : psi_store_rel_pos 
+------------------------------------------------------------------------------
| Description : The function psi_store_rel_pos () .stores the values relative
|               position for each PSI message
| Parameters  : dest: destination array; rel_pos: relative position; max_dest:
|               MAX size OF dest array
|
+------------------------------------------------------------------------------
*/
GLOBAL void psi_store_rel_pos(UBYTE *dest, UBYTE rel_pos, UBYTE max_dest)
{
  UBYTE i;
  TRACE_FUNCTION("psi_store_rel_pos");
  
  for ( i = 0; i < max_dest; i++)
  {
    if(dest[i] EQ 0xFF)
    {
      dest[i] = rel_pos;
      break;
    }
  }

}/*psi_store_rel_pos*/

#ifndef _TARGET_
/*
+------------------------------------------------------------------------------
| Function    : psi_fill_rel_pos 
+------------------------------------------------------------------------------
| Description : The function psi_fill_rel_pos () .fills the relative position
|               array and sets the psi_number
| Parameters  : src: array containing rel positions; max_src: MAX size of src
|               psi_nr: ptr to psi_number; pos_array: ptr to position_array
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_fill_rel_pos(UBYTE *src, UBYTE max_src, UBYTE *psi_nr, UBYTE *pos_array) 
{
  UBYTE i;
  TRACE_FUNCTION("psi_fill_rel_pos");

  for(i = 0; i<max_src; i++)
  {
    if(src[i] NEQ 0xff)
    {
      pos_array[(*psi_nr)] = src[i];
      (*psi_nr)++;
    }
  }
}/*psi_fill_rel_pos*/
#endif /*_TARGET_*/

/*
+------------------------------------------------------------------------------
| Function    : psi_reset_psi_pos 
+------------------------------------------------------------------------------
| Description : The function spsi_reset_psi_pos () .... 
|
| Parameters  : -
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_reset_psi_pos  ( void )
{ 
  TRACE_FUNCTION( "psi_reset_psi_pos " );
  
  memset(grr_data->psi.psi2_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI2);

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  memset(grr_data->psi.psi3_set_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI3TER
    +MAX_NR_OF_INSTANCES_OF_PSI3BIS+MAX_NR_OF_INSTANCES_OF_PSI3);
#else
  memset(grr_data->psi.psi3bis_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI3BIS+MAX_NR_OF_INSTANCES_OF_PSI3);
#endif

  memset(grr_data->psi.psi4_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI4);
  memset(grr_data->psi.psi5_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI5);
#ifdef REL99
  memset(grr_data->psi.psi8_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI8);
#endif

} /* psi_reset_psi_pos () */


#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : psi_update_bss_sgsn_rel 
+------------------------------------------------------------------------------
| Description : The function psi_update_bss_sgsn_rel () updates BSS and SGSN
|               releases during the processing of SI13 message.
|
| Parameters  : SI13 message, status of PBCCH presence in the cell
|
+------------------------------------------------------------------------------
*/
LOCAL void psi_update_bss_sgsn_rel  ( T_D_SYS_INFO_13  *si13, 
                                      BOOL              pbcch_status )
{ 
  TRACE_FUNCTION( "psi_update_bss_sgsn_rel " );

  /* Update the BSS release */  
  if (si13->si13_rest_oct.si13_info.v_sgsnr)
  {
    psc_db->network_rel = BSS_NW_REL_99;
    psc_db->sgsn_rel = 
      si13->si13_rest_oct.si13_info.sgsnr ? PS_SGSN_99_ONWARDS : PS_SGSN_98_OLDER;
  }
  else
  {
    psc_db->network_rel = BSS_NW_REL_97;
    
    if(pbcch_status EQ PBCCH_NOT_PRESENT)
    {
      psc_db->sgsn_rel = PS_SGSN_98_OLDER;
    }
    else
    {
      psc_db->sgsn_rel = PS_SGSN_UNKNOWN;
    }

  }

  /* Update the SGSN release in the Common library context */
  cl_nwrl_set_sgsn_release(psc_db->sgsn_rel);

  
} /* psi_update_bss_sgsn_rel () */

#endif