view src/g23m-gprs/grr/grr_psif.c @ 555:6690ae453594

configs: hybrid-gpf renamed to hybrid-osl
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 19 Nov 2018 00:16:07 +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