view src/g23m-gsm/dl/dl_trace.c @ 685:3fb7384e820d

tpudrv12.h: FCDEV3B goes back to being itself A while back we had the idea of a FreeCalypso modem family whereby our current fcdev3b target would some day morph into fcmodem, with multiple FC modem family products, potentially either triband or quadband, being firmware-compatible with each other and with our original FCDEV3B. But in light of the discovery of Tango modules that earlier idea is now being withdrawn: instead the already existing Tango hw is being adopted into our FreeCalypso family. Tango cannot be firmware-compatible with triband OM/FCDEV3B targets because the original quadband RFFE on Tango modules is wired in TI's original Leonardo arrangement. Because this Leonardo/Tango way is now becoming the official FreeCalypso way of driving quadband RFFEs thanks to the adoption of Tango into our FC family, our earlier idea of extending FIC's triband RFFE control signals with TSPACT5 no longer makes much sense - we will probably never produce any new hardware with that once-proposed arrangement. Therefore, that triband-or-quadband FCFAM provision is being removed from the code base, and FCDEV3B goes back to being treated the same way as CONFIG_TARGET_GTAMODEM for RFFE control purposes.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 24 Sep 2020 21:03:08 +0000
parents 27a4235405c6
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :
|  Modul   :
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This Modul defines the offline trace functions
|             for the component DL of the mobile station.
+-----------------------------------------------------------------------------
*/

#ifndef DL_TRACE_C
#define DL_TRACE_C

#define ENTITY_DL

/*==== INCLUDES ===================================================*/
#include "typedefs.h"
#include <string.h>
#include "vsi.h"
#include "pconst.cdg"
#include "custom.h"
#include "gsm.h"
#include "mon_dl.h"
#include "prim.h"
#include "pei.h"
#include "tok.h"
#include "ccdapi.h"
#include "dl.h"

/*==== EXPORT =====================================================*/
/*==== PRIVAT =====================================================*/
#if defined(DL_TRACE_ENABLED)
#ifdef OPTION_MULTITHREAD
  #define TRACE_TYPE    _ENTITY_PREFIXED(TRACE_TYPE)
  #define CHANNEL       _ENTITY_PREFIXED(CHANNEL)
  #define STATES        _ENTITY_PREFIXED(STATES)
#endif  /* OPTION_MULTITHREAD */
LOCAL const char* const STATES[] =      {
                                "INVALID",
                                "DISABLED",
                                "IDLE_DL",
                                "SUSPENDED",
                                "AWAITING_ESTABLISHMENT",
                                "MULTI_FRAME_ESTABLISHED",
                                "TIMER_RECOVERY",
                                "AWAITING_RELEASE"
                             };
LOCAL const char* const TRACE_TYPE[] =  { "UL", "DL", "Ev", "St", "PL", "RR" };
LOCAL const char* const CH_TYPE[] =     { "  ", "SA", "SD", "FH", "FF", "CC", "BC", "PC", "PE", "CB", "BE" };
LOCAL const char  SAPI_TYPE[] =         { '0', '1', '2', '3', ' '};

LOCAL void  array2hex (UBYTE *inarray, char *outarray, int size);

#if !defined(DL_IMMEDIATE_TRACE)

/*==== TEST TRACE ===================================================*/
#define TEST_ENTITY_DL

/*==== VARIABLES ==================================================*/
/*==== FUNCTIONS ==================================================*/
/*
 * The Data Link Layer Trace is a cyclic buffer for
 * debugging layer 2 problems.
 *
 * The buffer will be initialized at startup and will
 * be filled by the function dl_trace() until it is full.
 * The size of the buffer is IDLE_TRACE_SIZE.
 *
 * The content is
 *
 * trace_type (uplink, downlink, event state, alr_event, rr_event)
 * Channel Type (SACCH, SDDCH, FACCH)
 * real system clock
 * State (DL states)
 * pending disc request
 * data (layer frame, eevnt strings, state)
 *
 * During IDLE mode (triggered by RX_PERIODIC_IND in ALR/TIL_main.c)
 * an output is written to as SYST trace.
 * (IDLE_TRACE_MAX_READED traces each trigger)
 */

#define IDLE_TRACE_SIZE       512
#define IDLE_TRACE_MAX_READED  16

#if (((IDLE_TRACE_SIZE-1) & (~IDLE_TRACE_SIZE)) == (IDLE_TRACE_SIZE-1))
#define POWER_OF_2
#pragma message("IDLE_TRACE_SIZE is power of 2")
#else
#pragma message("IDLE_TRACE_SIZE is NOT power of 2")
#endif

typedef struct
{
  UBYTE         trace_type;
  UBYTE         ch_type;
  UBYTE         sapi;
  T_TIME        sysClock;
  UBYTE         disc_request;
  UBYTE         state;
  UBYTE         data [MAX_L2_FRAME_SIZE];
} T_IDLE_TRACE_DATA;

#ifdef OPTION_MULTITHREAD
  #define IDLE_Trace_buffer       _ENTITY_PREFIXED(IDLE_Trace_buffer)
  #define IDLE_Trace_write_index  _ENTITY_PREFIXED(IDLE_Trace_write_index)
  #define IDLE_Trace_read_index   _ENTITY_PREFIXED(IDLE_Trace_read_index)
#endif  /* OPTION_MULTITHREAD */

GLOBAL T_IDLE_TRACE_DATA   IDLE_Trace_buffer [IDLE_TRACE_SIZE];
GLOBAL USHORT              IDLE_Trace_write_index  = 0;
GLOBAL USHORT              IDLE_Trace_read_index   = 0;

LOCAL  T_HANDLE            sem_DL_TRC;

GLOBAL void dl_trace_init (void)
{
  sem_DL_TRC  = vsi_s_open (VSI_CALLER "DL_IDLE_TRACE",1);
  if (sem_DL_TRC NEQ VSI_ERROR)
    dl_trace_clear (0);
  else
    SYST_TRACE ("DL:canīt open semaphore \"DL_IDLE_TRACE\"");
}

GLOBAL void dl_trace_exit (void)
{
  if (sem_DL_TRC NEQ VSI_ERROR)
    vsi_s_close (VSI_CALLER sem_DL_TRC);
}

GLOBAL void dl_trace_clear ()
{
  dl_trace_read_all (0); /* first, get all remaining traces (if exists) */

  ENTER_CRITICAL_SECTION (sem_DL_TRC);
  IDLE_Trace_write_index = IDLE_Trace_read_index = 0;
  LEAVE_CRITICAL_SECTION (sem_DL_TRC);

  TRACE_EVENT ("offline trace reset");
  DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, 0, "offline trace reset");
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)            MODULE  : DL_COM                |
| STATE   : code                     ROUTINE : dl_trace              |
+--------------------------------------------------------------------+

  PURPOSE : Fill in a trace.

*/
GLOBAL void dl_trace (UCHAR trace_type, UCHAR channel, UCHAR ch_type, UCHAR* data)
{
  T_IDLE_TRACE_DATA*  trace_data;
  USHORT              write_index1, write_index2;/* trace_size must not be greater than 2 */
  UBYTE               trace_size;

  if (data)
  {
#if defined (DISABLE_MEASREPORT_TRACE)
    if ((ch_type EQ L2_CHANNEL_SACCH) AND
        (data[2] EQ 0x01) AND
        (data[3] EQ 0x03) AND
        (data[4] EQ 0x49))
      return;
#endif  /* DISABLE_MEASREPORT_TRACE */

#if defined (DISABLE_EMPTY_UI)
    if ((trace_type EQ TRACE_DOWNLINK) OR (trace_type EQ TRACE_UPLINK))
    {
      if ((ch_type EQ L2_CHANNEL_SACCH) AND
        (data[3] EQ 0x03) AND
        (data[4] EQ 0x01))
        return;
      else if (
        (data[1] EQ 0x03) AND
        (data[2] EQ 0x01))
        return;
    }
#endif  /* DISABLE_EMPTY_UI */
  }

  TEST_SEMAPHORE (sem_DL_TRC);
  ENTER_CRITICAL_SECTION(sem_DL_TRC);

  trace_size = 1;
  if ((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT))
  {
    if (data AND strlen ((char *)data) >= 23)
      trace_size = 2;
  }

#if defined(POWER_OF_2)
  write_index1 = (IDLE_Trace_write_index + 1) & (IDLE_TRACE_SIZE - 1);  /* if IDLE_TRACE_SIZE power of 2 */
  write_index2 = (IDLE_Trace_write_index + trace_size) & (IDLE_TRACE_SIZE - 1);  /* if IDLE_TRACE_SIZE power of 2 */
#else
  write_index1 = (IDLE_Trace_write_index + 1) % IDLE_TRACE_SIZE;      /* if IDLE_TRACE_SIZE not power of 2 */
  write_index2 = (IDLE_Trace_write_index + trace_size) % IDLE_TRACE_SIZE;      /* if IDLE_TRACE_SIZE not power of 2 */
#endif  /* POWER_OF_2 */
  if ((write_index1 NEQ IDLE_Trace_read_index) AND (write_index2 NEQ IDLE_Trace_read_index))
  { /* buffer is not full */
    trace_data = &IDLE_Trace_buffer[IDLE_Trace_write_index];

    trace_data->trace_type = trace_type;
    if ((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT))
    {
      trace_data->state = trace_size;
    }
    else
    {
  GET_INSTANCE_DATA; 
      trace_data->ch_type = ch_type;
      switch (channel)
      {
      case C_SACCH0:
      case C_DCCH0:
        trace_data->disc_request = dl_data->dcch0_disc_request;
        trace_data->state = dl_data->state [C_DCCH0];
        trace_data->sapi = PS_SAPI_0;
        break;
      case C_DCCH3:
        trace_data->disc_request = dl_data->dcch3_disc_request;
        trace_data->state = dl_data->state [C_DCCH3];
        trace_data->sapi = PS_SAPI_3;
        break;
      default:
        trace_data->disc_request = 0;
        trace_data->state = 0;
        trace_data->sapi = NOT_PRESENT_8BIT;
        break;
      }
    }

    vsi_t_time (VSI_CALLER &trace_data->sysClock);

    if (data)
    {
      memcpy (trace_data->data, data, MAX_L2_FRAME_SIZE);
      if ((trace_type NEQ TRACE_UPLINK) AND (trace_type NEQ TRACE_DOWNLINK))
      {
        trace_data->data[MAX_L2_FRAME_SIZE-1] = 0;
      }

      if (trace_size EQ 2)
      {
        if (IDLE_Trace_write_index EQ (IDLE_TRACE_SIZE - 1))/* the last buffer index ? */
          trace_data = &IDLE_Trace_buffer[0];/* -> overflow to the first buffer index */
        else
          trace_data++;
        memcpy (trace_data->data, data+MAX_L2_FRAME_SIZE-1, MAX_L2_FRAME_SIZE-1);
        trace_data->data[MAX_L2_FRAME_SIZE-1] = 0;
      }
    }

    IDLE_Trace_write_index = write_index2;
  }/* endif buffer is not full */

  LEAVE_CRITICAL_SECTION (sem_DL_TRC);

#if defined(_SIMULATION_)
  dl_trace_read (0);
#endif  /* _SIMULATION_ */
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)            MODULE  : DL_COM                |
| STATE   : code                     ROUTINE : dl_trace_read         |
+--------------------------------------------------------------------+

  PURPOSE : Fill in a trace.

*/
GLOBAL void dl_trace_read_all ()
{
  USHORT  write_index, read_index;

  do
  {
    dl_trace_read ();

    ENTER_CRITICAL_SECTION (sem_DL_TRC);
    write_index = IDLE_Trace_write_index;
    read_index = IDLE_Trace_read_index;
    LEAVE_CRITICAL_SECTION (sem_DL_TRC);
  } while (read_index NEQ write_index);
}

GLOBAL void dl_trace_read ()
{
  T_IDLE_TRACE_DATA*  trace_data;
  USHORT              write_index, read_index, left;
  UBYTE               trace_size;
  static char         buffer[80];
  UBYTE               j, o, readed = 0;

  TEST_SEMAPHORE (sem_DL_TRC);

  ENTER_CRITICAL_SECTION (sem_DL_TRC);
  write_index = IDLE_Trace_write_index;
  read_index = IDLE_Trace_read_index;
  LEAVE_CRITICAL_SECTION (sem_DL_TRC);

  if (read_index EQ write_index)
  {
    #if defined (_TARGET_) AND !defined( GPRS ) AND defined(FF_GTI)
      sleep_mode ();
    #endif  /* _TARGET_ AND !GPRS AND !FF_GTI */
    return;
  }

  while (read_index NEQ write_index)
  {
    ENTER_CRITICAL_SECTION (sem_DL_TRC);
    trace_data = &IDLE_Trace_buffer[read_index];
    LEAVE_CRITICAL_SECTION (sem_DL_TRC);

#if defined(POWER_OF_2)
    left = (write_index - read_index - 1) & (IDLE_TRACE_SIZE-1);
#else
    left = (IDLE_TRACE_SIZE + write_index - read_index - 1) % IDLE_TRACE_SIZE;
#endif  /* POWER_OF_2 */

    if (trace_data->ch_type > ELEMENTS(CH_TYPE))
      trace_data->ch_type = 0;

    if (trace_data->sapi >= ELEMENTS (SAPI_TYPE))
      trace_data->sapi = ELEMENTS (SAPI_TYPE) - 1;

    trace_size = 1;/* default */
    switch (trace_data->trace_type)
    {
    case TRACE_UPLINK:
    case TRACE_DOWNLINK:
      sprintf (buffer, "[%03d]:%07lu %c%d %s %s ",
        left,
        trace_data->sysClock,
        trace_data->disc_request?'D':' ',
        trace_data->state,
        TRACE_TYPE[trace_data->trace_type],
        CH_TYPE[trace_data->ch_type]);
      o = strlen (buffer);
      array2hex (trace_data->data, buffer+o, 23);
      break;

    case TRACE_DL_EVENT:
      sprintf (buffer, "[%03d]:%07lu %c%d Ev %s%c %s",
        left,
        trace_data->sysClock,
        trace_data->disc_request?'D':' ',
        trace_data->state,
        CH_TYPE[trace_data->ch_type],
        SAPI_TYPE[trace_data->sapi],
        trace_data->data);
      break;

    case TRACE_PL_EVENT:
    case TRACE_RR_EVENT:
      trace_size = trace_data->state;
      if (trace_size EQ 2)
      {
        T_IDLE_TRACE_DATA *trace_data2;
        if (read_index EQ (IDLE_TRACE_SIZE - 1))/* the last buffer index ? */
          trace_data2 = &IDLE_Trace_buffer[0];/* -> overflow to the first buffer index */
        else
          trace_data2 = trace_data+1;

        sprintf (buffer, "[%03d]:%07lu %d  Ev %s %s%s",
          left,
          trace_data->sysClock,
          trace_data->state,
          TRACE_TYPE[trace_data->trace_type],
          trace_data->data,
          trace_data2->data);
      }
      else
      {
        sprintf (buffer, "[%03d]:%07lu %d  Ev %s %s",
          left,
          trace_data->sysClock,
          trace_data->state,
          TRACE_TYPE[trace_data->trace_type],
          trace_data->data);
      }
      break;

    case TRACE_CHSTATE:
      sprintf (buffer, "[%03d]:%07lu %c%d ST %s%c state=%s",
        left,
        trace_data->sysClock,
        trace_data->disc_request?'D':' ',
        trace_data->state,
        CH_TYPE[trace_data->ch_type],
        SAPI_TYPE[trace_data->sapi],
        STATES[trace_data->state]);
      break;

    default:
      buffer[0] = 0;
      break;
    }

    if (buffer[0])
    {
      SYST_TRACE (buffer);
    }
    else
    {
      SYST_TRACE ("dl_trace_read() failed");
    }

    ENTER_CRITICAL_SECTION (sem_DL_TRC);
    trace_data->sysClock = 0; /* readed */
    IDLE_Trace_read_index += trace_size;
#if defined(POWER_OF_2)
    IDLE_Trace_read_index &= (IDLE_TRACE_SIZE-1);/* if power of 2 */
#else
    IDLE_Trace_read_index %= IDLE_TRACE_SIZE; /* if not power of 2 */
#endif  /* POWER_OF_2 */
    read_index = IDLE_Trace_read_index;
    write_index = IDLE_Trace_write_index;
    LEAVE_CRITICAL_SECTION (sem_DL_TRC);

    if (readed++ >= IDLE_TRACE_MAX_READED)
      break;
  }/* endwhile */
}

#else  /* DL_IMMEDIATE_TRACE */

#define IMM_TRACE_SIZE       2
typedef struct
{
  UBYTE         sapi;
  T_TIME        sysClock;
  UBYTE         disc_request;
  UBYTE         state;
  UBYTE         data [IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE];
} T_TRACE_DATA;

#ifdef OPTION_MULTITHREAD
  #define print_buffer  _ENTITY_PREFIXED(print_buffer)
  #define trace_buffer  _ENTITY_PREFIXED(trace_buffer)
#endif  /* OPTION_MULTITHREAD */
LOCAL char          print_buffer[25+IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE];
LOCAL T_TRACE_DATA  trace_buffer;

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)            MODULE  : DL_COM                |
| STATE   : code                     ROUTINE : dl_trace              |
+--------------------------------------------------------------------+

  PURPOSE : Fill in a trace.

*/

GLOBAL void dl_fast_trace (UBYTE trace_type, UBYTE channel, UBYTE ch_type,
                    T_TIME trace_time, ULONG trace_mask, UBYTE* data)
{
  T_TRACE_DATA*  trace_data;
  UBYTE          o;

  /* While TC_USER2 is set, measurements and empty frames will be traced always */
  if (data AND ((trace_mask & TC_USER2) EQ 0))
  {
    if ((ch_type EQ L2_CHANNEL_SACCH) AND
        (data[2] EQ 0x01) AND
        (data[3] EQ 0x03) AND
        (data[4] EQ 0x49))
      return;

    if ((trace_type EQ TRACE_DOWNLINK) OR (trace_type EQ TRACE_UPLINK))
    {
      if ((ch_type EQ L2_CHANNEL_SACCH) AND
        (data[3] EQ 0x03) AND
        (data[4] EQ 0x01))
        return;
      else if (
        (data[1] EQ 0x03) AND
        (data[2] EQ 0x01))
        return;
    }
  }

  trace_data = &trace_buffer;
  trace_data->sysClock = trace_time;
  if (!((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT)))
  {
  GET_INSTANCE_DATA; 
    switch (channel)
    {
    case C_SACCH0:
    case C_DCCH0:
      trace_data->disc_request = dl_data->dcch0_disc_request;
      trace_data->state = dl_data->state [C_DCCH0];
      trace_data->sapi = PS_SAPI_0;
      break;
    case C_DCCH3:
      trace_data->disc_request = dl_data->dcch3_disc_request;
      trace_data->state = dl_data->state [C_DCCH3];
      trace_data->sapi = PS_SAPI_3;
      break;
    default:
      trace_data->disc_request = 0;
      trace_data->state = 0;
      trace_data->sapi = NOT_PRESENT_8BIT;
      break;
    }
  }

  if (data)
  {
    if ((trace_type EQ TRACE_UPLINK) OR (trace_type EQ TRACE_DOWNLINK))
    {
      memcpy (trace_data->data, data, MAX_L2_FRAME_SIZE);
    }
    else
    {
      strncpy ((char *)trace_data->data, (char *)data, IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE-1);
      trace_data->data[IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE-1] = 0;
    }
  }
  else
  {
    trace_data->data[0] = 0;
  }


  if (ch_type > ELEMENTS(CH_TYPE))
    ch_type = 0;

  if (trace_data->sapi >= ELEMENTS (SAPI_TYPE))
    trace_data->sapi = ELEMENTS (SAPI_TYPE) - 1;

  switch (trace_type)
  {
  case TRACE_UPLINK:
  case TRACE_DOWNLINK:
    sprintf (print_buffer, "DLTRC:%07lu %c%d %s %s%c ",
      trace_data->sysClock,
      trace_data->disc_request?'D':' ',
      trace_data->state,
      TRACE_TYPE[trace_type],
      CH_TYPE[ch_type],
      SAPI_TYPE[trace_data->sapi]);
    o = strlen (print_buffer);
    array2hex (trace_data->data, print_buffer+o, 23);
    break;

  case TRACE_DL_EVENT:
    sprintf (print_buffer, "DLTRC:%07lu %c%d Ev %s%c %s",
      trace_data->sysClock,
      trace_data->disc_request?'D':' ',
      trace_data->state,
      CH_TYPE[ch_type],
      SAPI_TYPE[trace_data->sapi],
      trace_data->data);
    break;

  case TRACE_PL_EVENT:
  case TRACE_RR_EVENT:
    sprintf (print_buffer, "DLTRC:%07lu %d  Ev %s %s",
      trace_data->sysClock,
      trace_data->state,
      TRACE_TYPE[trace_type],
      trace_data->data);
    break;

  case TRACE_CHSTATE:
    sprintf (print_buffer, "DLTRC:%07lu %c%d ST %s%c state=%s",
      trace_data->sysClock,
      trace_data->disc_request?'D':' ',
      trace_data->state,
      CH_TYPE[ch_type],
      SAPI_TYPE[trace_data->sapi],
      STATES[trace_data->state]);
    break;

  default:
    print_buffer[0] = 0;
    break;
  }

  TRACE_USER_CLASS (TC_USER1, print_buffer);

#if 0
  if (print_buffer[0])
  {
    #if defined(_SIMULATION_)
      TRACE_EVENT_WIN (print_buffer);
    #else  /* _SIMULATION_ */
      SYST_TRACE_P ((DLTRC,print_buffer));
    #endif  /* _SIMULATION_ */
  }
#endif /* 0 */
}
#endif  /* DL_IMMEDIATE_TRACE */

LOCAL void  array2hex (UBYTE *inarray, char *outarray, int size)
{
  int col=0, n=0;
  UBYTE b, nh, nl;

  while (n < size)
  {
    b = inarray[n++];
    nh = b>>4;
    nl = b&0x0f;
    outarray[col++] = nh > 9 ? nh + 'A' - 10 : nh + '0';
    outarray[col++] = nl > 9 ? nl + 'A' - 10 : nl + '0';
  }
  outarray[col] = 0;
}
#endif  /* DL_TRACE_ENABLED */

#if defined (DL_TRACE_PFREE)
GLOBAL void* my_pfree(void *pointer, int line, char *file)
{

  char buffer[23];
  sprintf (buffer, "%s#%u:%p", file+2, line, pointer);
  dl_trace (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, buffer);

  if (pointer)
  {
    PFREE (pointer);
  }
  else
  {
    SYST_TRACE_P((SYST, "%s#%u: PFREE(NULL)", file, line));
  }

  return NULL;
}
#endif /* DL_TRACE_PFREE */

#endif  /* DL_TRACE_C */