diff src/gpf/frame/route.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gpf/frame/route.c	Fri Oct 16 06:23:26 2020 +0000
@@ -0,0 +1,1240 @@
+/* 
++------------------------------------------------------------------------------
+|  File:       route.c
++------------------------------------------------------------------------------
+|  Copyright 2004 Texas Instruments Deutschland, 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 Deutschland, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  This Modul performs the filtering and routing of
+|             primitives for testing capabilities of the protocol stack.
++----------------------------------------------------------------------------- 
+*/ 
+ 
+#ifndef __ROUTE_C__
+#define __ROUTE_C__
+#endif
+
+/*==== INCLUDES ===================================================*/
+ 
+#include <stdio.h>
+#include <string.h>
+
+#include "typedefs.h"
+#include "os.h"
+#include "vsi.h"
+#include "frame.h"
+#include "tools.h"
+#include "frm_defs.h"
+#include "frm_types.h"
+#include "frm_glob.h"
+#include "p_mem.h"
+#include "route.h"
+#include "frm_ext.h"
+
+/*==== CONSTANTS ==================================================*/
+
+/*==== TYPES ======================================================*/
+
+/*==== CONSTANTS ====================================================*/
+
+/*==== EXTERNALS =====================================================*/
+
+/* -------------- S H A R E D - BEGIN ---------------- */
+#ifdef _TOOLS_
+#pragma data_seg("FRAME_SHARED") 
+#endif
+
+extern OS_HANDLE ext_data_pool_handle;
+extern T_HANDLE TestGroupHandle;
+extern T_FRM_ROUTING_TABLE_ENTRY *Routing[];
+extern char TaskName[];
+#ifndef _TOOLS_
+extern T_lemu_SendToQueue lemu_SendToQueue_func; 
+#endif
+/*==== VARIABLES ==================================================*/
+
+#ifndef RUN_INT_RAM
+T_HANDLE rt_tst_handle = VSI_ERROR;
+#else
+extern int rt_tst_handle;
+#endif
+
+#ifdef _TOOLS_
+#pragma data_seg()
+#endif
+/* -------------- S H A R E D - END ---------------- */
+
+#ifndef _TOOLS_
+extern const T_MEM_PROPERTIES *mem;
+#endif
+
+/*==== FUNCTIONS ==================================================*/
+                          
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_Init             |
++--------------------------------------------------------------------+
+
+  PURPOSE : initialize the routing table.
+*/
+
+GLOBAL SHORT rt_Init (void)
+{  
+USHORT i;
+  /*
+   * Initialize the routingTable
+   */
+  for ( i = 0; i <= MaxEntities; i++ )
+    Routing[i] = NULL;
+
+  return OS_OK;
+}
+#endif
+
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_CvrtOpcMask      |
++--------------------------------------------------------------------+
+
+  PURPOSE : convert "1010101" mask to opcMask and opcStatus
+*/
+
+LOCAL SHORT rt_CvrtToOpcMask ( char *OpcString, ULONG *opcMask, ULONG *opcStatus )
+{  
+unsigned int len;
+unsigned int i;
+char *p;
+
+  len = strlen ( OpcString );
+  p = OpcString + len;
+
+  for ( i = 0; i < len; i++ )
+  {
+    switch (*--p)
+    {
+      case '1':
+        *opcMask |= (1<<i);
+        *opcStatus |= (1<<i);
+        break;       
+      case '0':
+        *opcMask |= (1<<i);
+        *opcStatus &= ~((unsigned int)1<<i);
+        break;       
+      case '*':           /* wildcard matches */
+        *opcMask &= ~((unsigned int)1<<i);
+        *opcStatus &= ~((unsigned int)1<<i);
+        break;
+      default:
+        break;       
+    }
+  }
+  return OS_OK;
+}
+#endif
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_CvrtOpcMask      |
++--------------------------------------------------------------------+
+
+  PURPOSE : convert opcMask and opcStatus to "1010101" 
+*/
+LOCAL SHORT rt_CvrtFromOpcMask ( char *OpcString, ULONG opcMask, ULONG opcStatus )
+{  
+signed char i;
+char len;
+
+  if ( opcMask >> 16 )
+    len = 32;
+  else
+    len = 16;
+  for ( i = len-1; i >= 0; i-- )
+  {
+    if ( opcMask & (1<<i) )
+    {
+      if ( opcStatus & (1<<i) )
+        *OpcString = '1';
+      else
+        *OpcString = '0';
+    }
+    else
+      *OpcString = '*';
+    OpcString++;
+  }
+  *(OpcString++) = ' ';
+  *(OpcString++) = 0;
+  
+  return OS_OK;
+}
+#endif
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_ReadRouting      |
++--------------------------------------------------------------------+
+
+  PURPOSE : reads all routings of the routing table of the task.
+*/
+
+GLOBAL SHORT rt_RouteRead ( T_HANDLE Handle, char *Buffer )               
+{
+T_HANDLE TstComHandle;
+static T_FRM_ROUTING_TABLE_ENTRY *pEntry;
+char OrgReceiver[ RESOURCE_NAMELEN ];
+char NewReceiver[ RESOURCE_NAMELEN ];
+char OpcString [18];
+char const *pCmd;
+static UBYTE FirstRead = 1;
+
+  if ( FirstRead )
+  {
+    FirstRead = 0;
+    pEntry = Routing[Handle];
+  }
+  if ( pEntry )
+  {
+    if ( pEntry->OldDestComHandle == ROUTE_ALL )
+      strcpy ( OrgReceiver, RT_ALL_TOKEN );
+    else
+      strcpy ( OrgReceiver, pf_TaskTable[pEntry->OldDestComHandle].Name );
+    TstComHandle = vsi_c_open ( Handle, FRM_TST_NAME );
+    if ( pEntry->NewDestComHandle == TstComHandle )
+      strcpy ( NewReceiver, pEntry->ExtDest );
+    else
+    {
+      if ( pEntry->NewDestComHandle != 0 )
+        strcpy ( NewReceiver, pf_TaskTable[pEntry->NewDestComHandle].Name );
+    }
+    if ( pEntry->opcMask )
+      rt_CvrtFromOpcMask ( OpcString, pEntry->opcMask, pEntry->opcStatus );
+    else
+      OpcString[0] = 0;
+
+    switch (pEntry->Command & RT_COMMAND_MASK)
+    {
+      case RT_DUPLICATE: pCmd = SYSPRIM_DUPLICATE_TOKEN;
+      break;
+      case RT_REDIRECT:  pCmd = SYSPRIM_REDIRECT_TOKEN;
+      break;
+      case RT_DESTROY:   pCmd = SYSPRIM_REDIRECT_TOKEN;
+                         strcpy ( NewReceiver, SYSPRIM_NULL_TOKEN );
+      break;
+      default:           pCmd = NULL;
+      break;
+    }
+    sprintf ( Buffer, "%s %s %s %s%s", pf_TaskTable[Handle].Name, pCmd, OrgReceiver, OpcString, NewReceiver );
+    pEntry = pEntry->pNextEntry;
+    return RT_OK;
+  }
+  else 
+  {
+    FirstRead = 1;
+    pEntry = Routing[Handle];
+    return RT_ERROR;
+  }
+}
+#endif
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_RoutingEntry     |
++--------------------------------------------------------------------+
+
+  PURPOSE : adds a new routing to the routing table of the task.
+            routings with duplicates are stored in the beginning
+            of the table because if the primitive is redirected and
+            send it can not be duplicated.
+*/
+
+LOCAL SHORT rt_RoutingEntry ( T_HANDLE SndTaskHandle, T_FRM_ROUTING_TABLE_ENTRY *pNewEntry, RT_ENTRY Status )
+{
+T_FRM_ROUTING_TABLE_ENTRY     *pEntry, *pNextEntry, *pPrevEntry;
+
+  /*
+   * delete all entries with same OldDestComHandle if a destroy command is stored
+   */
+  if ( pNewEntry->Command & RT_DESTROY )
+  {
+    if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
+    {
+      do
+      {
+        if ( pEntry->OldDestComHandle == pNewEntry->OldDestComHandle )
+        {
+          if ( pEntry == Routing[SndTaskHandle] )
+          {
+            if ( pEntry->pNextEntry )
+            {
+              ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
+            }
+            Routing[SndTaskHandle] = pEntry->pNextEntry;
+          }
+          else
+          {
+            ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
+            if ( pEntry->pNextEntry )
+            {
+              ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
+            }
+          }
+          pNextEntry = pEntry->pNextEntry;
+          os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
+        }
+        else
+          pNextEntry = pEntry->pNextEntry;
+
+        pEntry = pNextEntry;
+      }
+      while ( pEntry );
+    }
+  }
+  else
+  {
+    /*
+     * delete destroy command for OldDestComHandle if a new command is stored
+     */
+    if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
+    {
+      do
+      {
+        if ( pEntry->OldDestComHandle == pNewEntry->OldDestComHandle )
+        {
+          if ( pEntry->Command == RT_DESTROY )
+          {
+            if ( pEntry == Routing[SndTaskHandle] )
+            {
+              if ( pEntry->pNextEntry )
+              {
+                ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
+              }
+              Routing[SndTaskHandle] = pEntry->pNextEntry;
+            }
+            else
+            {
+              ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
+              if ( pEntry->pNextEntry )
+              {
+                ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
+              }
+            }
+            pNextEntry = pEntry->pNextEntry;
+            os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
+          }
+          break;
+        }
+        else
+          pNextEntry = pEntry->pNextEntry;
+
+        pEntry = pNextEntry;
+      }
+      while ( pEntry );
+    }
+  }
+     
+       
+  if ( (pEntry = Routing[SndTaskHandle]) != NULL )
+  {
+    do
+    {
+      if ( pEntry->SndTaskHandle    == SndTaskHandle   
+        && pEntry->NewDestComHandle == pNewEntry->NewDestComHandle  
+        && pEntry->OldDestComHandle == pNewEntry->OldDestComHandle  
+        && pEntry->MsgType          == pNewEntry->MsgType )
+      {
+        if ( !strcmp (pEntry->ExtDest, pNewEntry->ExtDest) )
+        {
+          if ( Status == RT_DELETE )
+          {
+            if ( pEntry == Routing[SndTaskHandle] )
+            {
+              Routing[SndTaskHandle] = pEntry->pNextEntry;
+              if ( pEntry->pNextEntry )
+              {
+                ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
+              }
+            }
+            else
+            {
+              ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
+              if ( pEntry->pNextEntry )
+              {
+                ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
+              }
+            }
+            pNextEntry = pEntry->pNextEntry;
+            os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
+            return RT_OK;
+          }
+#ifndef _TOOLS_
+          else
+          {
+            pEntry->Command = pNewEntry->Command;         /* modify command for old routing entry */
+            pEntry->opcMask = pNewEntry->opcMask;       /* set new opcMask in old routing entry */
+            pEntry->opcStatus = pNewEntry->opcStatus; /* set new opcStatus in old routing entry */
+            return RT_OK;
+          }
+#else
+          pEntry = pEntry->pNextEntry;
+#endif
+        }
+        else
+        {
+#ifdef _TOOLS_
+          if ( ( pEntry->opcMask == pNewEntry->opcMask )
+            && ( pEntry->opcStatus == pNewEntry->opcStatus ) )
+          {
+            strcpy ( pEntry->ExtDest, pNewEntry->ExtDest );
+            return RT_OK;
+          }
+          else
+#endif
+            pEntry = pEntry->pNextEntry;
+        }
+      }
+      else
+        pEntry = pEntry->pNextEntry;
+    } while ( pEntry );
+  }
+
+  pPrevEntry = NULL;
+  if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
+  {
+    do
+    {
+      pPrevEntry = pEntry;
+      if ( pNewEntry->Command & RT_DUPLICATE )/* put Duplications at the end of Duplications */
+      {
+        if ( pEntry->Command & RT_DUPLICATE )
+          pEntry = pEntry->pNextEntry;
+        else
+        {
+          if ( pPrevEntry == Routing[SndTaskHandle] )
+            pPrevEntry = NULL;
+          else
+            pPrevEntry = pEntry->pPrevEntry;
+          break;
+        }
+      }
+      else
+        pEntry = pEntry->pNextEntry;
+    }
+    while ( pEntry );
+  }
+  if ( os_AllocateMemory ( SndTaskHandle, (T_VOID_STRUCT**)&pNextEntry, sizeof(T_FRM_ROUTING_TABLE_ENTRY), OS_NO_SUSPEND, ext_data_pool_handle ) == OS_TIMEOUT )
+    return RT_NO_MEM;
+  pNextEntry->SndTaskHandle = SndTaskHandle;
+  pNextEntry->OldDestComHandle = pNewEntry->OldDestComHandle;
+  pNextEntry->NewDestComHandle = pNewEntry->NewDestComHandle;
+  pNextEntry->OldDestTaskHandle = pNewEntry->OldDestTaskHandle;
+  pNextEntry->Command       = pNewEntry->Command;
+  pNextEntry->MsgType       = pNewEntry->MsgType;
+  pNextEntry->opcMask       = pNewEntry->opcMask;
+  pNextEntry->opcStatus     = pNewEntry->opcStatus;
+  strcpy ( pNextEntry->ExtDest, pNewEntry->ExtDest );
+  
+  if ( pEntry )                 
+  {
+    pEntry->pPrevEntry = pNextEntry;          /* store at the beginning/in the list */
+  }
+  else                          
+    pNextEntry->pNextEntry = NULL;            /* append to the list */
+
+  if ( pPrevEntry )
+  {
+    pPrevEntry->pNextEntry = pNextEntry;      /* store in the list */
+    pNextEntry->pPrevEntry = pPrevEntry;
+    pNextEntry->pNextEntry = pEntry;
+  }
+  else
+  {
+    Routing[SndTaskHandle] = pNextEntry;      /* store at the beginning */
+    pNextEntry->pNextEntry = pEntry;
+  }
+  return RT_OK;
+}
+#endif
+
+#if 0
+/* not needed -> temporarily removed */
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_ModifyRouting    |
++--------------------------------------------------------------------+
+
+  PURPOSE : handle the contents of the redirection or duplicate
+            system primitive
+
+*/
+GLOBAL SHORT rt_isolate_entity ( T_HANDLE caller, char *entity )
+{
+T_FRM_ROUTING_TABLE_ENTRY entry;
+T_HANDLE snd;
+T_HANDLE rcv;
+int read_entry = FIRST_ENTRY;
+
+  if ( (rcv = vsi_e_handle ( caller, entity )) == VSI_ERROR )
+    return RT_ERROR;
+  else
+  {
+    while ( vsi_c_get_entity_com_entry ( read_entry, rcv, &snd ) == VSI_OK )
+    {
+      read_entry = NEXT_ENTRY;
+      entry.SndTaskHandle = snd;
+      entry.OldDestComHandle = rcv;
+      entry.NewDestComHandle = 0;
+      entry.opcMask = 0;
+      entry.MsgType = RT_PRIMITIVE_TYPE;
+      entry.Command = RT_DESTROY;
+      rt_RoutingEntry ( snd, &entry, RT_STORE );
+    }
+
+    entry.SndTaskHandle = rcv;
+    entry.OldDestComHandle = ROUTE_ALL;
+    entry.NewDestComHandle = 0;
+    entry.opcMask = 0;
+    entry.MsgType = RT_PRIMITIVE_TYPE;
+    entry.Command = RT_DESTROY;
+    rt_RoutingEntry ( rcv, &entry, RT_STORE );
+
+    return RT_OK;
+  }
+}
+#endif
+#endif
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_ModifyRouting    |
++--------------------------------------------------------------------+
+
+  PURPOSE : handle the contents of the redirection or duplicate
+            system primitive
+
+*/
+GLOBAL SHORT rt_RoutingModify ( T_HANDLE SndTaskHandle, char *Command, char *RoutingString)
+{
+char Token[81];
+char *pChar = RoutingString;
+T_FRM_ROUTING_TABLE_ENTRY Entry = { 0 }; 
+unsigned int len;
+T_FRM_ROUTING_TABLE_ENTRY *pEntry, *pNextEntry;
+
+  if ( !strcmp (Command, SYSPRIM_DUPLICATE_TOKEN) )
+    Entry.Command = RT_DUPLICATE;
+
+  if ( !strcmp (Command, SYSPRIM_REDIRECT_TOKEN) )
+    Entry.Command = RT_REDIRECT;
+  
+  if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
+    return RT_ERROR;
+  else
+    pChar += (len+1);
+
+  if ( !strcmp (Token, RT_CLEAR_TOKEN) )
+    Entry.Command |= RT_CLEAR_ENTRY;
+
+  if ( !strcmp (Token, RT_ALL_TOKEN) )
+    Entry.Command |= RT_ALL_DESTINATION;
+
+  if ( Entry.Command & RT_CLEAR_ENTRY )
+  {
+    if ( (pEntry = Routing[SndTaskHandle]) != NULL )
+    {
+      do
+      {
+        pNextEntry = (T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry;
+        os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
+        pEntry = pNextEntry;
+      }
+      while ( pEntry );
+      Routing[SndTaskHandle] = NULL;
+    }
+    return RT_OK;
+  }
+
+  if ( Entry.Command & RT_ALL_DESTINATION )
+  {
+    Entry.OldDestComHandle = ROUTE_ALL;
+    Entry.OldDestTaskHandle = ROUTE_ALL;
+  }
+  else
+  {
+    if ( ( Entry.OldDestComHandle = vsi_c_open (SndTaskHandle, Token ) ) == VSI_ERROR )
+      return RT_ERROR;
+    Entry.OldDestTaskHandle = Entry.OldDestComHandle;
+  }
+
+  if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
+    return RT_ERROR;
+  else
+    pChar += (len+1);
+
+  if ( !strcmp (Token, RT_TIMEOUT_TOKEN) ) 		
+  {
+    Entry.MsgType = RT_TIMEOUT_TYPE;
+    if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
+      return RT_ERROR;
+    else
+      pChar += (len+1);
+
+  }
+  else
+  {
+    if ( !strcmp (Token, RT_SIGNAL_TOKEN) )		
+    {
+      Entry.MsgType = RT_SIGNAL_TYPE;
+      if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
+        return RT_ERROR;
+      else
+        pChar += (len+1);
+    }
+    else
+      Entry.MsgType = RT_PRIMITIVE_TYPE;
+  } 
+
+  if ( (Token[0] == '1') || (Token[0] == '0') || (Token[0] == '*') )
+  {
+    rt_CvrtToOpcMask(Token, &Entry.opcMask, &Entry.opcStatus);
+    if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
+      return RT_ERROR;
+    else
+      pChar += (len+1);
+  }
+/*    else */
+  { 
+    if (!strcmp (Token, SYSPRIM_NULL_TOKEN))
+    {
+      if ( Entry.Command & RT_REDIRECT )
+      {
+        Entry.Command |= RT_DESTROY;  /* destroy the primitive */
+        Entry.Command &= ~RT_REDIRECT;  
+      }
+      else
+        return RT_ERROR;
+    }
+    else
+    {
+      if ( ( Entry.NewDestComHandle = vsi_c_open (SndTaskHandle, Token ) ) == VSI_ERROR )
+      {
+#ifdef _TOOLS_
+        if ( !strcmp ( FRM_PCO_NAME, Token ) )
+          return RT_ERROR;
+#endif
+        if ( ( Entry.NewDestComHandle = vsi_c_open (SndTaskHandle, FRM_TST_NAME ) ) != VSI_ERROR )
+        {
+          rt_tst_handle = Entry.NewDestComHandle;
+          if ( len < RESOURCE_NAMELEN )
+          {
+            strncpy( Entry.ExtDest, Token, RESOURCE_NAMELEN );
+            Entry.ExtDest[RESOURCE_NAMELEN-1] = 0;
+          }
+          else
+            return RT_ERROR;
+        }
+      }
+    }
+
+    if ( Entry.Command & RT_ALL_DESTINATION )
+    {
+      if ( (pEntry = Routing[SndTaskHandle]) != NULL )
+      {
+        int all_cleared = 1;
+        do
+        {
+          pNextEntry = (T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry;
+          if ( (pEntry->NewDestComHandle == Entry.NewDestComHandle )
+            && !strcmp(pEntry->ExtDest, Entry.ExtDest) )
+          {
+            if ( pEntry == Routing[SndTaskHandle] )
+            {
+              Routing[SndTaskHandle] = pEntry->pNextEntry;
+              if ( pEntry->pNextEntry != NULL )
+              {
+                ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
+              }
+            }
+            else
+            {
+              ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
+              if ( pEntry->pNextEntry != NULL )
+              {
+                ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
+              }
+            }
+            os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
+          }
+          else
+          {
+            all_cleared = 0;
+          }
+          pEntry = pNextEntry;
+        }
+        while ( pEntry );
+        if ( all_cleared == 1 )
+          Routing[SndTaskHandle] = NULL;
+      }
+    }
+
+    if ( (pChar >= RoutingString+ strlen (RoutingString)) 
+      || ((len = GetNextToken (pChar, Token, " #")) == 0) )
+      return ( rt_RoutingEntry(SndTaskHandle, &Entry, RT_STORE) );
+    else
+      pChar += (len+1);
+
+    if ( Entry.Command & RT_CLEAR_ENTRY )
+      return ( rt_RoutingEntry(SndTaskHandle, &Entry, RT_DELETE) );
+    return RT_ERROR;
+  }
+  
+}
+#endif
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_routePrim        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Looks if the task have some routing rules stored and
+            perform the redirection or duplication.
+
+*/
+
+GLOBAL SHORT rt_Route ( T_HANDLE SndTaskHandle, T_HANDLE RcvComHandle, USHORT Prio, ULONG Suspend, OS_QDATA *Msg )
+{
+T_FRM_ROUTING_TABLE_ENTRY *pEntry;
+
+T_PRIM_HEADER *prim;
+ULONG opc;
+
+  if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
+  {
+    if ( pEntry->MsgType == Msg->data16 )
+    { 
+      prim = (T_PRIM_HEADER*)Msg->ptr;
+
+#ifndef _TOOLS_
+      if (prim->opc & MEMHANDLE_OPC)
+      {
+        P_MEMHANDLE_SDU(prim)=0x00000000;
+      }
+#endif
+
+      do
+      {
+        if ( SndTaskHandle == pEntry->SndTaskHandle 
+         && ( (RcvComHandle == pEntry->OldDestComHandle) || (pEntry->OldDestComHandle == ROUTE_ALL) ) )
+        {
+        /*
+         * a route for the receiver is defined. Now
+         * check the filter conditions
+         */
+          opc = ((T_PRIM_HEADER*)Msg->ptr)->opc;
+          if ( (opc & pEntry->opcMask) == (pEntry->opcStatus & pEntry->opcMask) )
+          {
+          /*
+           * filter matched -> redirect, duplicate or destroy
+           * the primitive.
+           */
+            switch (pEntry->Command & RT_COMMAND_MASK)
+            {
+              case RT_DESTROY: 
+                /* add VSI_PPM_FREE(Msg->ptr) just to avoid the PPM warning of freeing a primitive in a queue */
+                VSI_PPM_RCV(Msg->ptr);
+                VSI_PPM_FREE(Msg->ptr);
+                os_DeallocatePartition (SndTaskHandle, Msg->ptr-PPM_OFFSET );
+                return RT_OK; 
+
+              case RT_REDIRECT:
+#ifndef _TOOLS_
+                if (pEntry->NewDestComHandle != rt_tst_handle)
+                {
+                  /* if not on tool side and not sending via TST -> send directly */
+                  Msg->e_id = pEntry->NewDestComHandle;
+                  return ( (SHORT)os_SendToQueue ( SndTaskHandle, pf_TaskTable[pEntry->NewDestComHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, Msg ) );
+                }
+#endif
+                /*lint -fallthrough */
+              case RT_DUPLICATE:
+                if (pEntry->NewDestComHandle != OS_ERROR)
+                {
+                  OS_QDATA QData;
+#ifdef _TOOLS_
+                  QData.len = (USHORT)(PSIZE(P2D(Msg->ptr))-sizeof(T_PRIM_HEADER));
+#else
+                  /* QData.len = 4; not needed if per reference */
+                  T_DP_HEADER *dp_hdr;
+#if 0                  
+                  P_ATTACH(P2D(prim));  /* recursivly increase use counters */
+#else
+                  prim->use_cnt++;
+                  if ( prim->dph_offset != 0 )
+                  {
+                    dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
+                    /* only increment use_cnt for dynamic primitives - not for DTI primitives */
+                    if ( dp_hdr->magic_nr == GUARD_PATTERN )
+                    {
+                      do
+                      {
+                        dp_hdr->use_cnt++;
+                      } while ( (dp_hdr = (T_DP_HEADER*)dp_hdr->next) != NULL );
+                    }
+                  }
+#endif /* 0 */
+
+#endif
+                  QData.data16 = MSG_PRIMITIVE;
+                  QData.ptr = Msg->ptr;
+
+#ifndef _TOOLS_
+                  if (pEntry->NewDestComHandle != rt_tst_handle)
+                  {
+                    Msg->e_id = pEntry->NewDestComHandle;
+                    os_SendToQueue ( SndTaskHandle, pf_TaskTable[pEntry->NewDestComHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, Msg );
+                  }
+                  else
+#endif
+                  {
+                    /* if on tool side or sending via TST -> send with sys header a.s.o */
+                    rt_ExtPrimitive ( SndTaskHandle, pEntry->NewDestComHandle, RcvComHandle, pEntry->ExtDest, &QData );
+                  }
+                }
+                if ( pEntry->Command & RT_REDIRECT )
+                {
+                  T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
+
+#ifndef _TOOLS_
+                  if ((prim->opc & MEMHANDLE_OPC) && (mem!=NULL))
+                  {
+                    if (P_MEMHANDLE(prim)!=0)
+                    {
+                      mem->dealloc(P_MEMHANDLE(prim));
+                    }
+                  }
+#endif /* !_TOOLS_ */
+                  
+                  vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
+                  return RT_OK; 
+                }
+                break;
+              default:
+                break;
+            }
+          }
+        }
+        pEntry = pEntry->pNextEntry;
+      } while ( pEntry );
+    }
+  }
+  
+  /*
+   * send original
+   */
+
+#ifdef _TOOLS_
+  return ( (SHORT)os_SendToQueue ( SndTaskHandle, RcvComHandle, Prio, Suspend, Msg ) );
+#else
+  if((pf_TaskTable[RcvComHandle].Flags & USE_LEMU_QUEUE) AND
+     (lemu_SendToQueue_func.magic_nr == LEMU_SENDTOQUEUE_INITIALIZED))
+  {
+    if(lemu_SendToQueue_func.plemu_SendToQueue( SndTaskHandle, RcvComHandle,
+             pf_TaskTable[RcvComHandle].QueueHandle, Prio, Suspend, Msg ) 
+             != lemu_SendToQueue_func.ret_ok  )
+    {
+      return OS_ERROR;
+    }
+    return OS_OK;
+  }
+  else
+  {
+    return ( (SHORT)os_SendToQueue ( SndTaskHandle, pf_TaskTable[RcvComHandle].QueueHandle, Prio, Suspend, Msg ) );
+  }
+#endif
+}
+#endif
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_ExtPrimitive     |
++--------------------------------------------------------------------+
+
+  PURPOSE : formats duplicated primitive to be sent to TST
+
+*/
+void rt_ExtPrimitive ( T_HANDLE TaskHandle, T_HANDLE DestComHandle, T_HANDLE OrgDestTaskHandle, char *ExtDest, OS_QDATA *Msg ) 
+{
+T_PRIM_HEADER *prim;
+#ifndef _TOOLS_
+T_PRIM_HEADER *sdu_prim;
+#endif /* not _TOOLS_ */
+T_PRIM_HEADER *ptr;
+T_S_HEADER *s_hdr;
+OS_QDATA DMsg;
+ULONG AllocSize;
+LONG Status;
+ULONG suspend;
+#ifdef _TOOLS_
+T_S_HEADER *prim_s_hdr;
+unsigned int i;
+#endif
+
+  prim = (T_PRIM_HEADER*)Msg->ptr;
+#ifdef _TOOLS_
+  AllocSize = S_ALLOC_SIZE(Msg->len + 1); /* +1 To add LF in TIF */
+#else
+  if ( prim->dph_offset != 0 )
+  {
+    T_DP_HEADER *dp_hdr;
+
+    dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
+    if ( dp_hdr->magic_nr != GUARD_PATTERN 
+#ifdef _TARGET_
+      && route_desclist[TaskHandle] == TRUE
+#endif
+         )
+    {
+      rt_desclist_to_sdu ( TaskHandle, DestComHandle, prim, &sdu_prim );
+      prim = sdu_prim;
+    }
+  }
+
+  AllocSize = S_ALLOC_SIZE(4 + 1);        /* only ptr to primitive */
+#endif /* _TOOLS_ */
+  suspend = get_suspend_state(TaskHandle,CHECK_PRIM_SUSPEND);
+  Status = os_AllocatePartition ( TaskHandle, (T_VOID_STRUCT**)&ptr, AllocSize, suspend, TestGroupHandle );
+  if ( Status == OS_OK || Status == OS_WAITED || Status == OS_ALLOCATED_BIGGER )
+  {
+    DMsg.data16 = MSG_PRIMITIVE;
+  	DMsg.data32 = Msg->data32;
+#ifdef _TOOLS_
+    DMsg.len = AllocSize;
+#endif
+    DMsg.ptr = (T_VOID_STRUCT*)ptr;
+
+    ptr->opc = prim->opc;
+    ptr->len = AllocSize;
+    ptr->sh_offset = S_HDR_OFFSET(AllocSize - sizeof(T_S_HEADER));
+    s_hdr = (T_S_HEADER*)((ULONG*)ptr + ptr->sh_offset);
+#ifdef _TOOLS_
+    if ( prim->sh_offset == 0 )
+    {
+      /* 
+         if the primitive is sent via the TAP REDIRECT TAP ... mechanism, then the prim->sh_offset
+         is zero and the org_rcv is filled corresponding to the original addressed entity name.
+      */
+      vsi_e_name ( TaskHandle, OrgDestTaskHandle, TaskName );
+      strcpy (s_hdr->org_rcv, TaskName);
+      strcpy (s_hdr->rcv, ExtDest);
+    }
+    else
+    {
+      /*
+         if the primitive is sent via the TAP TPORT mechanism then the original receiver is already 
+         filled by the TAP and copied to the newly allocated primitive to be routed.
+      */
+      prim_s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
+
+      for (i = 0; prim_s_hdr->org_rcv[i] != 0 && i < sizeof (s_hdr->org_rcv)-1; i++)
+        s_hdr->org_rcv[i] = prim_s_hdr->org_rcv[i];
+      for (i = 0; prim_s_hdr->rcv[i] != 0     && i < sizeof (s_hdr->rcv)-1;     i++)
+        s_hdr->rcv[i]     = prim_s_hdr->rcv[i];
+    }
+    get_local_time (&s_hdr->time);
+    os_GetTaskName ( TaskHandle, TaskHandle, TaskName );
+    strcpy (s_hdr->snd, TaskName);
+#else
+    vsi_e_name ( TaskHandle, OrgDestTaskHandle, TaskName );
+    strcpy (s_hdr->org_rcv, TaskName);
+    strcpy (s_hdr->rcv, ExtDest);
+    os_GetTime(TaskHandle,&s_hdr->time);
+    s_hdr->snd[0] = (char)(TaskHandle | HANDLE_BIT);
+#endif
+#ifdef _TOOLS_
+    memcpy ( (char*)P2D(ptr), P2D(Msg->ptr), Msg->len );
+#else
+    ((T_PRIM_X*)(ptr))->prim_ptr = prim;
+#endif
+    DMsg.e_id = DestComHandle;
+#ifdef _TOOLS_
+    os_SendToQueue ( TaskHandle, DestComHandle, OS_NORMAL, OS_SUSPEND, &DMsg );
+#else
+    if ((prim->opc & MEMHANDLE_OPC) && (mem!=NULL))
+    {
+      if (P_MEMHANDLE_SDU(prim)==0x00000000)
+      {
+        /* copy MEM-handle content into new sdu */
+        U8 *user_data;
+        U16 ptr_length;
+        user_data=mem->get_user_data(P_MEMHANDLE(prim), &ptr_length);
+
+        if (user_data)
+        {
+          T_sdu *sdu=(T_sdu *)M_ALLOC(ptr_length+2*sizeof(U16));
+
+          sdu->l_buf=ptr_length*8;
+          sdu->o_buf=0;
+          memcpy(sdu->buf,user_data,ptr_length);
+
+          P_MEMHANDLE_SDU(prim)=(U32)sdu;
+        }
+      }
+      else
+      {
+        M_ATTACH((void*)P_MEMHANDLE_SDU(prim));
+      }
+    }
+
+    if ( PrimAborted[TaskHandle] > 0 )
+    {
+      if ( vsi_o_ttrace ( 0, TC_SYSTEM, "%d %s primitive routings aborted",PrimAborted[TaskHandle], pf_TaskTable[TaskHandle].Name ) == VSI_OK )
+        PrimAborted[TaskHandle] = 0;
+    }
+    if ( os_SendToQueue ( TaskHandle, pf_TaskTable[DestComHandle].QueueHandle, OS_NORMAL, suspend, &DMsg ) == OS_TIMEOUT )
+    {
+      T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
+      vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
+      vsi_trc_free (0, (T_VOID_STRUCT**)&ptr);
+      PrimAborted[TaskHandle]++;
+    }
+#endif
+  }
+  else
+  {
+    T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
+    vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
+    PrimAborted[TaskHandle]++;
+  }
+}
+#endif
+
+#ifndef RUN_INT_RAM
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : PF_ROUTE            |
+| STATE   : code                       ROUTINE : rt_desclist_to_sdu  |
++--------------------------------------------------------------------+
+
+  PURPOSE : formats duplicated primitive with descriptor list into a 
+            primitive with SDU
+
+*/
+int rt_desclist_to_sdu ( T_HANDLE caller, T_HANDLE dst, T_PRIM_HEADER *prim, T_PRIM_HEADER **sdu_prim )
+{
+T_PRIM_HEADER *ptr;
+T_DP_HEADER *dp_hdr;
+T_M_HEADER *m_hdr;
+T_desc3 *desc3;
+T_desc2 *desc2;
+T_desc *desc;
+int len = 0;                   
+int sdu_prim_size = 0;
+char *fill_ptr;
+USHORT *l_buf_ptr;
+USHORT *o_buf_ptr;
+char *sdu_data_ptr;
+T_sdu *sdu = NULL;
+unsigned int new_opc;
+int desc_type = 0; 
+
+  dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
+  /* primitive contains descriptor list */
+
+  /*
+  START OF NON GENERIC CODE
+  This code is for the phase 1 routing of primitives containing descriptor lists.
+  It is non-generic and depends on the primitive ids defined in SAP docs.
+  It should be removed as soon as the generic descriptor list routing is ready
+  */
+  switch ( prim->opc )
+  {
+  case 0x7754: /* DTI2_DATA_IND */
+      new_opc = 0x7755; /* DTI2_DATA_TEST_IND */
+      desc_type = VSI_DESC_TYPE2 >> 16;
+      break;
+  case 0x3754: /* DTI2_DATA_REQ */
+      new_opc = 0x3755; /* DTI2_DATA_TEST_REQ */
+      desc_type = VSI_DESC_TYPE2 >> 16;
+      break;
+  case 0x6800: /* SN_DATA_IND */
+      new_opc = 0x6806; /* SN_DATA_TEST_IND */
+      desc_type = VSI_DESC_TYPE2 >> 16;
+      break;
+  case 0x2800: /* SN_DATA_REQ */
+      new_opc = 0x2806; /* SN_DATA_TEST_REQ */
+      desc_type = VSI_DESC_TYPE2 >> 16;
+      break;
+  case 0x6801: /* SN_UNITDATA_IND */
+      new_opc = 0x6807; /* SN_DATA_TEST_IND */
+      desc_type = VSI_DESC_TYPE2 >> 16;
+      break;
+  case 0x2801: /* SN_UNITDATA_REQ */
+      new_opc = 0x2807; /* SN_DATA_TEST_REQ */
+      desc_type = VSI_DESC_TYPE2 >> 16;
+      break;
+  case 0x7701: /* DTI_DATA_IND */
+      new_opc = 0x7702; /* DTI_DATA_TEST_IND */
+      desc_type = VSI_DESC_TYPE1 >> 16;
+      break;
+  case 0x3701: /* DTI_DATA_REQ */
+      new_opc = 0x3702; /* DTI_DATA_TEST_REQ */
+      desc_type = VSI_DESC_TYPE1 >> 16;
+      break;
+  case 0x80004097: /* GRLC_DATA_IND */
+      new_opc = 0x80014097; /* GRLC_DATA_IND_TEST */
+      desc_type = VSI_DESC_TYPE1 >> 16;
+      break;
+  case 0x80024097: /* GRLC_UNITDATA_IND */
+      new_opc = 0x80034097; /* GRLC_UNITDATA_IND_TEST */
+      desc_type = VSI_DESC_TYPE1 >> 16;
+      break;
+  default:
+      new_opc = prim->opc;
+      break;
+  }
+  /* END OF NON GENERIC CODE */
+
+  /* 
+  it has to be distinguished between T_desc, T_desc2 and T_desc3 because to length information
+  is located at different places inside the structure 
+  */
+  m_hdr = (T_M_HEADER*)(((T_desc_list*)dp_hdr)->first) - 1;
+  if ( m_hdr->desc_type != 0 )
+  {
+    desc_type = m_hdr->desc_type;
+  }
+  if ( desc_type == (VSI_DESC_TYPE2 >> 16) )
+  {
+    desc2 = (T_desc2*)(((T_desc_list2*)dp_hdr)->first);
+    while (desc2 != NULL)                         
+    {                                             
+      len = len + desc2->len;
+      desc2 = (T_desc2 *)desc2->next;                           
+    }
+    /* the size to be allocated for the primitive containing the sdu needs to be 
+                    root prim length  + data length + sdu size minus data buffer            - desc list2 size */
+    sdu_prim_size = prim->len         + len         + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list2);
+  }
+  else if ( desc_type == (VSI_DESC_TYPE1 >> 16) )
+  {
+    desc = (T_desc*)(((T_desc_list*)dp_hdr)->first);
+    while (desc != NULL)                         
+    {                                             
+      len = len + desc->len;
+      desc = (T_desc *)desc->next;                           
+    }
+    /* the size to be allocated for the primitive containing the sdu needs to be 
+                    root prim length  + data length + sdu size minus data buffer            - desc list size */
+    sdu_prim_size = prim->len         + len         + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list);
+  }
+  else if ( desc_type == (VSI_DESC_TYPE3 >> 16) )
+  {
+    /* it is assumed that type 3 is valid if not 1 or 2 */
+    desc3 = (T_desc3*)(((T_desc_list3*)dp_hdr)->first);
+    while (desc3 != NULL)                         
+    {                                             
+      len = len + desc3->len;
+      desc3 = (T_desc3 *)desc3->next;                           
+    }
+    /* the size to be allocated for the primitive containing the sdu needs to be 
+                    root prim length  + data length + sdu size minus data buffer            - desc list3 size */
+    sdu_prim_size = prim->len         + len         + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list3);
+  }
+  else 
+  {
+    vsi_o_ttrace ( 0, TC_SYSTEM, "unknown desc type in 0x%x, routing aborted", prim->opc );
+    vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
+    return RT_ERROR;
+  }
+
+  if ( sdu_prim_size < (int)MaxPrimPartSize )
+  {
+    ptr = (T_PRIM_HEADER*)vsi_c_new ( caller, sdu_prim_size, new_opc FILE_LINE_MACRO );
+  }
+  else
+  {
+    vsi_o_ttrace ( 0, TC_SYSTEM, "desclist in 0x%x too long, routing aborted", prim->opc );
+    vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
+    return RT_ERROR;
+  }
+#ifdef MEMORY_SUPERVISION
+  vsi_ppm_send ( caller, dst, (T_PRIM_HEADER*)ptr FILE_LINE_MACRO );
+#endif /* MEMORY_SUPERVISION */
+
+  fill_ptr = (char*)ptr;
+  l_buf_ptr =  &((T_sdu*)((int*)fill_ptr + prim->dph_offset))->l_buf;
+  o_buf_ptr =  &((T_sdu*)((int*)fill_ptr + prim->dph_offset))->o_buf;
+  sdu_data_ptr = (char*)&((T_sdu*)((int*)fill_ptr + prim->dph_offset))->buf;
+
+  memcpy ( (char*)P2D(fill_ptr), (char*)P2D(prim), prim->len-sizeof(T_PRIM_HEADER) );
+
+  *l_buf_ptr = 0;
+  *o_buf_ptr = 0;
+
+  fill_ptr = sdu_data_ptr;
+
+  if ( desc_type == (VSI_DESC_TYPE2 >> 16) )
+  {
+    desc2 = (T_desc2*)(((T_desc_list2*)dp_hdr)->first);
+    while (desc2 != NULL)                         
+    {                                             
+      *l_buf_ptr += (desc2->len*8);
+      memcpy ( fill_ptr, (char*)(&desc2->buffer)+desc2->offset, desc2->len );
+      fill_ptr += desc2->len;
+      desc2 = (T_desc2 *)desc2->next;                           
+    }
+  }
+  else if ( desc_type == (VSI_DESC_TYPE1 >> 16) )
+  {
+    desc = (T_desc*)(((T_desc_list*)dp_hdr)->first);
+    while (desc != NULL)                         
+    {                                             
+      *l_buf_ptr += (desc->len*8);
+      memcpy ( fill_ptr, (char*)(&desc->buffer), desc->len );
+      fill_ptr += desc->len;
+      desc = (T_desc *)desc->next;                           
+    }
+  }
+  else if ( desc_type == (VSI_DESC_TYPE3 >>16) )
+  {
+    desc3 = (T_desc3*)(((T_desc_list3*)dp_hdr)->first);
+    while (desc3 != NULL)                         
+    {                                             
+      *l_buf_ptr += (desc3->len*8);
+      memcpy ( fill_ptr, (char*)(desc3->buffer)+desc3->offset, desc3->len );
+      fill_ptr += desc3->len;
+      desc3 = (T_desc3 *)desc3->next;                           
+    }
+  }
+  vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
+  *sdu_prim = ptr;
+  return RT_OK;
+}
+#endif
+
+