view src/g23m-gprs/grlc/grlc_gfff.c @ 310:8488a9ae583c

doc/Compiling: added note that if wine doesn't whine, make nowhine a symlink
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 03 Nov 2017 20:43:47 +0000
parents 219afcfc6250
children
line wrap: on
line source

/*  
+----------------------------------------------------------------------------- 
|  Project :  GPRS (8441)
|  Modul   :  GRLC
+----------------------------------------------------------------------------- 
|  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 GFF of
|             entity GRLC.
+----------------------------------------------------------------------------- 
*/ 

#ifndef  GRLC_GFFF_C
#define  GRLC_GFFF_C
#endif

#define ENTITY_GRLC

/*==== INCLUDES =============================================================*/
#include <string.h>
#include "typedefs.h"   /* to get Condat data types */
#include <stdio.h>
#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 "prim.h"       /* to get the definitions of used SAP and directions */
#include "message.h"
#include "grlc.h"        
#include "grlc_f.h" 
#include "grlc_tms.h"   
#include "grlc_rus.h"   
#include "grlc_rds.h"   
#include "grlc_gfff.h"        
#include "cl_rlcmac.h"

/*==== CONST ================================================================*/

#define D_DL_DUMMY_c 0x25

/*==== LOCAL VARS ===========================================================*/

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

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

/*
+------------------------------------------------------------------------------
| Function    : gff_init
+------------------------------------------------------------------------------
| Description : The function gff_init() .... 
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void gff_init ( void )
{ 
  TRACE_FUNCTION( "gff_init" );

  grlc_data->gff.rlc_status = RLC_STATUS_NULL;
  grlc_data->ul_tfi         = 0xFF;
  grlc_data->dl_tfi         = 0xFF;

  grlc_data->next_poll_fn      = 1;
  grlc_data->ul_poll_pos_index = 0xFF;
  grlc_data->nr_of_crc_errors  = 0xFFFF;
  grlc_data->ta_value          = 0xFF;

  INIT_STATE(GFF,GFF_DEACTIVE); 
} /* gff_init() */



/*
+------------------------------------------------------------------------------
| Function    : gff_tbf_init
+------------------------------------------------------------------------------
| Description : The function gff_tbf_init() .... 
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void gff_tbf_init ( void )
{ 
  TRACE_FUNCTION( "gff_tbf_init" );
 
  /*
   * set segmented control block array
   */
  grlc_data->ul_poll_pos_index = 0;
  grlc_data->nr_of_crc_errors  = 0;


#if defined (_TARGET_)
  {
    UBYTE i;
    /* target debugging*/

    grlc_data->last_dl_fn = 1; 
    
    for (i=0; i < CALL_ERROR_NR_OF_ST_FN;i++)
    {
      grlc_data->ul_fn_store[i]  = 0;
      grlc_data->ul_fn_errors[i] = 0;
      grlc_data->dl_fn_store[i]  = 0;
      grlc_data->dl_fn_errors[i] = 0;
    }
    grlc_data->ul_cnt_syn        = 0;  /*for target, count calls in rlc uplink*/
    grlc_data->ul_cnt_asyn       = 0;  /*for target, count calls in gffp mac_ready_ind*/
    grlc_data->dl_cnt_syn        = 0;  /*for target, count calls in rlc downlink*/
    grlc_data->dl_cnt_asyn       = 0;  /*for target, count calls in gffp mac_data_ind*/
    grlc_data->ul_call_errors    = 0;  /*for target, count calls in rlc uplink during grlc is active*/
    grlc_data->dl_call_errors    = 0;  /*for target, count calls in rlc downlink during grlc is active*/
  }
#endif /* defined (_TARGET_) */

} /* gff_tbf_init() */



/*
+------------------------------------------------------------------------------
| Function    : gff_send_ctrl_block
+------------------------------------------------------------------------------
| Description : The function gff_send_ctrl_block() .... 
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void gff_send_ctrl_block (ULONG fn_i, UBYTE tn_i, UBYTE * ptr_ctrl_block_i )
{
  PALLOC(cgrlc_data_ind,CGRLC_DATA_IND); /*T_CGRLC_DATA_IND*/

  TRACE_FUNCTION( "gff_send_ctrl_block" );

  cgrlc_data_ind->fn = fn_i;
  cgrlc_data_ind->tn = tn_i;  

  memcpy( cgrlc_data_ind->data_array, 
          ptr_ctrl_block_i,
          CGRLC_MAX_CTRL_MSG_SIZE );

  PSEND(hCommGRR,cgrlc_data_ind);

}/* gff_send_ctrl_block() */




/*
+------------------------------------------------------------------------------
| Function    : gff_analyse_dl_data
+------------------------------------------------------------------------------
| Description : The function gff_analyse_dl_data() .... It returns whether
|               the downlink block was intended for that MS or not.
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL gff_analyse_dl_data (ULONG fn_i, T_dl_data * ptr_dl_data_i )
{ 

  BOOL        tfi_correct = FALSE;
  UBYTE       payload,rrbp,sp,tfi,*ptr_blk;

  TRACE_FUNCTION( "gff_analyse_dl_data" );

/*
 *  Layer 1 buffer
 *  B1 B0  --> ptr_dl_data_i->dl_block[0]
 *  B3 B2
 *
 * B0 is the mac header
 */


  ptr_blk = (UBYTE *) (&ptr_dl_data_i->dl_block[0]);


  payload = (ptr_blk[0] & 0xC0) >> 6;
  rrbp    = (ptr_blk[0] & 0x30) >> 4;
  sp      = (ptr_blk[0] & 0x08) >> 3;

  
  /* 
   * In Test mode B,if there is CRC error on the payload data the MS will,
   * where required by the USF, transmit the decoded payload data. The block
   * transmitted will be a valid uplink block format.
   */
  if(((ptr_dl_data_i->block_status & 0x0100) NEQ 0x0000) AND ((grlc_data->testmode.mode EQ CGRLC_LOOP)))
  {
    UBYTE       bsn,e_bit;
     
    bsn     = (ptr_blk[2] & 0xFE)>>1;
    e_bit   = (ptr_blk[2] & 0x01);
    
    TRACE_EVENT(" Bad CRC - In Testmode B ");

    sig_gff_rd_data(  fn_i, 
                        (UBYTE)ptr_dl_data_i->tn, 
                        ptr_dl_data_i->block_status,
                        rrbp,
                        sp,
                        bsn,
                        0,
                        e_bit,
                        ptr_blk);
  }
  else
  {
    if(payload EQ RLC_DATA_BLOCK) 
    {
      UBYTE       bsn,fbi,e_bit;
     
      tfi     = (ptr_blk[1] & 0x3E) >> 1;
      bsn     = (ptr_blk[2] & 0xFE)>>1;
      fbi     = (ptr_blk[1] & 0x01);
      e_bit   = (ptr_blk[2] & 0x01);
      ptr_blk = (UBYTE *) (&ptr_blk[3]);

      if((tfi EQ grlc_data->dl_tfi) AND
         ((0x80>>ptr_dl_data_i->tn) & grlc_data->dl_tn_mask))
      {
        tfi_correct = TRUE;
        if(sp)
        {
          grlc_save_poll_pos ( fn_i,(UBYTE)ptr_dl_data_i->tn,rrbp, CGRLC_POLL_DATA, 3);
        }
        sig_gff_rd_data(  fn_i, 
                          (UBYTE)ptr_dl_data_i->tn, 
                          ptr_dl_data_i->block_status,
                          rrbp,
                          sp,
                          bsn,
                          fbi,
                          e_bit,
                          ptr_blk);
  #ifdef _TARGET_
      
        TRACE_BINDUMP( hCommGRLC, TC_USER6,
                 		  "D_DATA_BLOCK including MAC header", &ptr_dl_data_i->dl_block[0],53);
  #endif /* _TARGET_ */

      }
      else
      {
        TRACE_EVENT_P6("wrong tfi in data block  ad.tfi=%d dl_tfi=%d  bsn=%d || tn=%d->mask=%x tn_mask=%x"
                                                                ,tfi
                                                                ,grlc_data->dl_tfi
                                                                ,bsn
                                                                ,ptr_dl_data_i->tn
                                                                ,(0x80>>ptr_dl_data_i->tn)
                                                                ,grlc_data->dl_tn_mask);
      }


    }
    else
    {
      /*
       * any rlc control message received.
       * check if it is a packet uplink ack/nack and if it is adressed to MS
       */
      ULONG tc_user        = TC_USER4;
      UBYTE trace_msg_type = D_MSG_TYPE_UNKNOWN_c;

      UBYTE msg_type=0,i=0;

      if( payload EQ CTRL_BLK_NO_OPT )
      {
        msg_type = trace_msg_type = ptr_blk[1]>>2; 
        i        = 2; /* Byte position of tfi in puan */
      }
      else if( payload EQ CTRL_BLK_OPT )
      {
        if( !(ptr_blk[1] & 0x01) )           /* no tfi octet present: ac   = 0 */
        {
          if( !(ptr_blk[1] & 0x80) )         /* not segmented       : rbsn = 0 */
          {
            if( (ptr_blk[1] & 0x02) )        /* not segmented       : fs   = 1 */ 
            {
              msg_type = trace_msg_type = ptr_blk[2]>>2; 
              i        = 3; /* Byte position of tfi in puan */
            }
            else                             /* segmented           : fs   = 0 */
            {
              trace_msg_type = ptr_blk[2]>>2; 
            }
          }
          else                               /* segmented           : rbsn = 1 */
          {
            trace_msg_type = D_MSG_TYPE_2ND_SEGMENT_c;
          }
        }
        else                                 /* tfi octet present   : ac   = 1 */
        {
          if( !(ptr_blk[1] & 0x80) )         /* not segmented       : rbsn = 0 */ 
          {
            if( (ptr_blk[1] & 0x02) )        /* not segmented       : fs   = 1 */
            {
              msg_type = trace_msg_type = ptr_blk[3]>>2;
              i        = 4; /* Byte position of tfi in puan */
            }
            else                             /* segmented           : fs   = 0 */
            {
              trace_msg_type = ptr_blk[3]>>2;
            }
          }
          else                               /* segmented           : rbsn = 1 */ 
          {
            trace_msg_type = D_MSG_TYPE_2ND_SEGMENT_c;
          }
        }
      }

      /*
       * send control message to GRR
       */
      if(msg_type NEQ D_DL_DUMMY_c ) /* No Dummy blocks sent to GRR , to primitive load between GRR and GRLC*/
      {  
        gff_send_ctrl_block(fn_i, (UBYTE)ptr_dl_data_i->tn,ptr_blk);
      }
  
      if( trace_msg_type EQ D_DL_DUMMY_c )
      {
        tc_user = TC_USER5;
      }

      TRACE_BINDUMP( hCommGRLC, tc_user,
                     cl_rlcmac_get_msg_name( trace_msg_type, RLC_MAC_ROUTE_DL ),
                     ptr_blk, MAX_L2_FRAME_SIZE ); /*lint !e569*/

      if(msg_type EQ D_GRLC_UL_ACK_c)
      {
        /*
         * tfi check for packet uplink ack nack
         */
        if(i EQ 4                AND                          /* tfi in header present       */
          !(ptr_blk[2] & 0x01)   AND                          /* D=0 packet uplink tfi add.  */
          (((ptr_blk[2]) & 0x3E)>>1) EQ grlc_data->ul_tfi)    /* header tfi addressed to MS  */
        {
          tfi = ((ptr_blk[2]) & 0x3E)>>1;
        }
        else
        {
          tfi = ((ptr_blk[i]) & 0x3E)>>1;  /* Take tfi from airmessage*/
        }

        if((grlc_data->ul_tfi EQ tfi) AND
           ((0x80>>ptr_dl_data_i->tn) & grlc_data->ul_tn_mask))
        {
          T_MSGBUF msg;
          UBYTE    data[22];

          memset(data,0xEE,22);

          msg.l_buf  = (23 - i + 1) * 8;
          msg.o_buf  = 0;
          msg.buf[0] = data[0];

          memcpy(msg.buf, &(ptr_blk[i-1]), (msg.l_buf)/8);


          if(sp)
          {
            grlc_save_poll_pos ( fn_i,(UBYTE)ptr_dl_data_i->tn,rrbp, CGRLC_POLL_UACK, 3);
          }
          grlc_decode_grlc (&msg);
          sig_gff_ru_ul_ack ( fn_i,(UBYTE)ptr_dl_data_i->tn,rrbp,sp); 
        } 
      }
    }
  }


  return( tfi_correct );
} /* gff_analyse_dl_data() */


/*
+------------------------------------------------------------------------------
| Function    : gff_handle_continious_ta
+------------------------------------------------------------------------------
| Description : store the new ta value, and pass it to L1
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void gff_handle_continious_ta ( void )
{

  TRACE_FUNCTION( "gff_handle_continious_ta" );

 
  if(grlc_data->func.mac_ready_ind.ta_value NEQ 0xFF)
  {
    /*
     * valid TA in L1
     */
    if(grlc_data->ta_value NEQ grlc_data->func.mac_ready_ind.ta_value )
    {
      PALLOC(cgrlc_ta_value_ind,CGRLC_TA_VALUE_IND);

      /*
       * Current TA in GRLC differs from the TA in L1: store in GRLC
       */
      grlc_data->ta_value           = grlc_data->func.mac_ready_ind.ta_value;
      cgrlc_ta_value_ind->ta_value  = grlc_data->ta_value;
      PSEND(hCommGRR,cgrlc_ta_value_ind);
    }
  }

} /* gff_handle_continious_ta */

/*
+------------------------------------------------------------------------------
| Function    : gff_clip_rxlev
+------------------------------------------------------------------------------
| Description : This function is used to clip received signal level values.
|
| Parameters  : clipp  - pointer to clipped received signal level values
|               rxlev  - pointer to received signal level values
|               number - number of received signal level values
|
+------------------------------------------------------------------------------
*/
GLOBAL void gff_clip_rxlev ( UBYTE *clipp, UBYTE *rxlev, UBYTE number )
{ 
  UBYTE i; /* used for counting */
  
  TRACE_FUNCTION( "gff_clip_rxlev" );

  for( i = 0; i < number; i++ )
  { 
    if( (signed char)( rxlev[i] ) <   MAC_RXLEV_MIN  AND
                       rxlev[i]   NEQ MAC_RXLEV_NONE     )
    {
      clipp[i] = MAC_RXLEV_MIN;
    }
    else if ( (signed char)( rxlev[i] ) > MAC_RXLEV_MAX )
    {
      clipp[i] = MAC_RXLEV_MAX;
    }
    else if( rxlev[i] EQ MAC_RXLEV_NONE )
    {
      clipp[i] = MAC_RXLEV_NONE;
    }
    else
    {
      clipp[i] = rxlev[i];
    }
  }
} /* gff_clip_rxlev() */