FreeCalypso > hg > fc-magnetite
diff src/gpf3/frame/vsi_com.c @ 2:c41a534f33c6
src/gpf3: preened GPF goo from TCS3.2
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 25 Sep 2016 23:52:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gpf3/frame/vsi_com.c Sun Sep 25 23:52:50 2016 +0000 @@ -0,0 +1,2295 @@ +/* ++------------------------------------------------------------------------------ +| File: vsi_com.c ++------------------------------------------------------------------------------ +| 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 defines the virtual system interface part +| about communication via primitives and signals. ++----------------------------------------------------------------------------- +*/ + +#undef TEST_PCHECK + +#ifndef __VSI_COM_C__ +#define __VSI_COM_C__ +#endif + +/*==== INCLUDES ===================================================*/ + +#include "typedefs.h" +#include "string.h" +#include "os.h" +#include "vsi.h" +#include "frame.h" +#include "vsi.h" +#include "frm_defs.h" +#include "frm_types.h" +#include "frm_glob.h" +#include "route.h" + +#ifdef MEMORY_SUPERVISION + #include "tools.h" +#endif + +#ifdef _TOOLS_ + #include "stdlib.h" +#endif + +/*==== CONSTANTS ==================================================*/ + +#ifndef RUN_INT_RAM +char const *waited_queue_str= "Waited for space in queue"; +char const *freed_sent_str = "Freed partition sent"; +char const *disc_str = "Signal discarded"; +char const *freed_str = "Partition already freed"; +char const *trunc_str = "Allocation request truncated"; +char const *guard_str = "Partition guard pattern destroyed"; +char const *unknown_str = "unknown"; +#else +extern char const *waited_queue_str; +extern char const *freed_sent_str; +extern char const *disc_str; +extern char const *freed_str; +extern char const *trunc_str; +extern char const *guard_str; +extern char const *unknown_str; +#endif + +#if !defined _TARGET_ && !defined _TOOLS_ +char const *pcheck_str = "pcon_check() returned error"; +#define PCHECK_INITIALIZED 0xaffedead +#endif + + +#define MAX_DRP_BOUND 12 + +/*==== TYPES ======================================================*/ + +#if !defined _TARGET_ && !defined _TOOLS_ +typedef struct +{ + unsigned int magic_nr; + ULONG ret_ok; + ULONG (*pcheck)(ULONG opc, void * decoded_prim); +} T_PCHECK; +#endif + +/*==== EXTERNALS ==================================================*/ + +/* -------------- S H A R E D - BEGIN ---------------- */ +#ifdef _TOOLS_ +#pragma data_seg("FRAME_SHARED") +#endif + + +#ifdef _TOOLS_ + extern char FRM_TST_NAME[]; + __declspec (dllimport) T_HANDLE TST_Handle; +#else + extern T_HANDLE TST_Handle; +#endif + +extern T_HANDLE vsi_m_sem_handle; +extern char TaskName []; +//extern OS_HANDLE ext_data_pool_handle; +#if defined _NUCLEUS_ && defined NU_DEBUG + extern char check_desclist; +#endif + +/*==== VARIABLES ==================================================*/ + +#if !defined _TARGET_ && !defined _TOOLS_ +T_PCHECK pcheck_func; +#endif /* _TARGET_ */ + +#ifndef RUN_INT_RAM +char QueueName [ RESOURCE_NAMELEN ]; +//char *pf_com_matrix = NULL; +#else +extern char QueueName []; +#endif + +#ifdef _TOOLS_ +#pragma data_seg() +#endif +/* -------------- S H A R E D - END ---------------- */ + +/*==== PROTOTYPES =================================================*/ + +#if !defined _TARGET_ && !defined _TOOLS_ +#ifdef TEST_PCHECK +ULONG test_pcheck ( ULONG opc, void * decoded_prim ); +#endif +#endif /* _TARGET_ */ + + +#if defined _NUCLEUS_ && defined NU_DEBUG + int check_descriptor_list ( T_HANDLE caller, T_PRIM_HEADER *prim FILE_LINE_TYPE ); +#endif + +int int_vsi_c_pattach (T_VOID_STRUCT *prim FILE_LINE_TYPE); + + +/*==== FUNCTIONS ==================================================*/ + +#if 0 + not needed -> temporarily removed +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_open | ++--------------------------------------------------------------------+ + + PURPOSE : get the handle of a queue + +*/ + +char * vsi_c_init_com_matrix ( int max_entities ) +{ +int size; + + size = (max_entities+1)*(max_entities+1); + if ( os_AllocateMemory ( NO_TASK, (T_VOID_STRUCT**)&pf_com_matrix, size, OS_NO_SUSPEND, ext_data_pool_handle ) != OS_OK ) + { + vsi_o_assert ( NO_TASK, OS_SYST_ERR_NO_MEMORY, __FILE__, __LINE__, "No memory available for com matrix"); + } + return pf_com_matrix; +} +#endif + + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_get_com_matrix_entry| ++--------------------------------------------------------------------------+ + + PURPOSE : get an entry of the com matrix + +*/ + +int vsi_c_get_com_matrix_entry ( int entry, char *dst ) +{ +T_HANDLE snd, rcv; +static int cnt; +int size_of_matrix = (MaxEntities+1)*(MaxEntities+1); +int snd_len; + + if ( entry == FIRST_ENTRY ) + { + cnt = 0; + } + while ( cnt <= size_of_matrix ) + { + if ( pf_com_matrix[cnt] != 0 ) + { + snd = cnt/(MaxEntities+1); + vsi_e_name (NO_TASK, snd, &dst[0]); + snd_len = strlen(&dst[0]); + dst[snd_len]=' '; + rcv = cnt%(MaxEntities+1); + vsi_e_name (NO_TASK, rcv, &dst[snd_len+1]); + cnt++; + return VSI_OK; + } + cnt++; + } + return VSI_ERROR; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_get_entity_com_entry| ++--------------------------------------------------------------------------+ + + PURPOSE : get a entity handle the is used by an entity to send primitives + +*/ + +int vsi_c_get_entity_com_entry ( int entry, T_HANDLE rcv, T_HANDLE *snd ) +{ +static int cnt; +int size_of_matrix = (MaxEntities+1)*(MaxEntities+1); + + if ( entry == FIRST_ENTRY ) + { + cnt = rcv; + } + while ( cnt <= size_of_matrix ) + { + if ( pf_com_matrix[cnt] != 0 ) + { + *snd = cnt / (MaxEntities + 1); + cnt = cnt + MaxEntities + 1; + return VSI_OK; + } + cnt = cnt + MaxEntities + 1; + } + return VSI_ERROR; +} +#endif +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_open | ++--------------------------------------------------------------------+ + + PURPOSE : get the handle of a queue + +*/ + +T_HANDLE vsi_c_open (T_HANDLE Caller, char *Name) +{ +#ifdef _TOOLS_ +OS_HANDLE ComHandle; + + if ( os_OpenQueue ( Caller, Name, &ComHandle ) != OS_ERROR ) + return ComHandle; +#else +T_HANDLE e_handle; + + for ( e_handle = MaxEntities; e_handle > 0; e_handle-- ) + { + if ( pf_TaskTable[e_handle].Name[0] != 0 + && pf_TaskTable[e_handle].QueueHandle != 0 + && !strncmp (pf_TaskTable[e_handle].Name, Name, RESOURCE_NAMELEN-1) ) + { + /* + not needed -> temporarily removed + pf_com_matrix[Caller*(MaxEntities+1)+e_handle] = 1; + */ + return e_handle; + } + } +#endif + return VSI_ERROR; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_close | ++--------------------------------------------------------------------+ + + PURPOSE : return the handle of a queue + +*/ + +int vsi_c_close (T_HANDLE Caller, T_HANDLE ComHandle) +{ + + if ( os_CloseQueue ( Caller, ComHandle ) != OS_ERROR ) + return VSI_OK; + + return VSI_ERROR; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_clear | ++--------------------------------------------------------------------+ + + PURPOSE : read all messages from a queue + +*/ + +int vsi_c_clear (T_HANDLE Caller, T_HANDLE ComHandle) +{ +OS_QDATA Msg; + + while ( os_ReceiveFromQueue ( NO_TASK, ComHandle, &Msg, OS_NO_SUSPEND ) == OS_OK ) + { + ; + } + + return VSI_OK; +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_send | ++--------------------------------------------------------------------+ + + PURPOSE : write a message to a queue + +*/ + +int vsi_c_send (T_HANDLE Caller, T_HANDLE ComHandle, T_QMSG *Msg FILE_LINE_TYPE) +{ +OS_QDATA OS_Msg = { 0 }; +LONG Status; +USHORT Prio; +#ifdef NU_DEBUG +T_PRIM_HEADER *prim; + #ifdef _TARGET_ + T_HANDLE t_handle; + #endif +#endif + + OS_Msg.data16 = Msg->MsgType; + OS_Msg.e_id = ComHandle; + switch ( Msg->MsgType ) + { + case MSG_PRIMITIVE: + OS_Msg.ptr = Msg->Msg.Primitive.Prim; + OS_Msg.data32 = P_OPC(Msg->Msg.Primitive.Prim); +#ifdef _TOOLS_ + OS_Msg.len = Msg->Msg.Primitive.PrimLen; +#endif + os_GetTime ( 0, &OS_Msg.time ); + Prio = MSG_PRIMITIVE_PRIO; + break; + case MSG_SIGNAL: + OS_Msg.ptr = Msg->Msg.Signal.SigBuffer; + OS_Msg.data32 = Msg->Msg.Signal.SigOPC; +#ifdef _TOOLS_ + OS_Msg.len = Msg->Msg.Signal.SigLen; +#endif + os_GetTime ( 0, &OS_Msg.time ); + Prio = MSG_SIGNAL_PRIO; + break; + default: return VSI_ERROR; + /*lint -e527 suppress Warning -- Unreachable */ + break; + /*lint +e527 */ + } + +#ifdef _NUCLEUS_ +#ifdef NU_DEBUG + /* PARTITION GUARD PATTERN CHECK */ + if ( Msg->MsgType == MSG_PRIMITIVE ) + { + prim = (T_PRIM_HEADER*)Msg->Msg.Primitive.Prim; + if ( (Status = os_PartitionCheck ( (T_VOID_STRUCT*)prim )) == OS_OK ) + { + if ( check_desclist == TRUE && prim->dph_offset != 0 ) + { + check_descriptor_list ( Caller, prim FILE_LINE ); + } + } + else + { + switch ( Status ) + { + case OS_PARTITION_FREE: + vsi_o_assert ( Caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "%s (PSEND),entity %s, partition 0x%x, opc 0x%x", + freed_sent_str, pf_TaskTable[Caller].Name, prim, prim->opc ); + break; + case OS_PARTITION_GUARD_PATTERN_DESTROYED: + vsi_o_assert ( Caller, OS_SYST_ERR_PCB_PATTERN FILE_LINE_MACRO_PASSED, + "%s (PSEND), entity %s, partition 0x%x, opc 0x%x", + guard_str, pf_TaskTable[Caller].Name, prim, prim->opc ); + break; + default: + break; + } + } +#ifdef MEMORY_SUPERVISION + vsi_ppm_send ( Caller, ComHandle, (T_PRIM_HEADER*)Msg->Msg.Primitive.Prim, file, line ); +#endif /* MEMORY_SUPERVISION */ + } +#ifdef _TARGET_ + if ( (t_handle = os_MyHandle()) != 0 ) + { + int opc; + switch ( os_CheckTaskStack ( t_handle ) ) + { + case OS_ERROR: + if ( Msg->MsgType == MSG_PRIMITIVE ) + { + opc = ((T_PRIM_HEADER*)Msg->Msg.Primitive.Prim)->opc; + } + else + { + opc = Msg->Msg.Signal.SigOPC; + } + vsi_o_assert ( Caller, OS_SYST_ERR_STACK_OVERFLOW FILE_LINE_MACRO_PASSED, + "%s Stack overflow, 0x%x", pf_TaskTable[Caller].Name, opc ); + break; + default: + break; + } + } +#endif /* _TARGET_ */ +#endif /* NU_DEBUG */ +#endif /* _NUCLEUS_ */ + + Status = rt_Route ( Caller, ComHandle, Prio, OS_SUSPEND, &OS_Msg ); + + switch ( Status ) + { + case OS_WAITED: +#ifdef NU_DEBUG + pf_handle_warning ( OS_SYST_WRN_WAIT_QUEUE, "%s %s, entity %s, queue %s, %s(%d)", + syst_wrn, waited_queue_str, pf_TaskTable[Caller].Name, pf_TaskTable[ComHandle].Name FILE_LINE_MACRO_PASSED ); +#endif + return VSI_OK; + /*lint -e527 suppress Warning -- Unreachable */ + break; + /*lint +e527 */ + case OS_TIMEOUT: + case OS_ERROR: + case OS_INVALID_QUEUE: + Caller = e_running[os_MyHandle()]; + if ( Msg->MsgType == MSG_SIGNAL ) + { +#ifdef NU_DEBUG + pf_handle_warning ( OS_SYST_WRN_WAIT_QUEUE, "%s %s from %s to %s, opc 0x%x, %s(%d)", + syst_wrn, disc_str, pf_TaskTable[Caller].Name, pf_TaskTable[ComHandle].Name, Msg->Msg.Signal.SigOPC FILE_LINE_MACRO_PASSED ); +#endif + return VSI_OK; + } + else + { + char const *p_queue_name; + if ( Status == OS_INVALID_QUEUE ) + { + p_queue_name = unknown_str; + } + else + { +#ifdef _TOOLS_ + os_GetQueueName ( Caller, ComHandle, QueueName ); + p_queue_name = QueueName; +#else + p_queue_name = pf_TaskTable[ComHandle].Name; +#endif + } + vsi_o_assert ( Caller, OS_SYST_ERR_QUEUE_FULL FILE_LINE_MACRO_PASSED, + "%s write attempt to %s queue failed", + pf_TaskTable[Caller].Name, p_queue_name ); +#ifdef MEMORY_SUPERVISION + vsi_ppm_free ( Caller, (T_PRIM_HEADER*)(OS_Msg.ptr-PPM_OFFSET), file, line); +#endif + os_DeallocatePartition (Caller, OS_Msg.ptr-PPM_OFFSET ); + return VSI_ERROR; + } + /*lint -e527 suppress Warning -- Unreachable */ + break; + /*lint +e527 */ + case OS_OK: + return VSI_OK; + /*lint -e527 suppress Warning -- Unreachable */ + break; + /*lint +e527 */ + default: + return VSI_ERROR; + /*lint -e527 suppress Warning -- Unreachable */ + break; + /*lint +e527 */ + } + +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_psend | ++--------------------------------------------------------------------+ + + PURPOSE : wrapper for vsi_c_send to avoid code wasting macro + +*/ +int vsi_c_psend_caller ( T_HANDLE Caller, T_HANDLE ComHandle, T_VOID_STRUCT *ptr FILE_LINE_TYPE ) +{ +T_QMSG QMsg; +T_VOID_STRUCT *snd_ptr = (T_VOID_STRUCT*)D2P(ptr); + + QMsg.Msg.Primitive.Prim = snd_ptr; +#ifdef _TOOLS_ + if ( ((T_PRIM_HEADER*)snd_ptr)->sh_offset != 0 ) + QMsg.Msg.Primitive.PrimLen = ALIGN(PSIZE(ptr)) + sizeof(T_S_HEADER); + else +#endif + QMsg.Msg.Primitive.PrimLen = PSIZE(ptr); + QMsg.MsgType = MSG_PRIMITIVE; + if ( Caller != TST_Handle && !(P_OPC(QMsg.Msg.Primitive.Prim) & SYS_MASK ) ) + vsi_o_ptrace (Caller, P_OPC(QMsg.Msg.Primitive.Prim), 1); + +#if !defined _TARGET_ && !defined _TOOLS_ + if ( (pcheck_active[Caller] == 1) && (pcheck_func.pcheck != NULL) ) + { + ULONG ret; + if ( (ret = pcheck_func.pcheck ( D_OPC(ptr), ptr )) != pcheck_func.ret_ok ) + { + pf_handle_warning ( OS_SYST_WRN, "%s %s %d in %s, opc 0x%x, %s(%d)", + syst_wrn, pcheck_str, ret, pf_TaskTable[Caller].Name, D_OPC(ptr) FILE_LINE_MACRO_PASSED ); + } + } +#endif + return ( vsi_c_send ( Caller, ComHandle, &QMsg FILE_LINE) ); +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_psend | ++--------------------------------------------------------------------+ + + PURPOSE : wrapper for vsi_c_send to avoid code wasting macro + +*/ +int vsi_c_psend ( T_HANDLE ComHandle, T_VOID_STRUCT *ptr FILE_LINE_TYPE ) +{ +T_HANDLE Caller; + + Caller = e_running[os_MyHandle()]; + + return ( vsi_c_psend_caller ( Caller, ComHandle, ptr FILE_LINE) ); +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_ssend | ++--------------------------------------------------------------------+ + + PURPOSE : wrapper for vsi_c_send to avoid code wasting macro + +*/ +int vsi_c_ssend ( T_HANDLE ComHandle, ULONG opc, T_VOID_STRUCT *ptr, + ULONG MsgLen FILE_LINE_TYPE ) +{ +T_QMSG QMsg; +T_HANDLE Caller; + + Caller = e_running[os_MyHandle()]; + + QMsg.Msg.Signal.SigBuffer = (T_VOID_STRUCT*)ptr; + QMsg.Msg.Signal.SigOPC = opc; + QMsg.Msg.Signal.SigLen = MsgLen; + QMsg.MsgType = MSG_SIGNAL; + + return ( vsi_c_send ( Caller, ComHandle, &QMsg FILE_LINE ) ); + +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_new | ++--------------------------------------------------------------------+ + + PURPOSE : allocate a partition to send a primitive + +*/ + +T_VOID_STRUCT * vsi_c_new (T_HANDLE Caller, ULONG Size, ULONG opc FILE_LINE_TYPE) +{ +T_VOID_STRUCT *prim; +ULONG flags; + + /* VSI_MEM_NON_BLOCKING not set, blocking allocation for backwards compatibility */ + flags = PrimGroupHandle; + prim = (T_VOID_STRUCT*)D2P(vsi_c_pnew_generic (Caller, Size, opc, flags FILE_LINE)); + return prim; + +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_new | ++--------------------------------------------------------------------+ + + PURPOSE : allocate a partition to send a primitive + +*/ + +T_VOID_STRUCT * vsi_c_pnew_generic (T_HANDLE Caller, ULONG Size, ULONG opc, ULONG flags FILE_LINE_TYPE) +{ +T_VOID_STRUCT *prim; + + if ( Size < sizeof(T_PRIM_HEADER) ) + Size = sizeof(T_PRIM_HEADER); + + if ( (prim = vsi_m_new ( Size, flags FILE_LINE )) != NULL ) + { + P_OPC(prim) = opc; + P_LEN(prim) = Size; + P_SDU(prim) = NULL; + P_CNT(prim) = 1; + P_SHO(prim) = 0; + P_DPHO(prim) = 0; +#ifdef MEMORY_SUPERVISION + Caller = e_running[os_MyHandle()]; + vsi_ppm_new ( Caller, Size, (T_PRIM_HEADER*)prim, file, line ); +#endif + +#ifndef _TOOLS_ + if (opc & MEMHANDLE_OPC) + { + P_MEMHANDLE_SDU(prim)=0x00000000; + } +#endif + + return (T_VOID_STRUCT*)P2D(prim); + } + return NULL; + +} +#endif +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_pnew | ++--------------------------------------------------------------------+ + + PURPOSE : allocate a partition to send a primitive + +*/ + +T_VOID_STRUCT * vsi_c_pnew (ULONG Size, ULONG opc FILE_LINE_TYPE) +{ +T_HANDLE Caller; + + Caller = 0; + + Size += sizeof(T_PRIM_HEADER); + + return ( (T_VOID_STRUCT*)vsi_c_pnew_generic ( Caller, Size, opc, PrimGroupHandle FILE_LINE )); +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_pnew | ++--------------------------------------------------------------------+ + + PURPOSE : allocate a partition to send a primitive + +*/ + +T_VOID_STRUCT * vsi_c_pnew_nb (ULONG Size, ULONG opc FILE_LINE_TYPE) +{ +T_HANDLE Caller; + + Caller = 0; + + Size += sizeof(T_PRIM_HEADER); + + return ( (T_VOID_STRUCT*)vsi_c_pnew_generic ( Caller, Size, opc, VSI_MEM_NON_BLOCKING|PrimGroupHandle FILE_LINE )); +} +#endif + +#ifndef RUN_FLASH +/* ++---------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_new_sdu_generic| ++---------------------------------------------------------------------+ + + PURPOSE : allow pool selection and flags for blocking bahavior + +*/ +T_VOID_STRUCT * vsi_c_new_sdu_generic (ULONG Size, ULONG opc, USHORT sdu_len, USHORT sdu_offset, USHORT encode_offset, ULONG flags FILE_LINE_TYPE ) +{ +T_PRIM_HEADER *prim; +ULONG alloc_size; +T_HANDLE Caller; + + Caller = 0; + alloc_size = Size + sizeof(T_PRIM_HEADER) + BYTELEN((SHORT)sdu_len + (SHORT)encode_offset); + if ( (prim = (T_PRIM_HEADER*)vsi_c_pnew_generic (Caller, alloc_size, opc, flags FILE_LINE)) != NULL ) + { + D_SDU(prim) = (T_sdu*)(((char*)prim) + sdu_offset); + D_SDU_LEN(prim) = sdu_len; + D_SDU_OFF(prim) = encode_offset; + return ( (T_VOID_STRUCT*)prim ); + } + else + { + return NULL; + } +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_new_sdu | ++--------------------------------------------------------------------+ + + PURPOSE : wrapper for vsi_c_new to avoid code wasting macro + +*/ +T_VOID_STRUCT * vsi_c_new_sdu (ULONG Size, ULONG opc, USHORT sdu_len, USHORT sdu_offset, USHORT encode_offset FILE_LINE_TYPE ) +{ +ULONG flags; + + flags = PrimGroupHandle; + + return vsi_c_new_sdu_generic (Size, opc, sdu_len, sdu_offset, encode_offset, flags FILE_LINE); +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_ppass | ++--------------------------------------------------------------------+ + + PURPOSE : pass a partition from one primitive to another + +*/ +T_VOID_STRUCT * vsi_c_ppass (T_VOID_STRUCT *prim, ULONG opc FILE_LINE_TYPE ) +{ +T_VOID_STRUCT *ptr; +ULONG len; +T_HANDLE Caller; + + Caller = e_running[os_MyHandle()]; + if ( D_CNT(prim) > 1 ) + { + /* + * This does not work for dynamic primitive containing pointers, PDUP needed !!!! + * The sdu pointer is currently not set correctly because it is never used !!! + */ + len = D_LEN(prim); + ptr = vsi_c_pnew ( len, opc FILE_LINE ); + memcpy ( ptr, prim, len - sizeof(T_PRIM_HEADER) ); +#ifdef PRIM_AUTO_FREE + if ( !(pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE) ) +#endif + vsi_c_pfree ( &prim FILE_LINE ); + return ptr; + } + else + { + D_OPC(prim) = opc; +#ifdef PRIM_AUTO_FREE + if ( pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE ) + { + D_CNT(prim)++; + } +#endif +#ifdef MEMORY_SUPERVISION + vsi_ppm_reuse ( Caller, D2P(prim), file, line); +#endif + return prim; + } + +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_pstore | ++--------------------------------------------------------------------+ + + PURPOSE : store a partition (increment the reference counter) + consider PARTITION_AUTO_FREE + +*/ +void vsi_c_pstore ( T_VOID_STRUCT *prim FILE_LINE_TYPE ) +{ +#ifdef PRIM_AUTO_FREE +T_PRIM_HEADER *ptr; +T_DP_HEADER *dp_hdr; +T_HANDLE Caller; + + Caller = e_running[os_MyHandle()]; + if ( pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE ) + { + ptr = D2P(prim); + /* take control -> enable entity to free the prim */ + processed_prim[Caller] = NULL; + /* increment reference counter */ + D_CNT(prim)++; +#ifdef MEMORY_SUPERVISION + vsi_ppm_store ( Caller, ptr, file, line ); +#endif + if ( P_DPHO(ptr) != 0 ) + { + dp_hdr = (T_DP_HEADER*)((ULONG*)ptr + ptr->dph_offset); + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + while ( (ptr = (T_PRIM_HEADER*)dp_hdr) != NULL ) + { +#ifdef MEMORY_SUPERVISION + vsi_ppm_store ( Caller, ptr, file, line ); +#endif + P_CNT(ptr)++; + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + vsi_o_assert ( Caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "Magic number in dp_header destroyed (PSTORE) %s , opc: 0x%lx, partition 0x%lx", + pf_TaskTable[Caller].Name, ptr->opc, ptr ); + } + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + } + } + } +#endif /* PRIM_AUTO_FREE */ +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_pattach | ++--------------------------------------------------------------------+ + + PURPOSE : call internal function to store a partition (increment the reference counter) + +*/ +int vsi_c_pattach ( T_VOID_STRUCT *prim FILE_LINE_TYPE ) +{ +T_HANDLE Caller = 0; +LONG sts; +int ret; + + sts = os_ObtainSemaphore (Caller, vsi_m_sem_handle, OS_SUSPEND); + if ( sts == OS_ERROR || sts == OS_TIMEOUT ) + { + /* Semaphore invalid or overrun */ + Caller = e_running[os_MyHandle()]; + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "Ref Cnt Semaphore overrun, entity %s", pf_TaskTable[Caller].Name ); + } + + ret=int_vsi_c_pattach(prim FILE_LINE_MACRO); + + os_ReleaseSemaphore (Caller, vsi_m_sem_handle); + + return ret; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : int_vsi_c_pattach | ++--------------------------------------------------------------------+ + + PURPOSE : actually store a partition (increment the reference counter) + +*/ +int int_vsi_c_pattach ( T_VOID_STRUCT *prim FILE_LINE_TYPE) +{ +T_PRIM_HEADER *ptr; +T_DP_HEADER *dp_hdr; +T_HANDLE Caller = 0; +int pos; + + ptr = D2P(prim); + +#ifdef NU_DEBUG + if ( os_is_valid_partition ((T_VOID_STRUCT*)ptr) ) + { + /* attach to non-partition memory */ + Caller = e_running[os_MyHandle()]; + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "PATTACH to non-partition memory, entity %s, ptr 0x%x", pf_TaskTable[Caller].Name, ptr ); + } +#endif + + if ( ptr->use_cnt <= 0 ) + { + /* attach to non allocated memory */ + Caller = e_running[os_MyHandle()]; + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "PATTACH to free memory, entity %s, ptr 0x%x", pf_TaskTable[Caller].Name, ptr ); + } + + dp_hdr=NULL; + + /* check if we have a primitive pointer */ + if ( ((T_DP_HEADER*)ptr)->magic_nr != GUARD_PATTERN ) + { + /* increment reference counter */ + P_CNT(ptr)++; + #ifdef MEMORY_SUPERVISION + vsi_ppm_store ( Caller, ptr, file, line ); + #endif + + /* look for dynamic partition header */ + if ( P_DPHO(ptr) != 0 ) + { + dp_hdr = (T_DP_HEADER*)((ULONG*)ptr + ptr->dph_offset); + if (dp_hdr->drp_bound_list) + { + /* call attach for bound root pointers */ + pos=0; + while(pos<MAX_DRP_BOUND && dp_hdr->drp_bound_list[pos]) + { + int_vsi_c_pattach(dp_hdr->drp_bound_list[pos] FILE_LINE_MACRO); + pos++; + } + } + + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + } + } + else + { + dp_hdr=(T_DP_HEADER*)ptr; + } + + if ( dp_hdr ) + { + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + /* primitive with T_desc_list element, use MATTACH */ + os_ReleaseSemaphore (Caller, vsi_m_sem_handle); + return VSI_OK; + } + else + { + while ( (ptr = (T_PRIM_HEADER*)dp_hdr) != NULL ) + { +#ifdef MEMORY_SUPERVISION + vsi_ppm_store ( Caller, ptr, file, line ); +#endif + P_CNT(ptr)++; + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + vsi_o_assert ( Caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "Magic number in dp_header destroyed (PATTACH), %s, opc: 0x%lx, partition 0x%lx", + pf_TaskTable[Caller].Name, ptr->opc, ptr ); + } + + if (dp_hdr->drp_bound_list) + { + /* call attach for bound root pointers */ + pos=0; + while(pos<MAX_DRP_BOUND && dp_hdr->drp_bound_list[pos]) + { + int_vsi_c_pattach(dp_hdr->drp_bound_list[pos] FILE_LINE_MACRO); + pos++; + } + } + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + } + } + } + return VSI_OK; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_reuse | ++--------------------------------------------------------------------+ + + PURPOSE : function to avoid code wasting macro + +*/ +T_VOID_STRUCT *vsi_c_reuse ( T_PRIM_HEADER *ptr, ULONG Size, ULONG opc, + USHORT sdu_len, USHORT sdu_offset, USHORT encode_offset FILE_LINE_TYPE ) +{ +T_HANDLE Caller; + + D_OPC(ptr) = opc; + D_LEN(ptr) = Size; + if ( sdu_offset != NO_SDU ) + { + D_SDU(ptr) = (T_sdu*)((char*)(ptr) + sdu_offset); + D_SDU_LEN(ptr) = sdu_len; + D_SDU_OFF(ptr) = encode_offset; + } + else + D_SDU(ptr) = NULL; + + Caller = e_running[os_MyHandle()]; +#ifdef MEMORY_SUPERVISION + vsi_ppm_reuse ( Caller, D2P(ptr), file, line); +#endif +#ifdef PRIM_AUTO_FREE + if ( pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE ) + { + D_CNT(ptr)++; + } +#endif + return ( (T_VOID_STRUCT*)ptr ); +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_free | ++--------------------------------------------------------------------+ + + PURPOSE : deallocate a partition that was used to send a primitive + +*/ + +int vsi_c_free (T_HANDLE Caller, T_VOID_STRUCT **Msg FILE_LINE_TYPE) +{ +static T_VOID_STRUCT *protected_prim_to_free = NULL; +#if defined (NU_DEBUG) || defined (OSL_DEBUG) +LONG count; +#endif + +//LONG sts; + +#if 0 + sts = os_ObtainSemaphore (Caller, vsi_m_sem_handle, OS_SUSPEND); + if ( sts == OS_ERROR || sts == OS_TIMEOUT ) + { + /* Semaphore invalid or overrun */ + if ( *Msg == protected_prim_to_free ) + { + /* fatal error only if semaphore overrun on same primitive */ + Caller = e_running[os_MyHandle()]; + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "Ref Cnt Semaphore overrun, entity %s", pf_TaskTable[Caller].Name ); + return VSI_ERROR; + } + } + else +#endif + { + protected_prim_to_free = *Msg; + } +#if defined (NU_DEBUG) || defined (OSL_DEBUG) + count = (LONG)((T_PRIM_HEADER*)*Msg)->use_cnt; + if ( count <= 0 ) + { + pf_handle_warning ( OS_SYST_WRN_MULTIPLE_FREE, "%s %s in %s, 0x%x, %s(%d)", + syst_wrn, freed_str, pf_TaskTable[Caller].Name, P_OPC(*Msg) FILE_LINE_MACRO_PASSED ); + protected_prim_to_free = NULL; + // os_ReleaseSemaphore (Caller, vsi_m_sem_handle); + return VSI_OK; + } +#endif + if ( --((T_PRIM_HEADER*)*Msg)->use_cnt == 0 ) + { +#ifdef PRIM_AUTO_FREE + if ( pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE ) + freed_prim[Caller] = *Msg; +#endif +#ifdef _NUCLEUS_ +#ifdef NU_DEBUG + + if ( os_PartitionCheck( (ULONG*)*Msg ) == OS_PARTITION_GUARD_PATTERN_DESTROYED ) + { +// os_ReleaseSemaphore (Caller, vsi_m_sem_handle); + vsi_o_assert ( Caller, OS_SYST_ERR_PCB_PATTERN FILE_LINE_MACRO_PASSED, + "%s (PFREE), entity %s,Partition 0x%x", + guard_str, pf_TaskTable[Caller].Name, *Msg ); + return VSI_ERROR; + } +#endif +#endif + protected_prim_to_free = NULL; +// os_ReleaseSemaphore (Caller, vsi_m_sem_handle); + return ( vsi_m_free ( Msg FILE_LINE ) ); + } + + protected_prim_to_free = NULL; +// os_ReleaseSemaphore (Caller, vsi_m_sem_handle); + return VSI_OK; +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_pfree | ++--------------------------------------------------------------------+ + + PURPOSE : deallocate a partition that was used to send a primitive + +*/ + +int vsi_c_pfree (T_VOID_STRUCT **Msg FILE_LINE_TYPE) +{ +T_VOID_STRUCT *free_ptr; +T_HANDLE Caller; + + /* + * PFREE is disabled if the primitive to be freed is the currently + * processed one and the auto free is enabled for the calling entity + */ + + Caller = e_running[os_MyHandle()]; + free_ptr = (T_VOID_STRUCT*)D2P(*Msg); +#ifdef NU_DEBUG + if ( os_is_valid_partition ((T_VOID_STRUCT*)free_ptr) ) + { + /* free to non-partition memory */ + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "PFREE to non-partition memory, entity %s, prim 0x%x", pf_TaskTable[Caller].Name, *Msg ); + } +#endif +#ifdef PRIM_AUTO_FREE + if ( free_ptr == processed_prim[Caller] && pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE ) + { + return VSI_OK; + } +#endif /* PRIM_AUTO_FREE */ + return ( vsi_c_free ( Caller, &free_ptr FILE_LINE ) ); +} +#endif + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_await | ++--------------------------------------------------------------------+ + + PURPOSE : receive a primitive + +*/ + +int vsi_c_await (T_HANDLE Caller, T_HANDLE ComHandle, T_QMSG *Msg, ULONG Timeout) +{ +OS_QDATA OS_Msg; +LONG ret; +OS_HANDLE q_handle; + + +#ifdef _TOOLS_ + q_handle = ComHandle; +#else + q_handle = pf_TaskTable[ComHandle].QueueHandle; +#endif + e_running[os_MyHandle()] = 0; + + if ( (ret = os_ReceiveFromQueue ( Caller, q_handle, &OS_Msg, Timeout)) == OS_OK ) + { + Msg->MsgType = OS_Msg.data16; + switch ( Msg->MsgType ) + { + case MSG_PRIMITIVE: + Msg->Msg.Primitive.Prim = OS_Msg.ptr; +#ifdef _TOOLS_ + Msg->Msg.Primitive.PrimLen = OS_Msg.len; +#endif + vsi_o_ptrace (Caller, ((T_PRIM_HEADER*)Msg->Msg.Primitive.Prim)->opc, 0); + break; + case MSG_SIGNAL: + Msg->Msg.Signal.SigBuffer = OS_Msg.ptr; + Msg->Msg.Signal.SigOPC = OS_Msg.data32; +#ifdef _TOOLS_ + Msg->Msg.Signal.SigLen = OS_Msg.len; +#endif + break; + case MSG_TIMEOUT: + if ( *(pf_TaskTable[Caller].FirstTimerEntry + OS_Msg.data32) & TIMEOUT_OCCURRED ) + { + if ( !(*(pf_TaskTable[Caller].FirstTimerEntry + OS_Msg.data32) & PERIODIC_TIMER) ) + { + os_DestroyTimer ( Caller, (OS_HANDLE)(*(pf_TaskTable[Caller].FirstTimerEntry + OS_Msg.data32) & TIMER_HANDLE_MASK) ); + *(pf_TaskTable[Caller].FirstTimerEntry + OS_Msg.data32) = 0; + } + else + { + *(pf_TaskTable[Caller].FirstTimerEntry + OS_Msg.data32) &= ~TIMEOUT_OCCURRED; + } + Msg->Msg.Timer.Index = OS_Msg.data32; + } + break; + default: return VSI_ERROR; + /*lint -e527 suppress Warning -- Unreachable */ + break; + /*lint +e527 */ + } + e_running[os_MyHandle()] = Caller; + prf_log_entity_activate ((void*)Caller); + return VSI_OK; + } + else + { + if ( ret == OS_TIMEOUT ) + { + e_running[os_MyHandle()] = Caller; + return VSI_TIMEOUT; + } + } + return VSI_ERROR; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_primitive | ++--------------------------------------------------------------------+ + + PURPOSE : send a non GSM primitive to the frame + +*/ + +int vsi_c_primitive (T_HANDLE Caller, void *Msg) +{ + /* + * the following line of code causes a warning on tms470 compiler, that cannot be avoided + * without changing all entities PEI modules. Warning will not cause a problem + */ + pf_ProcessSystemPrim ( Caller, Msg ); + return VSI_OK; + +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_awake | ++--------------------------------------------------------------------+ + + PURPOSE : send NULL primitive to itself + +*/ +GLOBAL int vsi_c_awake ( T_HANDLE caller ) +{ +OS_QDATA QMsg = { 0 }; + + QMsg.data16 = MSG_PRIMITIVE; + QMsg.ptr = NULL; + os_SendToQueue ( caller, caller, OS_URGENT, OS_NO_SUSPEND, &QMsg ); + return VSI_OK; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_status | ++--------------------------------------------------------------------+ + + PURPOSE : allocate root of dynamic sized primitive + +*/ +int vsi_c_status (T_HANDLE handle, unsigned int *used, unsigned int *free) +{ +#ifdef _NUCLEUS_ +int status; + + if ( (status = os_GetQueueState (0, pf_TaskTable[handle].QueueHandle, (ULONG*)used, (ULONG*)free)) == OS_OK ) + return OS_OK; + else +#endif + return OS_ERROR; + +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_drpo_new | ++--------------------------------------------------------------------+ + + PURPOSE : allocate root of dynamic sized primitive + +*/ +GLOBAL T_VOID_STRUCT *vsi_drpo_new ( ULONG size, ULONG opc, ULONG guess FILE_LINE_TYPE ) +{ +T_PRIM_HEADER *prim; +T_DP_HEADER *dp_hdr; +T_S_HEADER *s_hdr; +ULONG alloc_size; +ULONG partition_size; +ULONG header_size; +T_HANDLE caller; + + caller = e_running[os_MyHandle()]; + + header_size = sizeof(T_PRIM_HEADER) + sizeof(T_DP_HEADER); + + if ( ALIGN(header_size + size) > MaxPrimPartSize ) + { + os_GetTaskName ( caller, caller, TaskName ); + vsi_o_assert ( NO_TASK, OS_SYST_ERR_BIG_PARTITION FILE_LINE_MACRO_PASSED, + "No Partition available, entity %s, size %d", pf_TaskTable[caller].Name, size ); + return NULL; + } + + if ( guess == DP_NO_FRAME_GUESS ) + alloc_size = ALIGN(header_size + size); + else if ( guess == DP_FRAME_GUESS ) + alloc_size = ALIGN(header_size + size * 3); + else + alloc_size = ALIGN(header_size + guess + size); + + if ( caller != 0 && caller == TST_Handle ) + { + /* + if called by PCON in the test interface while decoding we need to reserve + space for the S_HEADER + */ + alloc_size += sizeof(T_S_HEADER); + } + + if ( alloc_size > MaxPrimPartSize ) + { +#ifdef NU_DEBUG + pf_handle_warning ( OS_SYST_WRN_REQ_TRUNCATED, "%s %s (%d->%d), entity %s, opc 0x%x, %s(%d)", + syst_wrn, trunc_str, alloc_size, MaxPrimPartSize, pf_TaskTable[caller].Name, opc FILE_LINE_MACRO_PASSED ); +#endif + alloc_size = MaxPrimPartSize; + } + if ( ( prim = (T_PRIM_HEADER*)vsi_m_new_size ( alloc_size, PrimGroupHandle, + &partition_size FILE_LINE ) ) != NULL ) + { +#ifdef MEMORY_SUPERVISION + vsi_ppm_new ( caller, alloc_size, (T_PRIM_HEADER*)prim, file, line ); +#endif + prim->len = partition_size; /* complete partition because header is at the end */ + prim->opc = opc; + prim->sdu = NULL; + prim->use_cnt = 1; + prim->sh_offset = 0; + prim->dph_offset = D_HDR_OFFSET(partition_size); + dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset); + dp_hdr->magic_nr = GUARD_PATTERN; + dp_hdr->drp_bound_list = NULL; + dp_hdr->next = NULL; + dp_hdr->offset = sizeof(T_PRIM_HEADER) + ALIGN(size); + dp_hdr->size = partition_size - sizeof(T_DP_HEADER); + if ( dp_hdr->offset > dp_hdr->size ) + { + dp_hdr->offset = dp_hdr->size; + } + /* + * The following code does not work since the 'caller' parameter has been removed from the function + * prototype. The code was needed for the case where the function was called by PCON when decoding a + * received primitive in the test interface. The caller in this case is 0 because it is either the + * RCV_HISR on the target or the EXTR task in the simulation which is not running in the context of + * the frame. Currently the sh_offset is set in the TIF driver tif.c although the guard pattern is not + * set there. This is working fine so there is no reason to modify the code here. This comment + * is just the result of some brainstorming and can be used for future modifications + */ + if ( caller != 0 && caller == TST_Handle ) /* called by PCON */ + { + prim->sh_offset = prim->dph_offset - sizeof(T_S_HEADER); + dp_hdr->size = dp_hdr->size - sizeof(T_S_HEADER); + s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset); + s_hdr->magic_nr = GUARD_PATTERN; + } + else + prim->sh_offset = 0; + return ((T_VOID_STRUCT*)P2D(prim)); + } + return NULL; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_drpo_new_sdu | ++--------------------------------------------------------------------+ + + PURPOSE : allocate dynamic sized partition root + +*/ + +T_VOID_STRUCT * vsi_drpo_new_sdu (ULONG Size, ULONG opc, USHORT sdu_len, + USHORT sdu_offset, USHORT encode_offset, ULONG guess FILE_LINE_TYPE ) +{ +T_VOID_STRUCT *ptr; +ULONG alloc_size; +T_HANDLE Caller; + + Caller = 0; + alloc_size = Size + BYTELEN((SHORT)sdu_len + (SHORT)encode_offset); + ptr = vsi_drpo_new ( alloc_size, opc, guess FILE_LINE ); + /* + * the following line of code causes a warning on tms470 compiler, + * that cannot be avoided. Warning will not cause a problem because due to the + * arm7 alignment it is guaranteed that the sdu will start at an address divisable + * by 4. + */ + D_SDU(ptr) = (T_sdu*)((char*)ptr + sdu_offset); + D_SDU_LEN(ptr) = sdu_len; + D_SDU_OFF(ptr) = encode_offset; + + return ( (T_VOID_STRUCT*)ptr ); +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_drp_bind | ++--------------------------------------------------------------------+ + + PURPOSE : bind child root pointer to a given parent root pointer + +*/ +GLOBAL int vsi_drp_bind (T_VOID_STRUCT *child, T_VOID_STRUCT *parent FILE_LINE_TYPE) +{ +T_PRIM_HEADER *prim; +T_DP_HEADER *dp_hdr; +T_VOID_STRUCT **new_drp_bound_list; +ULONG alloc_size; +T_HANDLE caller; +int pos; + + caller = e_running[os_MyHandle()]; + + prim = D2P(parent); + if ( ((T_DP_HEADER*)prim)->magic_nr == GUARD_PATTERN ) + { + dp_hdr = (T_DP_HEADER*)prim; + } + else + { + dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset); + } + + if (dp_hdr->drp_bound_list == NULL) + { + /* no partitions bound so far */ + alloc_size=MAX_DRP_BOUND*sizeof(T_DP_HEADER*); + if ( ( new_drp_bound_list = (T_VOID_STRUCT**)M_ALLOC (alloc_size) ) == NULL ) + { + /* no more memory */ + return VSI_ERROR; + } + + memset(new_drp_bound_list,0x00,alloc_size); + dp_hdr->drp_bound_list=new_drp_bound_list; + } + + /* find free bind pointer */ + pos=0; + while(pos<MAX_DRP_BOUND && dp_hdr->drp_bound_list[pos]) + { + pos++; + } + if (pos == MAX_DRP_BOUND) + { + /* no more free bound pointers */ + return VSI_ERROR; + } + + /* actually bind */ + P_ATTACH(child); + dp_hdr->drp_bound_list[pos]=child; + + return VSI_OK; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_dp_new | ++--------------------------------------------------------------------+ + + PURPOSE : allocate dynamic sized partition root + +*/ +GLOBAL T_VOID_STRUCT *vsi_dp_new ( ULONG size, T_VOID_STRUCT *addr, ULONG guess FILE_LINE_TYPE ) +{ +T_PRIM_HEADER *prim; +T_PRIM_HEADER *last_in_chain; +T_PRIM_HEADER *dyn_ptr; +T_DP_HEADER *dp_hdr; +T_DP_HEADER *new_prim; +T_VOID_STRUCT *ptr; +ULONG partition_size; +ULONG alloc_size; +//ULONG estimated_size; +T_HANDLE caller; +char is_opc_root; + + if ( size + sizeof(T_DP_HEADER) > MaxPrimPartSize ) + { + caller = e_running[os_MyHandle()]; + vsi_o_assert ( NO_TASK, OS_SYST_ERR_BIG_PARTITION FILE_LINE_MACRO_PASSED, + "No Partition available, entity %s, size %d", pf_TaskTable[caller].Name, size ); + return NULL; + } + prim = D2P(addr); + dyn_ptr = prim; + if ( ((T_DP_HEADER*)prim)->magic_nr == GUARD_PATTERN ) + { + dp_hdr = (T_DP_HEADER*)prim; + is_opc_root = 0; + } + else + { + dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset); + is_opc_root = 1; + } + + if ( guess == DP_NO_FRAME_GUESS ) + alloc_size = size + sizeof(T_DP_HEADER); + else if ( guess == DP_FRAME_GUESS ) + alloc_size = size * 3 + sizeof(T_DP_HEADER); + else + alloc_size = size + guess + sizeof(T_DP_HEADER); + +#if 0 + /* + * update estimated size + */ + estimated_size = dp_hdr->est_size; + + if ( guess != DP_NO_FRAME_GUESS && guess != DP_FRAME_GUESS ) + { + estimated_size = size + guess; + alloc_size = estimated_size + sizeof(T_DP_HEADER); + estimated_size -= size; + } + else + { + if ( size > estimated_size ) + { + if ( guess == DP_FRAME_GUESS ) + estimated_size = size * 3; + else + estimated_size = size; + } + estimated_size -= size; + if ( size > estimated_size ) + estimated_size = size * 2; + alloc_size = estimated_size + sizeof(T_DP_HEADER); + } + + if ( estimated_size > MaxPrimPartSize ) + estimated_size = MaxPrimPartSize; + + dp_hdr->est_size = estimated_size; +#endif + /* + * check if free space in already allocated blocks (first fit) + */ + do + { + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + caller = e_running[os_MyHandle()]; + vsi_o_assert ( caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "Magic number in dp_header destroyed (DP_ALLOC), %s opc: 0x%lx, partition 0x%lx", + pf_TaskTable[caller].Name, ((T_PRIM_HEADER*)prim)->opc, prim ); + } + if ( dp_hdr->size - dp_hdr->offset > size ) + { + /* + * if root was allocated with drpo_alloc then dp header is at the end, + * the dph offset is not 0 and a primitive header is present. + */ + if ( is_opc_root && dyn_ptr == prim ) + ptr = (T_VOID_STRUCT*)(((ULONG*)prim) + (dp_hdr->offset>>2)); + else + ptr = (T_VOID_STRUCT*)(((ULONG*)dp_hdr) + (dp_hdr->offset>>2)); + dp_hdr->offset += ALIGN(size); + return ( ptr ); + } + if ( is_opc_root && dyn_ptr == prim ) + last_in_chain = prim; + else + last_in_chain = (T_PRIM_HEADER*)dp_hdr; + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + dyn_ptr = (T_PRIM_HEADER*)dp_hdr; + } while ( dp_hdr ); + + /* + * not enough free space -> additional allocation needed + */ + if ( alloc_size > MaxPrimPartSize ) + { +#ifdef NU_DEBUG + caller = e_running[os_MyHandle()]; + pf_handle_warning ( OS_SYST_WRN_REQ_TRUNCATED, "%s %s (%d->%d), entity %s, %s(%d)", + syst_wrn, trunc_str, alloc_size, MaxPrimPartSize, pf_TaskTable[caller].Name FILE_LINE_MACRO_PASSED ); +#endif + alloc_size = MaxPrimPartSize; + } + + if ( ( new_prim = (T_DP_HEADER*)vsi_m_new_size ( alloc_size, PrimGroupHandle, + &partition_size FILE_LINE ) ) != NULL ) + { +#ifdef MEMORY_SUPERVISION + caller = e_running[os_MyHandle()]; + vsi_ppm_new ( caller, alloc_size, (T_PRIM_HEADER*)new_prim, file, line ); +#endif + if ( ((T_DP_HEADER*)last_in_chain)->magic_nr == GUARD_PATTERN ) + dp_hdr = (T_DP_HEADER*)last_in_chain; + else + dp_hdr = (T_DP_HEADER*)((ULONG*)last_in_chain + last_in_chain->dph_offset); + dp_hdr->next = new_prim; + new_prim->magic_nr = GUARD_PATTERN; + new_prim->drp_bound_list = NULL; + new_prim->use_cnt = 1; + new_prim->next = NULL; + new_prim->size = partition_size; + new_prim->offset = sizeof(T_DP_HEADER) + ALIGN(size); + if ( new_prim->offset > new_prim->size ) + { + new_prim->offset = new_prim->size; + } + return (T_VOID_STRUCT*)(new_prim + 1); + } + + return NULL; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_drp_new | ++--------------------------------------------------------------------+ + + PURPOSE : allocate dynamic sized partition except root + +*/ +GLOBAL T_VOID_STRUCT *vsi_drp_new ( ULONG size, ULONG guess FILE_LINE_TYPE ) +{ +T_PRIM_HEADER *prim; +T_DP_HEADER *dp_hdr; +ULONG alloc_size; +ULONG header_size; +ULONG partition_size; +T_HANDLE caller; + + header_size = sizeof(T_DP_HEADER); + + if ( ALIGN(header_size + size) > MaxPrimPartSize ) + { + caller = e_running[os_MyHandle()]; + os_GetTaskName ( caller, caller, TaskName ); + vsi_o_assert ( NO_TASK, OS_SYST_ERR_BIG_PARTITION FILE_LINE_MACRO_PASSED, + "No Partition available, entity %s, size %d", pf_TaskTable[caller].Name, size ); + return NULL; + } + + if ( guess == DP_NO_FRAME_GUESS ) + alloc_size = header_size + size; + else if ( guess == DP_FRAME_GUESS ) + alloc_size = header_size + size * 3; + else + alloc_size = header_size + guess + size; + + if ( alloc_size > MaxPrimPartSize ) + { +#ifdef NU_DEBUG + caller = e_running[os_MyHandle()]; + pf_handle_warning ( OS_SYST_WRN_REQ_TRUNCATED, "%s %s (%d->%d), entity %s, %s(%d)", + syst_wrn, trunc_str, alloc_size, MaxPrimPartSize, pf_TaskTable[caller].Name FILE_LINE_MACRO_PASSED ); +#endif + alloc_size = MaxPrimPartSize; + } + + if ( ( prim = (T_PRIM_HEADER*)vsi_m_new_size ( alloc_size, PrimGroupHandle, + &partition_size FILE_LINE ) ) != NULL ) + { +#ifdef MEMORY_SUPERVISION + caller = e_running[os_MyHandle()]; + vsi_ppm_new ( caller, alloc_size, (T_PRIM_HEADER*)prim, file, line ); +#endif + dp_hdr = (T_DP_HEADER*)prim; + dp_hdr->next = NULL; + dp_hdr->magic_nr = GUARD_PATTERN; + dp_hdr->drp_bound_list = NULL; + dp_hdr->use_cnt = 1; + dp_hdr->offset = sizeof(T_DP_HEADER) + ALIGN(size); + dp_hdr->size = partition_size; + if ( dp_hdr->offset > dp_hdr->size ) + { + dp_hdr->offset = dp_hdr->size; + } + return (T_VOID_STRUCT*)(dp_hdr+1); + } + + return NULL; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_free | ++--------------------------------------------------------------------+ + + PURPOSE : deallocate a chain of linked partitions + +*/ + +int vsi_free ( T_VOID_STRUCT **Msg FILE_LINE_TYPE ) +{ +T_PRIM_HEADER *prim; +T_DP_HEADER *dp_hdr; +T_VOID_STRUCT** drp_bound_list; +T_HANDLE Caller = 0; +int pos; + + /* + * PFREE is disabled if the primitive to be freed is the currently + * processed one and the auto free is enabled for the calling entity + */ + + Caller = e_running[os_MyHandle()]; + + prim = D2P(*Msg); + +#ifdef NU_DEBUG + if ( os_is_valid_partition ((T_VOID_STRUCT*)prim) ) + { + /* free to non-partition memory */ + Caller = e_running[os_MyHandle()]; + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "FREE to non-partition memory, entity %s, prim 0x%x", pf_TaskTable[Caller].Name, *Msg ); + } +#endif + +#ifdef PRIM_AUTO_FREE + if ( prim == (T_PRIM_HEADER*)processed_prim[Caller] && pf_TaskTable[Caller].Flags & PARTITION_AUTO_FREE ) + { + return VSI_OK; + } +#endif /* PRIM_AUTO_FREE */ + + /* check if we have dynamic partition or primitive */ + if ( ((T_DP_HEADER*)prim)->magic_nr == GUARD_PATTERN ) + { + dp_hdr = (T_DP_HEADER*)prim; + } + else if ( prim->dph_offset != 0 ) + { + dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset); + } + else + { + return ( vsi_c_free ( Caller, (T_VOID_STRUCT**)&prim FILE_LINE ) ); + } + + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + /* primitive with T_desc_list element */ + vsi_c_free ( Caller, (T_VOID_STRUCT**)&prim FILE_LINE ); + return VSI_OK; + } + else + { + do + { + drp_bound_list=dp_hdr->drp_bound_list; + if (drp_bound_list) + { + /* call free for bound root pointers */ + pos=0; + while(pos<MAX_DRP_BOUND && drp_bound_list[pos]) + { + FREE(drp_bound_list[pos]); + pos++; + } + } + + /* free linked memory */ + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + vsi_c_free ( Caller, (T_VOID_STRUCT**)&prim FILE_LINE ); + + if (prim == NULL && drp_bound_list) + { + /* free drp_bound_list */ + M_FREE(drp_bound_list); + } + } while ( (prim = (T_PRIM_HEADER*)dp_hdr) != NULL ); + } + return VSI_OK; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_d_sum | ++--------------------------------------------------------------------+ + + PURPOSE : get number of bytes in dynamic sized primitive + +*/ +GLOBAL int vsi_dp_sum ( T_VOID_STRUCT *addr, ULONG *bytes ) +{ +T_PRIM_HEADER *prim; +T_DP_HEADER *dp_hdr; +ULONG size; +T_HANDLE caller; + + prim = D2P(addr); + if ( ((T_DP_HEADER*)prim)->magic_nr == GUARD_PATTERN ) + dp_hdr = (T_DP_HEADER*)prim; + else if ( prim->dph_offset != 0 ) + dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset); + else + { + caller = e_running[os_MyHandle()]; + vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "SYSTEM WARNING: No root of linked memory in %s", + pf_TaskTable[caller].Name ); + return VSI_ERROR; + } + + size = 0; + do + { + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + caller = e_running[os_MyHandle()]; + vsi_o_assert ( caller, OS_SYST_ERR, __FILE__, __LINE__, + "Magic number in dp_header destroyed, opc: 0x%lx, partition 0x%lx", + prim->opc, prim ); + } + size += (dp_hdr->offset-sizeof(T_DP_HEADER)); + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + } while ( (prim = (T_PRIM_HEADER*)dp_hdr) != NULL ); + + *bytes = size; + return VSI_OK; +} +#endif + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_dp_max_size | ++--------------------------------------------------------------------+ + + PURPOSE : get maximum number of bytes available for user data + in dynamic primitive + +*/ +GLOBAL int vsi_dp_max_size ( void ) +{ + return ( (int)(MaxPrimPartSize - sizeof(T_PRIM_HEADER) - sizeof(T_DP_HEADER)) ); +} +#endif + + +#ifndef RUN_INT_RAM +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_pmax_size | ++--------------------------------------------------------------------+ + + PURPOSE : get maximum number of bytes available for user data + in dynamic primitive + +*/ +GLOBAL int vsi_c_pmax_size ( void ) +{ + return ( (int)(MaxPrimPartSize - sizeof(T_DP_HEADER)) ); +} +#endif + +#ifdef _TOOLS_ +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_sync | ++--------------------------------------------------------------------+ + + PURPOSE : check if PS already started + +*/ +GLOBAL int vsi_c_sync ( T_HANDLE caller, T_TIME timeout ) +{ +T_VOID_STRUCT *prim; +T_QMSG Msg; +T_HANDLE tst_q_handle; +char sync_req_name[RESOURCE_NAMELEN]; +char sync_req_time[8]; +static int sync_active = 0; + + + if ( sync_active == FALSE ) + { + sync_active = TRUE; + os_GetTaskName(caller, caller, sync_req_name); + itoa(timeout, sync_req_time,10); + + prim = vsi_c_pnew ( sizeof(T_PRIM_HEADER)+strlen(SYSPRIM_CONFIG_TOKEN)+1 + +strlen(SYSPRIM_TST_SYNC_REQ)+1 + +strlen(sync_req_name)+1 + +strlen(sync_req_time)+1, 0x8000 FILE_LINE ); + strcpy ( (char*)prim, SYSPRIM_CONFIG_TOKEN ); + strcat ( (char*)prim, " " ); + strcat ( (char*)prim, SYSPRIM_TST_SYNC_REQ ); + strcat ( (char*)prim, " " ); + strcat ( (char*)prim, sync_req_name ); + strcat ( (char*)prim, " " ); + strcat ( (char*)prim, sync_req_time ); + + tst_q_handle = vsi_c_open ( caller, FRM_TST_NAME ); + vsi_c_psend ( tst_q_handle, prim ); + + if ( vsi_c_await ( caller, pf_TaskTable[caller].QueueHandle, &Msg, timeout ) == VSI_TIMEOUT ) + { + vsi_o_ttrace (caller, TC_SYSTEM, "timeout - Synchronization with Stack failed" ); + sync_active = FALSE; + return VSI_ERROR; + } + else + { + sync_active = FALSE; + if ( strcmp ((char*)P2D(Msg.Msg.Primitive.Prim), SYSPRIM_TST_SYNC_CNF ) == 0 ) + { + vsi_o_ttrace (caller, TC_SYSTEM, "TST_SYNC_CNF - Synchronization with Stack succeeded" ); + vsi_c_free (caller, &Msg.Msg.Primitive.Prim); + return VSI_OK; + } + else + { + vsi_o_ttrace (caller, TC_SYSTEM, "TST_SYNC_REJ - Synchronization with Stack failed" ); + vsi_c_free (caller, &Msg.Msg.Primitive.Prim); + return VSI_ERROR; + } + } + } + return VSI_OK; +} +#endif + +#ifdef _TOOLS_ +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : vsi_c_generic_send | ++--------------------------------------------------------------------+ + + PURPOSE : check if PS already started + +*/ +int vsi_c_alloc_send ( T_HANDLE com_handle, char* dst, char* src, void *prim, char *string ) +{ +int alloc_size; +T_PRIM_HEADER *ptr; +T_S_HEADER *s_hdr; +unsigned int i; +unsigned int size; +int opc; +int s_header_added = 0; +int sh_offset; + + if ( string != NULL ) + { + size = strlen(string); + alloc_size = size + sizeof(T_PRIM_HEADER); + if ( dst != NULL || src != NULL ) + { + sh_offset = ALIGN(alloc_size) / (int)sizeof(ULONG); + alloc_size = ALIGN(alloc_size) + sizeof(T_S_HEADER); + if ( dst != 0 ) + opc = 0; /* to stack -> set to SYS_MASK in tst_pei_primitive() when sh_offset != 0 */ + else + opc = SYS_MASK; /* to tools */ + s_header_added = 1; + } + else + { + opc = SYS_MASK; + sh_offset = 0; + } + ptr = (T_PRIM_HEADER*)vsi_c_new ( 0, alloc_size, opc ); + memcpy ( (char*)P2D(ptr), string, size ); + if ( s_header_added == 1 ) + { + ptr->sh_offset = sh_offset; + s_hdr = (T_S_HEADER*)((int*)ptr+ptr->sh_offset); + ptr->len = size + sizeof(T_PRIM_HEADER); /* exclude S_HEADER */ + } + } + else + { + ptr = D2P(prim); /* work on passed primitive */ + } + if ( dst != NULL ) + { + if ( s_header_added == 0 ) + { + alloc_size = ALIGN(ptr->len) + sizeof(T_S_HEADER); + ptr = (T_PRIM_HEADER*)vsi_c_new ( 0, alloc_size, 0 ); + memcpy((char*)ptr, (char*)D2P(prim), D_LEN(prim)); + ptr->sh_offset = ALIGN(D_LEN(prim)) / sizeof(ULONG); + s_hdr = (T_S_HEADER*)((int*)ptr+ptr->sh_offset); + FREE(prim); + } + else + { + s_hdr = (T_S_HEADER*)((int*)ptr+ptr->sh_offset); + } + /* set org_rcv and rcv */ + for (i = 0; dst[i] && i < sizeof (s_hdr->rcv) && dst[i]!= ';'; i++) + s_hdr->org_rcv[i] = s_hdr->rcv[i] = dst[i]; + if (i < sizeof s_hdr->rcv) + s_hdr->org_rcv[i] = s_hdr->rcv[i] = 0; + + s_hdr->time = 0; + s_header_added = 1; + } + + if ( src != NULL ) + { + if ( s_header_added == 0 ) + { + alloc_size = ALIGN(ptr->len) + sizeof(T_S_HEADER); + ptr = (T_PRIM_HEADER*)vsi_c_new ( 0, alloc_size, 0 ); + memcpy((char*)ptr, (char*)D2P(prim), D_LEN(prim)); + ptr->sh_offset = ALIGN(D_LEN(prim)) / sizeof(ULONG); + s_hdr = (T_S_HEADER*)((int*)ptr+ptr->sh_offset); + FREE(prim); + } + else + { + s_hdr = (T_S_HEADER*)((int*)ptr+ptr->sh_offset); + } + + s_hdr->time = 0; + + /* set snd */ + for (i = 0; src[i] && i < sizeof (s_hdr->snd) && src[i]!= ';'; i++) + s_hdr->snd[i] = src[i]; + if (i < sizeof s_hdr->snd) + s_hdr->snd[i] = 0; + } + + return ( vsi_c_psend (com_handle, (T_VOID_STRUCT*)P2D(ptr)) ); +} +#endif + +#ifdef NU_DEBUG +#ifndef RUN_FLASH +/* ++----------------------------------------------------------------------+ +| PROJECT : GSM-Frame (8415) MODULE : VSI_COM | +| STATE : code ROUTINE : check_descriptor_list | ++----------------------------------------------------------------------+ + + PURPOSE : check partitions in descriptor list + +*/ +int check_descriptor_list ( T_HANDLE caller, T_PRIM_HEADER *prim FILE_LINE_TYPE ) +{ +T_DP_HEADER *dp_hdr; +T_M_HEADER *mem; +T_desc *desc; +LONG Status; + + dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset); + /* the presence of the guard pattern at dph_offset is used to distinguish between dynamic primitives + and primitives with descriptor list. If the guard pattern is destroyed, the primitive looks like + having a descriptor list and the frame will probably crash during checking the integrity of the + partitions in the list. This bahavior is prefered to non checking the partitions */ + + if ( *((ULONG*)dp_hdr) == GUARD_PATTERN ) + { + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + while (dp_hdr != NULL) + { + if ( dp_hdr->magic_nr != GUARD_PATTERN ) + { + prim = (T_PRIM_HEADER*)dp_hdr; + vsi_o_assert ( caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "Magic number in dp_header destroyed (PSEND) %s , opc: 0x%lx, partition 0x%lx", + pf_TaskTable[caller].Name, prim->opc, prim ); + } + if ( (Status = os_PartitionCheck ( (T_VOID_STRUCT*)dp_hdr)) == OS_PARTITION_GUARD_PATTERN_DESTROYED ) + { + vsi_o_assert ( caller, OS_SYST_ERR_PCB_PATTERN FILE_LINE_MACRO_PASSED, + "%s in dynamic primitive (PSEND),entity %s, prim 0x%x, opc 0x%x, bad partition 0x%x", + guard_str, pf_TaskTable[caller].Name, prim, prim->opc, dp_hdr ); + break; + } + dp_hdr = (T_DP_HEADER*)dp_hdr->next; + } + } + else + { + if ( caller != TST_Handle ) + { + /* do not check and update the states of the primitives in descriptor lists when called by TST, because + descriptor lists are not routed to TST and will result in the warning generated below */ + desc = (T_desc*)(((T_desc_list*)dp_hdr)->first); + while (desc != NULL) + { + mem = (T_M_HEADER*)(((char*)desc)-sizeof(T_M_HEADER)); + if ( os_is_valid_partition ((T_VOID_STRUCT*)mem) ) + { + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "pointer to non-partition memory in desc list(PSEND), entity %s, prim 0x%x, opc 0x%x", + pf_TaskTable[caller].Name, prim, prim->opc ); + return VSI_ERROR; + } + if ( (Status = os_PartitionCheck ( (T_VOID_STRUCT*)mem)) != OS_OK ) + { + switch ( Status ) + { + case OS_PARTITION_GUARD_PATTERN_DESTROYED: + vsi_o_assert ( caller, OS_SYST_ERR_PCB_PATTERN FILE_LINE_MACRO_PASSED, + "%s in desclist (PSEND), entity %s, prim 0x%x, opc 0x%x, bad partition 0x%x", + guard_str, pf_TaskTable[caller].Name, prim, prim->opc, mem ); + break; + case OS_PARTITION_FREE: + vsi_o_assert ( caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "%s in desclist (PSEND), entity %s, prim 0x%x, opc 0x%x, freed partition 0x%x", + freed_sent_str, pf_TaskTable[caller].Name, prim, prim->opc, mem ); + break; + default: + break; + } + } + if ( mem->desc_type == (VSI_DESC_TYPE3 >> 16) ) + { + mem = ((T_M_HEADER*)(((T_desc3*)desc)->buffer)) - 1; + if ( os_is_valid_partition ( (T_VOID_STRUCT*)mem ) ) + { + vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "pointer to non-partition memory in desc list type 3 (PSEND), entity %s, prim 0x%x, opc 0x%x, invalid partition 0x%x", + pf_TaskTable[caller].Name, prim, prim->opc, mem ); + return VSI_ERROR; + } + if ( (Status = os_PartitionCheck ( (T_VOID_STRUCT*)mem )) != OS_OK ) + { + switch ( Status ) + { + case OS_PARTITION_GUARD_PATTERN_DESTROYED: + vsi_o_assert ( caller, OS_SYST_ERR_PCB_PATTERN FILE_LINE_MACRO_PASSED, + "%s in desclist type 3 (PSEND), entity %s, prim 0x%x, opc 0x%x, bad partition 0x%x", + guard_str, pf_TaskTable[caller].Name, prim, prim->opc, mem ); + break; + case OS_PARTITION_FREE: + vsi_o_assert ( caller, OS_SYST_ERR FILE_LINE_MACRO_PASSED, + "%s in desclist type 3 (PSEND), entity %s, prim 0x%x, opc 0x%x, freed partition 0x%x", + freed_sent_str, pf_TaskTable[caller].Name, prim, prim->opc, mem ); + break; + default: + break; + } + } + } + + desc = (T_desc *)desc->next; + } + } + } + return VSI_OK; +} +#endif +#endif + +#if !defined _TARGET_ && !defined _TOOLS_ + +/* ------------------------------------------------------------------------- + check functions +----------------------------------------------------------------------------*/ + +#ifdef TEST_PCHECK + +#ifndef RUN_INT_RAM +ULONG test_pcheck ( ULONG opc, void * decoded_prim ) +{ + vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "test_pcheck() called for opc %8x", D_OPC(decoded_prim) ); + return pcheck_func.ret_ok+1; +} +#endif + +#endif /* TEST_PCHECK */ + +#ifndef RUN_INT_RAM +/* ++------------------------------------------------------------------------------ +| Function : pcheck_register ++------------------------------------------------------------------------------ +| Description : register the pcheck function. +| +| Parameters : func - pointer to API function pointer table +| +| Return : void ++------------------------------------------------------------------------------ +*/ +void vsi_pcheck_register ( ULONG (*func)(ULONG, void*), ULONG ret_ok ) +{ + pcheck_func.ret_ok = ret_ok; + pcheck_func.pcheck = func; + pcheck_func.magic_nr = PCHECK_INITIALIZED; +} +#endif + +#ifndef RUN_INT_RAM +/* ++------------------------------------------------------------------------------ +| Function : ext_trace_init ++------------------------------------------------------------------------------ +| Description : initialize external trace function pointer table. +| +| Parameters : void +| +| Return : void ++------------------------------------------------------------------------------ +*/ +void vsi_pcheck_init ( void ) +{ +#ifdef TEST_PCHECK + vsi_pcheck_register ( test_pcheck, 0 ); +#endif + if ( pcheck_func.magic_nr != PCHECK_INITIALIZED ) + { + pcheck_func.ret_ok = 0; + pcheck_func.pcheck = NULL; + pcheck_func.magic_nr = 0; + } +} +#endif + +#endif /* !_TARGET_ && !_TOOLS_*/ + + + +