FreeCalypso > hg > freecalypso-sw
diff gsm-fw/g23m-aci/dti/dti_kerf.c @ 775:eedbf248bac0
gsm-fw/g23m-aci subtree: initial import from LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 12 Oct 2014 01:45:14 +0000 |
parents | |
children | ac329f4627ac |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/g23m-aci/dti/dti_kerf.c Sun Oct 12 01:45:14 2014 +0000 @@ -0,0 +1,2464 @@ +/* ++----------------------------------------------------------------------------- +| Project : DTILIB +| Modul : DTI ++----------------------------------------------------------------------------- +| 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 : Definitions for the Protocol Stack Library +| DTI ++----------------------------------------------------------------------------- +*/ + +/* + * Version 1.6 + */ + +#ifndef DTI_KERF_C +#define DTI_KERF_C +#endif + + +/*==== CONST =======================================================*/ + +#include <string.h> +#include "typedefs.h" +#include "pconst.cdg" +#include "vsi.h" +#include "custom.h" +#include "gsm.h" +#include "prim.h" +#include "dti.h" +#include "dti_int_def.h" +#include "dti_int_prot.h" + +#ifdef FF_TCP_IP +#include "atp/atp_api.h" +#include "atp/atp_messages.h" +#include "aaa.h" +#include "dti_atp.h" +#include "gprs.h" +#include "dti_conn_mng.h" /* for getting EXTRACT_DTI_ID */ +#endif + +/*==== LOCALS ================================================================*/ + +#ifdef _SIMULATION_ +LOCAL void send_data_test_req_or_ind + ( + DTI_HANDLE hDTI, + DTI_LINK *link, + T_DTI2_DATA_IND *dti_data_ind + ); +#endif /* _SIMULATION_ */ + + +#ifdef FF_TCP_IP +static BOOL ATP_used_flag; +#endif + +/*==== GLOBALS ===============================================================*/ + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_init | ++--------------------------------------------------------------------+ + * + * Malloc and set default parameters and specified entity_options for the database + * + */ + +GLOBAL DTI_HANDLE dti_init( + U8 maximum_links, + T_HANDLE handle, + U32 entity_options, + void (sig_callback( + U8 instance, + U8 interfac, + U8 channel, + U8 reason, + T_DTI2_DATA_IND *dti_data_ind) + ) + ) +{ + U16 i; + DTI_HANDLE hDTI; + DTI_LINK *link, *last_link; + + trace_function(handle, "dti_init()", entity_options); + +#if defined ALLOCATE_DATABASE_BLOCK + + /* + * Allocate all needed memory for the DTI Database in one block. + */ + MALLOC( hDTI, (U16) + /* Database */ + (sizeof(temp_mem_1) - sizeof(DTI_LINK) + + /* Every links */ + ((sizeof(temp_mem_2) - sizeof(temp_mem_1))* maximum_links))); + + /* + * Set defaults to the Database. + */ + set_default_para_data_base(hDTI); + + /* + * Number of links in the Data Base (DTI_DATA_BASE). + */ + hDTI->max_links = maximum_links; + hDTI->handle = handle; + hDTI->entity_options = entity_options; + + /* + * Cast the links and init them. + */ + { + U32 link_addr_offset = 0; + for(i = 0; i < maximum_links; i++) + { + if(i == 0) + { + hDTI->first_link = ((U32) &((temp_mem_1*) hDTI)->tmp_link[i]); + link = (DTI_LINK*)hDTI->first_link; + init_link_table(link); + link_addr_offset = ((U32) &((temp_mem_2*) hDTI)->tmp_link[1]) - ((U32) link); + } + else + { + link = link + link_addr_offset; + init_link_table(link); + } + } + } +#else + + /* + * Allocate the memory over separate blocks. + */ + MALLOC (hDTI, (U16)(sizeof(DTI_DATA_BASE) - 1)); + + /* + * Set defaults + */ + set_default_para_data_base(hDTI); + + /* + * Number of links in the Data Base (DTI_DATA_BASE). + */ + hDTI->max_links = maximum_links; + hDTI->handle = handle; + hDTI->entity_options = entity_options; + + /* + * Allocate LINK_TABLE for maximum_links and set default parameters + */ + if(maximum_links > 0) + { + MALLOC (link, (U16) sizeof(DTI_LINK)); + init_link_table(link); + hDTI->first_link = (U32) link; + for(i = 1; i < maximum_links; i++) + { + last_link = link; + MALLOC (link, (U16) sizeof(DTI_LINK)); + init_link_table(link); + last_link->next_link = (U32) link; + } + } +#endif + +#ifdef FF_TCP_IP + if (!ATP_used_flag) /* initialise array of references to ATP links */ + { + for ( i=0; i<MAX_ATP_LINKS; i++) + { + atp_links[i]= D_LINK; + } + } +#endif + + /* + * Set the callback function for the entity / instance + */ + hDTI->sig_callback = sig_callback; + return hDTI; +} /* dti_init() */ +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_deinit | ++--------------------------------------------------------------------+ + + * + * Malloc and set default parameter for the Data Base + * + */ + +GLOBAL void dti_deinit( DTI_HANDLE hDTI) +{ + trace_function(hDTI->handle, "dti_deinit()", hDTI->entity_options); + + if(hDTI EQ D_NO_DATA_BASE) + return; + +#if defined ALLOCATE_DATABASE_BLOCK + + /* + * Free the datablock as a block. + */ + + MFREE (hDTI); + +#else + + /* + * Free the links of the link table with DTI queue + */ + + free_dti_link_structure(hDTI); + + /* + * Free the DTI_DATA_BASE + */ + + MFREE (hDTI); + +#endif +} /* dti_deinit() */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : acquire_link | ++--------------------------------------------------------------------+ + + * + * This function acquires a link + */ +LOCAL DTI_RESULT acquire_link(DTI_HANDLE hDTI, + U32 link_id, + U8 direction, + DTI_LINK **link) +{ + trace_function(hDTI->handle, + "acquire_link()", + hDTI->entity_options); + + if((*link = get_pointer_link_table(hDTI, link_id, direction)) NEQ NULL) + return DTI_S_FOUND; + + if((*link=get_pointer_free_link(hDTI)) NEQ NULL) + { + set_default_para_link_table (hDTI, *link, link_id, direction); + return DTI_S_CREATED_NEW; + } + + /* + * No free link and so no connection possible. + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: No link free in dtilib", + link_id, + hDTI->entity_options); + return DTI_E_FAIL; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : dti_kerf.c | +| STATE : code ROUTINE : send_connect_req_or_ind | ++--------------------------------------------------------------------+ + + * PURPOSE: Send a Connect primitive depending on the direction. + */ + +LOCAL void send_connect_req_or_ind (DTI_HANDLE hDTI, DTI_LINK *link) +{ +#define VSI_CALLER hDTI->handle, + /* + * Check if the link is upwards or downwards + * and send the according connect primitive. + */ + switch(link->direction) + { + case DTI_CHANNEL_TO_HIGHER_LAYER: + { + PALLOC (dti_connect_ind, DTI2_CONNECT_IND); + dti_connect_ind->link_id = link->link_id; + dti_connect_ind->version = link->version; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_connect_ind); + } + else + { + PSEND(link->link_handle, dti_connect_ind); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_CONNECT_IND", + link->link_id, + hDTI->entity_options); + } + } + break; + + case DTI_CHANNEL_TO_LOWER_LAYER: + { + PALLOC (dti_connect_req, DTI2_CONNECT_REQ); + dti_connect_req->link_id = link->link_id; + dti_connect_req->version = link->version; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_connect_req); + } + else + { + PSEND(link->link_handle, dti_connect_req); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_CONNECT_REQ", + link->link_id, + hDTI->entity_options); + } + } + break; + + default: + /* + * no known channel type open so do not send anything + */ + break; + } +#undef VSI_CALLER +} /* send_connect_req_or_ind() */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : dti_kerf.c | +| STATE : code ROUTINE : send_connect_res_or_cnf | ++--------------------------------------------------------------------+ + + * PURPOSE: Send a Connect Confirm primitive depending on the direction. + */ + +LOCAL void send_connect_res_or_cnf (DTI_HANDLE hDTI, DTI_LINK *link) +{ +#define VSI_CALLER hDTI->handle, + /* + * Check if the link is upwards or downwards + * and send the according connect primitive. + */ + switch(link->direction) + { + case DTI_CHANNEL_TO_HIGHER_LAYER: + { + PALLOC (dti_connect_cnf, DTI2_CONNECT_CNF); + dti_connect_cnf->link_id = link->link_id; + dti_connect_cnf->version = link->version; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_connect_cnf); + } + else + { + PSEND(link->link_handle, dti_connect_cnf); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_CONNECT_CNF", + link->link_id, + hDTI->entity_options); + } + } + break; + + case DTI_CHANNEL_TO_LOWER_LAYER: + { + PALLOC (dti_connect_res, DTI2_CONNECT_RES); + dti_connect_res->link_id = link->link_id; + dti_connect_res->version = link->version; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_connect_res); + } + else + { + PSEND(link->link_handle, dti_connect_res); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_CONNECT_RES", + link->link_id, + hDTI->entity_options); + } + } + break; + + default: + /* + * no known channel type open so do not send anything + */ + break; + } +#undef VSI_CALLER +} /* send_connect_res_or_cnf() */ + + + +/* ++-------------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : send_open_ready_callback | ++-------------------------------------------------------------------------+ + + * + * Activate connection_opened and tx_buffer_ready callback funktions. + */ + +LOCAL void send_open_ready_callback(DTI_HANDLE hDTI, DTI_LINK *link) +{ +#ifdef FF_TCP_IP + /* + * trigger DTI Primitive transmission separatly, because it can not be done by ATP + */ + if(link->link_type EQ RIVIERA_ATP_LINK) + { + PALLOC(dti_ready_ind, DTI2_READY_IND); + dti_ready_ind->link_id = link->link_id; +#define VSI_CALLER 0, + PSEND_NTRACE(link->link_handle, dti_ready_ind); +#undef VSI_CALLER + /* + * stop ATP reception Flow Control + */ + TRACE_EVENT("initial: ATP_RX_FLOW_OFF"); + atp_set_signal(hDTI->entity_id_p, + link->port_nb, + ATP_RX_FLOW_OFF, + ATP_RX_FLOW_UNMASK); + } +#endif /* FF_TCP_IP */ + /* + * send indication for the open connection + */ + hDTI->sig_callback( + link->instance, + link->interfac, + link->channel, + DTI_REASON_CONNECTION_OPENED, + NULL); + + /* + * Call the callback function with the signal tx_buffer_ready + * if the queue is used and not full + */ + if((link->direction EQ DTI_NULL_LINK) OR + ((link->queue_len < link->queue_size) OR + (link->link_options EQ DTI_QUEUE_UNBOUNDED))) + { + link->tx_state = DTI_TX_IDLE; + hDTI->sig_callback( + link->instance, + link->interfac, + link->channel, + DTI_REASON_TX_BUFFER_READY, + NULL + ); + } +} /* send_open_ready_callback() */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_open | ++--------------------------------------------------------------------+ + + * + * This function opens or resets a DTI connection. + * + */ + +GLOBAL BOOL dti_open (DTI_HANDLE hDTI, + U8 instance, + U8 interfac, + U8 channel, + U8 queue_size, + U8 direction, + U32 link_options, + U32 version, + U8 *neighbor_entity, + U32 link_id) +{ + DTI_LINK *link; + BOOL send_req_or_ind = FALSE; + BOOL send_res_or_cnf = FALSE; + BOOL open_vsi_channel = FALSE; + BOOL riviera_atp_channel = FALSE; /* came by DAA hack */ +#ifdef BT_ADAPTER + BOOL riviera_bt_channel = FALSE; /* came by dirty BT interface hack */ +#endif /* riviera_bt_channel */ + U8 signal = DTI_NO_SIGNAL; + + trace_function(hDTI->handle, + "dti_open()", + hDTI->entity_options); + + trace_message_l_e(hDTI->handle, + "open connection", + link_id, + (char*)neighbor_entity, + hDTI->entity_options); + +#ifdef BT_ADAPTER + /* + * Check if open with a riviera entity. + */ + if (strcmp ((CHAR*)neighbor_entity, BTI_NAME) EQ 0) + { + riviera_bt_channel = TRUE; + } +#endif /* BT_ADAPTER */ + +#ifdef FF_TCP_IP + TRACE_EVENT_P5 ("dti_open: QS:%d DIR:%d LOPT:%d NE:%s LID:%d V:4", queue_size, direction, link_options, neighbor_entity, link_id); + if (strcmp ((CHAR*)neighbor_entity, RIV_NAME) EQ 0) + { + riviera_atp_channel = TRUE; + TRACE_EVENT("Riviera link to be opened!"); + } +#endif /* FF_TCP_IP */ + + /* + * Validate and correct passed parameters + */ + if(validate_open_parameters(hDTI, + link_id, + &queue_size, + &direction, + &link_options, + version, + neighbor_entity) EQ DTI_E_FAIL) + { + return FALSE; + } + + /* + * Find a link with the given link_id and direction + */ + switch (acquire_link (hDTI, link_id, direction, &link) ) + { + case DTI_S_FOUND: + /* + * Found already existing link + */ + switch (link->connect_state) + { + case DTI_CLOSING: + link->connect_state = DTI_IDLE; + /* fall through */ + + case DTI_IDLE: + /* + * Reset the link and set the parameter. + */ + trace_message(hDTI->handle, + "existing DTI connection is being reset!", + hDTI->entity_options); + + set_open_para_link_table(hDTI, + link, + version, + link_options, + instance, + interfac, + channel, + queue_size, + DTI_IDLE); + /* + * Send a confirm primitive if we use SAP DTI2.DOC. Then also set the parameter. + */ + send_req_or_ind = TRUE; + signal = DTI_REASON_CONNECTION_OPENED; + if (link->direction NEQ DTI_NULL_LINK) + { + /* + * Close the old channel. + */ + vsi_c_close (hDTI->handle, link->link_handle); + } + + /* + * Set the flag to open a new channel. + */ + open_vsi_channel = TRUE; + + break; + + case DTI_SETUP: + /* + * Collision of DTI2_CONNECT_REQ and DTI2_CONNECT_IND. The parameters + * have been set in dti_open before. They stay in this state. + */ + break; + + case DTI_CLOSED: + /* + * Start with connecting + */ + + set_open_para_link_table + ( + hDTI, link, version, link_options, + instance, interfac, channel, queue_size, DTI_SETUP + ); + + link->connect_state = DTI_SETUP; + send_req_or_ind = TRUE; + open_vsi_channel = TRUE; + break; + + case DTI_CONNECTING: + /* + * Got a connecting primitive, send a confirm primitive and set the parameter. + */ + set_open_para_link_table + ( + hDTI, link, version, link_options, + instance, interfac, channel, queue_size, DTI_IDLE + ); + + send_res_or_cnf = TRUE; + signal = DTI_REASON_CONNECTION_OPENED; + open_vsi_channel = TRUE; + break; + + default: + /* + * Wrong state + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: Wrong state of dtilib", + link_id, + hDTI->entity_options); + break; + } + break; + + /* + * Created new link + */ + case DTI_S_CREATED_NEW: + /* + * Open the requested channel and send a req/ind primitive. + */ + open_vsi_channel = TRUE; + + /* + * DTILIB can handle DTI SAP DTI.DOC and DTI2.DOC. By using DTI.DOC (the old + * SAP) the parameter are set but the connect primitives are not supported. + * + * SAP DTI.DOC does also not support a queue. So the queue len is set to + * 0 in the function set_link_parameter(). + */ + set_open_para_link_table + ( + hDTI, link, version, link_options, + instance, interfac, channel, queue_size, DTI_SETUP + ); + send_req_or_ind = TRUE; + break; + + default: + /* + * No free link - no connection possible. + */ + return FALSE; + } /*lint !e788 enum constant not used */ + +/* in case of RIV link, get parameters from AAA */ +#ifdef FF_TCP_IP + if( riviera_atp_channel) + { + link->link_type = RIVIERA_ATP_LINK; + link->entity_db = hDTI; /* remember the entity the link belongs to */ + link->dti_id = EXTRACT_DTI_ID(link_id); +/* link->link_options = FLOW_CNTRL_DISABLED; */ /* to avoid the full DTI state machine */ + + /* get the parameters valid within RIV environment from AAA */ + if(!aaa_get_connection_data( link->dti_id, &(link->port_nb), &(hDTI->entity_id_p), &(hDTI->own_name))) + { + TRACE_ERROR("aaa_get_connection_data() failed!"); + } + else + { + TRACE_EVENT_P2("got connection_data: name: %s, link_id: %d", (char*) (hDTI->own_name), link->link_id); + } + + if(hDTI->handle EQ PEI_ERROR) + { + TRACE_ERROR("error getting my own entity handle!"); + } + } +#endif + +/* mark links connection type */ + if( !riviera_atp_channel +#ifdef BT_ADAPTER + AND !riviera_bt_channel +#endif + ) /*lint !e774 (Info -- Boolean within 'if' always evaluates to True), only used for FF_TCP_IP/BT */ + { + link->link_type = ENTITY_LINK; + } + + /* + * link to BlueTooth + */ +#ifdef BT_ADAPTER + if(riviera_bt_channel) + { + link->link_type = RIVIERA_BT_LINK; + } +#endif + + /* + * Open a channel to VSI. If it is not possible to open, return FALSE to the entity + * so that the entity can try again. + */ + if(open_vsi_channel) + { + /* + * If NULL device then disable flow control + */ + if(direction EQ DTI_NULL_LINK) + { + trace_message(hDTI->handle, + "DTI connection is to be opened for NULL device", + hDTI->entity_options); + /* + * it is not exactly necessary to set this here, + * but only a logical consequence + */ + link->link_options = DTI_FLOW_CNTRL_DISABLED; + link->link_type = NULL_LINK; + link->connect_state = DTI_IDLE; + /* + * Activate callback function with reason_connection_opened + * and, additionally, signal tx_buffer_ready if the queue is used. + */ + send_open_ready_callback(hDTI, link); + return TRUE; + } + + if (link->link_type EQ ENTITY_LINK) /* check for connection within GPF */ + { + open_comm_channel(hDTI->handle, + &link->link_handle, + (char *) neighbor_entity, + hDTI->entity_options); + } + +#ifdef FF_TCP_IP + else if (link->link_type EQ RIVIERA_ATP_LINK) /* check for connection towards Riv */ + { + link->dti_data_ind = NULL; + link->connect_state = DTI_IDLE; /* we don't use connect prims here, */ + /* so set it by hand */ + signal = DTI_REASON_CONNECTION_OPENED; + send_res_or_cnf = FALSE; + send_req_or_ind = FALSE; + + open_comm_channel( hDTI->handle, /* open com handle to hDTI-entity */ + &link->link_handle, + (char *) hDTI->own_name, + hDTI->entity_options); + + /* the port has already been opened by AAA, so only remember link as leading to ATP, + * for sending data or events 'backwards' to that entity + */ + if(link->link_handle >= VSI_OK) + { + if(atp_links[link->port_nb] EQ D_LINK) + { + atp_links[link->port_nb] = link; + ATP_used_flag = TRUE; + } + else + { + TRACE_ERROR("link reference could not be saved for DAA"); + } + } + } +#endif + + if(link->link_handle < VSI_OK) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: open a comm channel not possible", + link_id, + hDTI->entity_options); + + set_default_para_link_table(hDTI, link, D_FREE_LINK_ID, D_DIRECTION); + return FALSE; + } + +#ifdef BT_ADAPTER + if(link->link_type EQ RIVIERA_BT_LINK) /* connection links into RIV environment */ + { + /* + xxxx: handle new BT link + */ + } +#endif + } /* if(open_channel) */ + + if(send_res_or_cnf) /* shouldn't happen for ATP links! */ + { + /* Send DTI2_CONNECT_RES or DTI2_CONNECT_CNF + */ + send_connect_res_or_cnf (hDTI, link); + } + else if(send_req_or_ind) /* is supposed to happen for ATP links??? */ + { + /* Send DTI2_CONNECT_REQ or DTI_CONNECT_IND. + */ + if(link->link_type EQ ENTITY_LINK) + { + send_connect_req_or_ind (hDTI, link); + } + } + /* + * Activate the callback function to the entity. + */ + if(signal EQ DTI_REASON_CONNECTION_OPENED) + { + if (!(hDTI->entity_options & DTI_NO_TRACE) ) + { + trace_message_l_e(hDTI->handle, + "DTI connection opened", /*lint !e605 Increase in pointer capability */ + link_id, + (char*)neighbor_entity, + hDTI->entity_options); + } + + /* + * Activate callback function with reason_connection_opened + * and, additionally, signal tx_buffer_ready if the queue is used. + */ + send_open_ready_callback (hDTI, link); + } + return TRUE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : dti_kerf.c | +| STATE : code ROUTINE : send_disconnect_req_or_ind | ++--------------------------------------------------------------------+ + + * PURPOSE: Send a Disconnect primitive depending on the direction. + */ + +LOCAL void send_disconnect_req_or_ind (DTI_HANDLE hDTI, + DTI_LINK* link, + U8 cause) +{ +#define VSI_CALLER hDTI->handle, + /* + * Check if the link is upwards or downwards + * and send the according disconnect primitive. + */ + switch (link->direction) + { + case DTI_CHANNEL_TO_HIGHER_LAYER: + { + PALLOC (dti_disconnect_ind, DTI2_DISCONNECT_IND); + dti_disconnect_ind->link_id = link->link_id; + dti_disconnect_ind->cause = cause; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_disconnect_ind); + } + else + { + PSEND(link->link_handle, dti_disconnect_ind); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_DISCONNECT_IND", + link->link_id, + hDTI->entity_options); + } + } + break; + + case DTI_CHANNEL_TO_LOWER_LAYER: + { + PALLOC (dti_disconnect_req, DTI2_DISCONNECT_REQ); + dti_disconnect_req->link_id = link->link_id; + dti_disconnect_req->cause = cause; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_disconnect_req); + } + else + { + PSEND(link->link_handle, dti_disconnect_req); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_DISCONNECT_REQ", + link->link_id, + hDTI->entity_options); + } + } + break; + + default: + /* + * no known channel type open so do not send anything + */ + break; + } +#undef VSI_CALLER +} /* send_disconnect_req_or_ind() */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : dti_kerf.c | +| STATE : code ROUTINE : send_ready_req_or_ind | ++--------------------------------------------------------------------+ + + * PURPOSE: Send a Flow Control primitive depending on the direction. + */ + +LOCAL void send_ready_req_or_ind (DTI_HANDLE hDTI, DTI_LINK *link) +{ +#define VSI_CALLER hDTI->handle, + +#ifdef FF_TCP_IP + /* + * do not send flow control primitives in case of riviera link + * but send a Data primitive to trigger next data reception + * this is needed because ATP may has sent data + * where DTILIB was not initialized yet + */ + if(link->link_type EQ RIVIERA_ATP_LINK) + { + PALLOC(dti_data_ind, DTI2_DATA_IND); + dti_data_ind->link_id = link->link_id; + dti_data_ind->desc_list2.list_len = 0; + dti_data_ind->desc_list2.first = (U32)NULL; + PSEND(link->link_handle, dti_data_ind); + return; + } +#endif /* FF_TCP_IP */ + /* + * Check if the link is upwards or downwards + * and send the according connect primitive. + */ + switch (link->direction) + { + case DTI_CHANNEL_TO_HIGHER_LAYER: +#ifdef BT_ADAPTER + if(link->link_type EQ RIVIERA_BT_LINK) + { + btidti_getdata_req(link_id); + } + else +#endif /* BT_ADAPTER */ + { + if(link->link_type EQ ENTITY_LINK) + { + PALLOC (dti_ready_ind, DTI2_READY_IND); + dti_ready_ind->link_id = link->link_id; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_ready_ind); + } + else + { + PSEND(link->link_handle, dti_ready_ind); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_READY_IND", + link->link_id, + hDTI->entity_options); + } + } + } + break; + + case DTI_CHANNEL_TO_LOWER_LAYER: +#ifdef BT_ADAPTER + if(link->link_type EQ RIVIERA_BT_LINK) + { + btidti_getdata_req(link_id); + } + else +#endif /* BT_ADAPTER */ + { + if(link->link_type EQ ENTITY_LINK) + { + PALLOC (dti_getdata_req, DTI2_GETDATA_REQ); + dti_getdata_req->link_id = link->link_id; + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_getdata_req); + } + else + { + PSEND(link->link_handle, dti_getdata_req); + trace_message_link_id(hDTI->handle, + "OUT: DTI2_GETDATA_REQ", + link->link_id, + hDTI->entity_options); + } + } + } + break; + + default: + /* + * no known channel type open so do not send anything + */ + break; + } +#undef VSI_CALLER +} /* send_ready_req_or_ind() */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_close | ++--------------------------------------------------------------------+ + + * + * The function searchs a link in the databank link list and closes it. + * Then it calls the callback function with the signal DTI_REASON_CONNECTION_CLOSED. + */ + +GLOBAL void dti_close (DTI_HANDLE hDTI, + U8 instance, + U8 interfac, + U8 channel, + BOOL flush) +{ + DTI_LINK *link; + + trace_function( hDTI->handle, + "dti_close()", + hDTI->entity_options); + + /* + * Find the link in the database + */ + + if((link = get_pointer_link_table_channel(hDTI, + instance, + interfac, + channel)) NEQ NULL) + { + + trace_message_link_id(hDTI->handle, + "closing DTI connection", /*lint !e605 Increase in pointer capability */ + link->link_id, + hDTI->entity_options); + + if (link->direction EQ DTI_NULL_LINK) + { + set_default_para_link_table(hDTI, link, D_FREE_LINK_ID, D_DIRECTION); + return; + } + + switch (link->connect_state) + { + /* + * The link is already closed + */ + + case DTI_CLOSED: + trace_message_link_id(hDTI->handle, + "Link is already closed for this entity", + link->link_id, + hDTI->entity_options); + return; + + /* + * In all other states the entity sends a disconnect primitive + */ + default: + /* + * exit only after send queue has been emptied? + */ + if(flush EQ TRUE) + { + /* + * if it is not empty, wait for data flow primitives + * from the peer entity + */ + if(link->queue_len NEQ 0) + { + link->connect_state = DTI_CLOSING; + return; + } + else + { + /* + * call the callback function right now. + */ + hDTI->sig_callback( + link->instance, + link->interfac, + link->channel, + DTI_REASON_CONNECTION_CLOSED, + NULL + ); + } + } + + if (link->link_type NEQ RIVIERA_ATP_LINK) + /* check for connection towards ATP. The NULL_LINK case is handled + * above, already. + */ + { + send_disconnect_req_or_ind (hDTI, link, DTI_CAUSE_NORMAL_CLOSE); + } +#ifdef FF_TCP_IP + else /* the links goes towards Riviera */ + { + U8 i; + atp_links[link->port_nb] = D_LINK; + ATP_used_flag = FALSE; + for (i=0; i<MAX_ATP_LINKS; i++) + { + if(atp_links[i] NEQ D_LINK) + { + ATP_used_flag = TRUE; + TRACE_EVENT("there are still open ATP links!"); + break; + } + } + } +#endif /* FF_TCP_IP */ + + /* + * close the communication channel + */ + vsi_c_close (hDTI->handle, link->link_handle); + /* + * Set the default parameter. The channel is closed in the neighbour entity. + */ + set_default_para_link_table(hDTI,link, D_FREE_LINK_ID, D_DIRECTION); + + /* + * Note: Flow control and data primitives are silently discarded. + */ + + break; + } + } + else + { + /* + * there is no link to be found in the table + */ + trace_message_iic(hDTI->handle, + "DTI link is alredy closed", + instance, + interfac, + channel, + hDTI->entity_options); + } +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_start | ++--------------------------------------------------------------------+ + + * + * If the entity wants to receive data primitives, this function must be + * called. + */ + +GLOBAL void dti_start( DTI_HANDLE hDTI, U8 instance, U8 interfac, U8 channel) +{ + DTI_LINK *link; + + trace_function( hDTI->handle, + "dti_start()", + hDTI->entity_options); + + /* + * Find the link in the database. + */ + link = get_pointer_link_table_channel(hDTI, instance, interfac, channel); + if(link EQ NULL) + { + /* + * Link id is not in the table. + */ + trace_message_iic(hDTI->handle, + "DTI ERROR: dti_start() - No link id in the database", + instance, + interfac, + channel, + hDTI->entity_options); + return; + } + /* + * Is the entity connected ? + */ + if(link->connect_state NEQ DTI_IDLE) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: link is not connected", + link->link_id, + hDTI->entity_options); + return; + } + /* + * Check if the flow control is not used but do nothing. + */ + if(link->link_options EQ DTI_FLOW_CNTRL_DISABLED) + return; + /* + * Handle the states + */ + switch(link->rx_state) + { + case DTI_RX_IDLE: + /* + * Change the state to indicate ready to receive data. + */ + link->rx_state = DTI_RX_READY; + /* + * No flow control primitive was sent. So send one now. + * NOTE: The parameter link->direction gives information about the + * direction for sending the data. + */ + send_ready_req_or_ind (hDTI, link); + break; + + case DTI_RX_STOPPED: + /* + * The entity has stopped the flow control. + * The flow control was sent already. + * So change state to DTI_RX_READY. + */ + link->rx_state = DTI_RX_READY; + break; + + case DTI_RX_READY: + /* + * dti_start() was already called. + */ + break; + + default: + /* + * Unexpected state - set ERROR. + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: wrong state", + link->link_id, + hDTI->entity_options); + break; + } +} /* dti_start() */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_stop | ++--------------------------------------------------------------------+ + + * + * This function is called if the entity wants to stop receiving of data + * primitives. + */ + +GLOBAL void dti_stop( DTI_HANDLE hDTI, U8 instance, U8 interfac, U8 channel) +{ + DTI_LINK *link; + + trace_function( hDTI->handle, + "dti_stop()", + hDTI->entity_options); + + /* + * Find the link in the databank. + */ + link = get_pointer_link_table_channel(hDTI, instance, interfac, channel); + /* + * It is link id in the table ? + */ + if(link EQ NULL) + { + trace_message_iic(hDTI->handle, + "DTI ERROR: dti_stop() - No link id in the database", + instance, + interfac, + channel, + hDTI->entity_options); + return; + } + /* + * Is the entity connected ? + */ + if(link->connect_state NEQ DTI_IDLE) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: dti_stop() - link is not connected", + link->link_id, + hDTI->entity_options); + return; + } + /* + * Check if the flow control is not used - then do nothing + */ + if(link->link_options EQ DTI_FLOW_CNTRL_DISABLED) + return; + /* + * Handle the states + */ + switch(link->rx_state) + { + case DTI_RX_READY: + /* + * The flow control was already sent therefor change to stop state. + */ + link->rx_state = DTI_RX_STOPPED; + break; + + case DTI_RX_STOPPED: + case DTI_RX_IDLE: + /* + * dti_stop() was already called. + * So there is no need to change state. + */ + break; + + default: + /* + * Other state - ERROR + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: dti_stop() - wrong state", + link->link_id, + hDTI->entity_options); + break; + } +} /* dti_stop() */ + + + +#ifdef _SIMULATION_ +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : dti_kerf.c | +| STATE : code ROUTINE : send_data_test_req_or_ind | ++--------------------------------------------------------------------+ + + * PURPOSE: Get a DTI_DATA_IND and translate it to DTI_DATA_TEST_IND + * and send it. + */ + +LOCAL void send_data_test_req_or_ind (DTI_HANDLE hDTI, + DTI_LINK* link, + T_DTI2_DATA_IND* dti_data_ind) +{ +#define VSI_CALLER hDTI->handle, + U16 len_buf_bits; + U16 i; + U16 len; + U16 j; + T_desc2 *p_desc; + + trace_function(hDTI->handle, + "send_data_test_req_or_ind()", + hDTI->entity_options); + + len_buf_bits = dti_data_ind->desc_list2.list_len * 8; + + /* + * Build the SDU primitive and send it + */ + { + PALLOC_SDU (dti_data_test_ind, DTI2_DATA_TEST_IND, len_buf_bits); + memset (dti_data_test_ind, 0, sizeof (T_DTI2_DATA_TEST_IND)); + + dti_data_test_ind->link_id = dti_data_ind->link_id; + dti_data_test_ind->parameters = dti_data_ind->parameters; + + dti_data_test_ind->sdu.l_buf = len_buf_bits; + dti_data_test_ind->sdu.o_buf = 0; + + /* + * Copy the descs into sdu structure. + */ + if(len_buf_bits > 0) + { + j = 0; + p_desc = (T_desc2*)(dti_data_ind->desc_list2.first); + while(p_desc NEQ NULL) + { + len = p_desc->len; + for(i=0; i < len; i++) + { + dti_data_test_ind->sdu.buf[j] = p_desc->buffer[i]; + j++; + } + p_desc = (T_desc2*)(p_desc->next); + } + } + + /* + * Check if the link is upwards or downwards + * and send the according disconnect primitive. + */ + switch (link->direction) + { + case DTI_CHANNEL_TO_HIGHER_LAYER: + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_data_test_ind); + } + else + { + PSEND(link->link_handle, dti_data_test_ind); + trace_message_l_dl(hDTI->handle, + "OUT: DTI2_DATA_TEST_IND", + dti_data_ind->link_id, + dti_data_ind->desc_list2.list_len, + hDTI->entity_options); + } + break; + + case DTI_CHANNEL_TO_LOWER_LAYER: + if(hDTI->entity_options & DTI_NO_TRACE) + { + PPASS_NTRACE(dti_data_test_ind, + dti_data_test_req, + DTI2_DATA_TEST_REQ); + PSEND_NTRACE(link->link_handle, dti_data_test_req); + } + else + { + PPASS(dti_data_test_ind, dti_data_test_req, DTI2_DATA_TEST_REQ); + PSEND(link->link_handle, dti_data_test_req); + trace_message_l_dl(hDTI->handle, + "OUT: DTI2_DATA_TEST_REQ", + dti_data_ind->link_id, + dti_data_ind->desc_list2.list_len, + hDTI->entity_options); + } + break; + + default: + /* + * no known channel type open so do not send anything + */ + break; + } + } + /* + * Free the dti_data_ind primitive and the descs in the linked list. + */ + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); +#undef VSI_CALLER +} /* send_data_test_req_or_ind() */ +#endif /* _SIMULATION_ */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : dti_kerf.c | +| STATE : code ROUTINE : send_data_req_or_ind | ++--------------------------------------------------------------------+ + + * PURPOSE: Send a Data primitive depending on the direction. + */ + +LOCAL void send_data_req_or_ind (DTI_HANDLE hDTI, + DTI_LINK* link, + T_DTI2_DATA_IND* dti_data_ind) +{ +#ifndef _SIMULATION_ + U32 link_id; + U16 list_len; +#endif /* !_SIMULATION_ */ +#ifdef BT_ADAPTER + if(link->link_type EQ RIVIERA_BT_LINK) + { + btidti_data_req(dti_data_ind); + } + else +#endif /* BT_ADAPTER */ +/* + * Check if the primitive is directed to a GPF or ATP entity, and send it. + */ +#ifdef FF_TCP_IP + if(link->link_type EQ RIVIERA_ATP_LINK) + { + dti_send_data_to_atp(hDTI, link, dti_data_ind); + return; + } +#endif /* FF_TCP_IP */ + +#ifdef _SIMULATION_ + send_data_test_req_or_ind(hDTI, link, dti_data_ind); +#else /* _SIMULATION_ */ +#define VSI_CALLER hDTI->handle, + /* + * Check if the link is upwards or downwards + * and send the according disconnect primitive. + */ + switch (link->direction) + { + case DTI_CHANNEL_TO_HIGHER_LAYER: +#ifdef BT_ADAPTER + if(link->link_type EQ RIVIERA_LINK) + { + btidti_data_req(dti_data_ind); + } + else +#endif /* BT_ADAPTER */ + { + if(hDTI->entity_options & DTI_NO_TRACE) + { + PSEND_NTRACE(link->link_handle, dti_data_ind); + } + else + { + link_id = dti_data_ind->link_id; + list_len = dti_data_ind->desc_list2.list_len; + PSEND(link->link_handle, dti_data_ind); + trace_message_l_dl(hDTI->handle, + "OUT: DTI2_DATA_IND", + link_id, + list_len, + hDTI->entity_options); + } + } + break; + + case DTI_CHANNEL_TO_LOWER_LAYER: + if(hDTI->entity_options & DTI_NO_TRACE) + { + PPASS_NTRACE(dti_data_ind, dti_data_req, DTI2_DATA_REQ); + PSEND_NTRACE(link->link_handle, dti_data_req); + } + else + { + PPASS(dti_data_ind, dti_data_req, DTI2_DATA_REQ); + link_id = dti_data_req->link_id; + list_len = dti_data_req->desc_list2.list_len; + PSEND(link->link_handle, dti_data_req); + trace_message_l_dl(hDTI->handle, + "OUT: DTI2_DATA_REQ", + link_id, + list_len, + hDTI->entity_options); + } + break; + + default: + /* + * no known channel type open so do not send anything + */ + break; + } +#undef VSI_CALLER +#endif /* else _SIMULATION_ */ +} /* send_data_req_or_ind() */ + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : dti_send_data | ++--------------------------------------------------------------------+ + + * + * This function sends data. If the database direction is set to + * DTI_UPLINK then it sends a dti_data_req primitive otherwise a DTI_DATA_IND + * primitive. + */ + +GLOBAL void dti_send_data (DTI_HANDLE hDTI, + U8 instance, + U8 interfac, + U8 channel, + T_DTI2_DATA_IND *dti_data_ind) +{ + DTI_LINK *link; + T_DTI2_DATA_IND *hlp_data_ind; + + trace_function(hDTI->handle, + "dti_send_data()", + hDTI->entity_options); + + /* + * Find the link in the database. + */ + link = get_pointer_link_table_channel(hDTI, instance, interfac, channel); + if(link EQ NULL) + { + /* + * link_id is not in the table. + */ + trace_message_iic(hDTI->handle, + "DTI ERROR: dti_send_data() - No link id in the database", + instance, + interfac, + channel, + hDTI->entity_options); + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + return; + } + + /* + * Is the entity connected ? + */ + if(link->connect_state NEQ DTI_IDLE) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: dti_send_data() - link is not connected", + link->link_id, + hDTI->entity_options); + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + return; + } + + /* + * If link is a NULL device then just free the message + */ + if (link->direction EQ DTI_NULL_LINK) + { + mfree_desc (hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + return; + } + + /* + * There is no flow control, so the primitive doesn't get into the queue + * and has to get sent at once. + */ + if(link->link_options EQ DTI_FLOW_CNTRL_DISABLED) + { + send_data_req_or_ind(hDTI, link, dti_data_ind); + return; + } + + switch (link->tx_state) + { + case DTI_TX_IDLE: + case DTI_TX_BUFFER_FULL: + /* + * While waiting for a flow control primitive no sending is possible. + * Put the primitive dti_data_ind in the queue. + */ + put_dti_data_ind_in_queue_managed (hDTI, link, dti_data_ind); + break; + + case DTI_TX_FLOW: + /* + * The flow control primitive is already received. + * So just send Data primitive and change state. + * Because of ATP links there might be still a prim in the queue + * therefore we have to use the queue for this + */ + put_dti_data_ind_in_queue(hDTI, link, dti_data_ind); + /* + * Read the last packet from the queue and send it. + */ + { + hlp_data_ind = get_dti_data_ind_from_queue(hDTI, link); + hlp_data_ind->link_id = link->link_id; + /* + * The packet will be sent. Now change the state to DTI_TX_IDLE. + */ + link->tx_state = DTI_TX_IDLE; + /* + * Send the primitive depending on its direction. + */ + send_data_req_or_ind(hDTI, link, hlp_data_ind); + } + break; + + default: + /* + * Unknown state.. + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: dti_send_data() - wrong state", + link->link_id, + hDTI->entity_options); + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + break; + } + /* + * if queue is full now, send a warning callback + */ + if((link->queue_len >= link->queue_size) AND + (link->link_options NEQ DTI_QUEUE_UNBOUNDED)) + { + link->tx_state = DTI_TX_BUFFER_FULL; + hDTI->sig_callback(link->instance, + link->interfac, + link->channel, + DTI_REASON_TX_BUFFER_FULL, + NULL); + } +} /* dti_send_data() */ + + + +/* ++--------------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : flow_control_prim_received | ++--------------------------------------------------------------------------+ + + PURPOSE : Process primitives DTI_GETDATA_REQ and DTI_READY_IND + received from neighbour DTI + */ + +GLOBAL void flow_control_prim_received (DTI_HANDLE hDTI, + U32 link_id, + U8 direction) +{ + DTI_LINK* link; + T_DTI2_DATA_IND* dti_data_ind; + + trace_function(hDTI->handle, + "flow_control_prim_received()", + hDTI->entity_options); + + /* + * get link pointer + */ + link = get_pointer_link_table(hDTI, link_id, direction); + if(link EQ NULL) + { + /* + * There is no link_id which requested to the link_id in the link_table. + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: fc_prim - No link in data base", + link_id, + hDTI->entity_options); + return; + } + + /* + * check for valid link + * the link is valid if it is in IDLE or CLOSING state + * Flow Control primitives are unexpected if Flow Control is disabled + */ + if(((link->connect_state NEQ DTI_IDLE) AND + (link->connect_state NEQ DTI_CLOSING)) OR + (link->link_options EQ DTI_FLOW_CNTRL_DISABLED)) + { + TRACE_EVENT_P4("HORST=7, weil: connect_state %d, link_options %d, link_id %u, direction %d", + link->connect_state, link->link_options, link_id, direction); + return; + } + /* + * get next prim from queue + */ + dti_data_ind = get_dti_data_ind_from_queue(hDTI, link); + /* + * Select the state. + */ + switch (link->tx_state) + { + case DTI_TX_IDLE: + case DTI_TX_FLOW: + /* + * A flow control primitive is received. Send a data packet + * if there is any in the queue or change the state. + * In case of an RIVIERA_ATP_LINK it is necessary to check the send queue + * also in DTI_TX_FLOW state + */ + if(dti_data_ind NEQ NULL) + { + /* + * Select link_id and send data. + */ + dti_data_ind->link_id = link->link_id; + send_data_req_or_ind(hDTI, link, dti_data_ind); + + /* + * Stay in this state. + */ + } + else + { + /* + * Change the state because there is a flow control primitive + * and no packet has been sent. + */ + link->tx_state = DTI_TX_FLOW; + } + break; + + case DTI_TX_BUFFER_FULL: + /* + * The buffer had been full. Send packets from queue and signal ready + */ + if(dti_data_ind NEQ NULL) + { + /* + * Select link_id and send data. + */ + dti_data_ind->link_id = link->link_id; + send_data_req_or_ind(hDTI, link, dti_data_ind); + /* + * Change the state if the queue is ready + * to get the next data from the entity + */ + if(link->queue_len < link->queue_size) + { + link->tx_state = DTI_TX_IDLE; + } + } + else + { + /* + * Change the state because there is a flow control primitive + * and no packet has been sent. + */ + link->tx_state = DTI_TX_FLOW; + } + /* + * Signal to the callback function that the buffer is ready. + */ + if((link->connect_state NEQ DTI_CLOSING) AND + (link->tx_state NEQ DTI_TX_BUFFER_FULL)) + { + hDTI->sig_callback(link->instance, + link->interfac, + link->channel, + DTI_REASON_TX_BUFFER_READY, + NULL); + } + break; + + default: + trace_message_link_id(hDTI->handle, + "DTI ERROR: Wrong state for flow control primitive", + link->link_id, + hDTI->entity_options); + /* + * free whole prim, incl. descs + */ + if(dti_data_ind NEQ NULL) + { + mfree_desc(hDTI, (T_desc_list2*) &(dti_data_ind->desc_list2)); + PFREE(dti_data_ind); + } + break; + } + + /* + * if the connection is to be closed and the send queue is empty + * then close the connection now + */ + if((link->queue_len EQ 0) AND + (link->connect_state EQ DTI_CLOSING)) + { + send_disconnect_req_or_ind(hDTI, link, DTI_CAUSE_NORMAL_CLOSE); + close_link_with_signal(hDTI, link); + } +} /* flow_control_prim_received() */ + + + +/* ++--------------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : connect_init_prim_received | ++--------------------------------------------------------------------------+ + +PURPOSE : Process primitives DTI_CONNECT_REQ and DTI_CONNECT_IND + received from neighbour DTI +*/ + +GLOBAL void connect_init_prim_received (DTI_HANDLE hDTI, + U32 link_id, + U32 version, + U8 direction) +{ + DTI_LINK* link; + BOOL send_cnf = FALSE; + BOOL send_disc = FALSE; + U8 signal = DTI_NO_SIGNAL; + + trace_function( hDTI->handle, + "connect_init_prim_received()", + hDTI->entity_options); + + /* + * Check version of peer dtilib + */ + if(check_dti_version(hDTI, version) EQ FALSE) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: init_prim - Wrong DTI version", + link_id, + hDTI->entity_options); + /* + * Inform peer dtilib that connection failed + */ + link = get_pointer_link_table(hDTI, link_id, direction); + if(link NEQ NULL) + { + send_disconnect_req_or_ind (hDTI, link, DTI_CAUSE_UNSUPPORTED_VERSION); + close_link_with_signal(hDTI, link); + } + return; + } + + switch (acquire_link (hDTI, link_id, direction, &link) ) + { + case DTI_S_FOUND: + /* + * Entry for link_id found, continue connecting procedure + */ + break; + + case DTI_S_CREATED_NEW: + /* + * There is no entry with the requested link_id in the link_table yet. + * Wait for call of dti_open(). + * The remaining parameters are set in dti_open(). Then the response + * primitive will be sent. + */ + link->connect_state = DTI_CONNECTING; + return; + + default: + /* + * No free link + */ + return; + } + + /* + * Start up connecting. + */ + switch (link->connect_state) + { + case DTI_IDLE: + /* + * Reset the link and send a response primitive, free the data packets, + * and call the callback funktion. + */ + set_reset_req_para_link_table(hDTI, link); + send_cnf = TRUE; + signal = DTI_REASON_CONNECTION_OPENED; + trace_message_link_id(hDTI->handle, + "DTI connection opened", + link->link_id, + hDTI->entity_options); + break; + + case DTI_SETUP: + /* + * Collision ! The neighbour entity has sent a dti_connect_ind + * primitive as well which means the neighbor enitiy is willing to connect as well. + * So we send a response and open the connection. + */ + link->connect_state = DTI_IDLE; + send_cnf = TRUE; + signal = DTI_REASON_CONNECTION_OPENED; + link->rx_state = DTI_RX_IDLE; + trace_message_link_id(hDTI->handle, + "DTI connection opened", + link->link_id, + hDTI->entity_options); + break; + + case DTI_CLOSING: + /* + * because of the connect request, internal buffers + * are being reset. Thus, the send queue is empty now + * and the connection can be closed down. + * there has to be a confirmation for the connect + * primitive anyway + */ + send_disc = TRUE; + send_cnf = TRUE; + break; + + case DTI_CLOSED: + /* + * dti_open() is not called yet. The confirm primitive will + * be sent then and the parameter will be set. + */ + link->connect_state = DTI_CONNECTING; + break; + + default: + trace_message_link_id(hDTI->handle, + "DTI ERROR: init_prim - Wrong state dtilib", + link_id, + hDTI->entity_options); + break; + } + + /* + * Send the confirm primitive. + */ + if (send_cnf) + { + send_connect_res_or_cnf (hDTI, link); + } + + /* + * Send the disconnect primitive. + */ + if (send_disc) + { + send_disconnect_req_or_ind (hDTI, link, DTI_CAUSE_NORMAL_CLOSE); + close_link_with_signal(hDTI, link); + /* + * No more signals to be sent in this case.. + */ + return; + } + + /* + * Activate callback function with reason_connection_opened + * and, additionally, signal tx_buffer_ready if the queue is used. + */ + if(signal EQ DTI_REASON_CONNECTION_OPENED) + { + send_open_ready_callback (hDTI, link); + } +} /* connect_init_prim_received() */ + + + +/* ++--------------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : connect_confirm_prim_received | ++--------------------------------------------------------------------------+ + +PURPOSE : Process primitives DTI_CONNECT_RES and DTI_CONNECT_CNF + received from neighbour DTI +*/ + +GLOBAL void connect_confirm_prim_received (DTI_HANDLE hDTI, + U32 link_id, + U32 version, + U8 direction) +{ + DTI_LINK* link; + U8 signal = DTI_NO_SIGNAL; + + trace_function(hDTI->handle, + "connect_confirm_prim_received()", + hDTI->entity_options); + + /* + * Note: No need to check the version because this has already been done + * by the primitives dti_connect_req and dti_connect_ind. + */ + if((link = get_pointer_link_table(hDTI, link_id, direction)) EQ NULL) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: cnf_prim - No link in dtilib", + link_id, + hDTI->entity_options); + return; + } + + /* + * The link is in the list so check the state. + */ + switch (link->connect_state) + { + case DTI_SETUP: + /* + * The entity can now enter the final state. The entity connection + * is established. + */ + link->connect_state = DTI_IDLE; + signal = DTI_REASON_CONNECTION_OPENED; + link->rx_state = DTI_RX_IDLE; + trace_message_link_id(hDTI->handle, + "DTI connection opened", + link->link_id, + hDTI->entity_options); + break; + + case DTI_CLOSED: + case DTI_IDLE: + /* + * We are already in the final state. So there is nothing to do here. + */ + break; + + default: + trace_message_link_id(hDTI->handle, + "DTI ERROR: cnf_prim - Wrong state dtilib", + link_id, + hDTI->entity_options); + break; + } + + /* + * Activate callback function with reason_connection_opened + * and, additionally, signal tx_buffer_ready if the queue is used. + */ + if(signal EQ DTI_REASON_CONNECTION_OPENED) + { + send_open_ready_callback (hDTI, link); + } +} /* connect_confirm_prim_received() */ + + + +/* ++--------------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : disconnect_prim_received | ++--------------------------------------------------------------------------+ + +PURPOSE : Process primitives DTI_DISCONNECT_IND and DTI_DISCONNECT_REQ + received from neighbour DTI +*/ + +GLOBAL void disconnect_prim_received (DTI_HANDLE hDTI, + U32 link_id, + U8 direction) +{ + + DTI_LINK *link; + + trace_function(hDTI->handle, + "disconnect_prim_received()", + hDTI->entity_options); + + /* + * Is the link in the link list ? + */ + if((link = get_pointer_link_table( + hDTI, + link_id, + direction) + ) NEQ NULL) + { + switch (link->connect_state) + { + /* + * Link is already closed. + */ + case DTI_CLOSED: + trace_message_link_id(hDTI->handle, + "DTI link alredy closed", + link->link_id, + hDTI->entity_options); + break; + + /* + * Close the link. + */ + default: + close_link_with_signal(hDTI, link); + + break; + } + } + +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERP | +| STATE : code ROUTINE : data_prim_received | ++--------------------------------------------------------------------+ + + * + * Process primitives DTI_DATA_REQ and DTI_DATA_IND received from DTI peer + */ + +GLOBAL void data_prim_received(DTI_HANDLE hDTI, + T_DTI2_DATA_IND *dti_data_ind, + U8 direction) +{ + DTI_LINK *link; + U32 link_id; + + trace_function(hDTI->handle, + "data_prim_received()", + hDTI->entity_options); + + /* + * Check if old or new SAP is supported. + */ + link_id = dti_data_ind->link_id; + + /* + * Is the link in the link list ? + */ + link = get_pointer_link_table(hDTI, link_id, direction); + if(link EQ NULL) + { + /* + * The link_id is not in the list of ids. + */ + trace_message_link_id(hDTI->handle, + "DTI ERROR: data_prim - No link in data base", + link_id, + hDTI->entity_options); + /* + * Just ignore the received data primitive. + */ + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE(dti_data_ind); + return; + } + /* + * If there is no connection silently discard primitive. + */ + if(link->connect_state NEQ DTI_IDLE) + { + trace_message_link_id(hDTI->handle, + "DTI ERROR: data_prim_received() - link is not connected", + link->link_id, + hDTI->entity_options); + /* + * Just ignore the received data primitive. + */ + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE(dti_data_ind); + return; + } + /* + * Check if no flow control should be supported. Pass the primitive at once + * to the entity over the callback function. + */ + if(link->link_options EQ DTI_FLOW_CNTRL_DISABLED) + { + hDTI->sig_callback(link->instance, + link->interfac, + link->channel, + DTI_REASON_DATA_RECEIVED, + dti_data_ind); + return; + } + +#ifdef FF_TCP_IP + /* + * Get primitive content in case it is a RIVIERA_ATP_LINK + */ + if(link->link_type EQ RIVIERA_ATP_LINK) + { + if((link->rx_state EQ DTI_RX_READY) OR + (link->rx_state EQ DTI_RX_STOPPED)) + { + /* + * DTI does not really know if there is data available + * In case there is no ATP data the list_len value is set to 0 + */ + get_data_from_atp(hDTI, link, dti_data_ind); + + if(dti_data_ind->desc_list2.list_len EQ 0) + { + /* + * there is no data in the ATP buffer any more + * so release the primitive and start ATP flow control again + */ + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + TRACE_EVENT("atp_set_signal: ATP_RX_FLOW_ON"); + atp_set_signal(hDTI->entity_id_p, + link->port_nb, + ATP_RX_FLOW_ON, + ATP_RX_FLOW_UNMASK); + return; + } + } + else + { + /* + * the entity has stopped data flow + * currently it is not allowed to receive data + */ + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + return; + } + } +#endif /* FF_TCP_IP */ + + /* + * Handle the states. + */ + switch(link->rx_state) + { + case DTI_RX_READY: + /* + * Receive dti_data_ind, give a signal and send flow control primitive. + */ + hDTI->sig_callback(link->instance, + link->interfac, + link->channel, + DTI_REASON_DATA_RECEIVED, + dti_data_ind); + /* + * Check if the entity has stoped during the callback. + * If yes do not send a flow control. + */ + if(link->rx_state EQ DTI_RX_READY) + { + send_ready_req_or_ind(hDTI, link); + } + else + { + link->rx_state = DTI_RX_IDLE; + } + break; + + case DTI_RX_STOPPED: + /* + * The entity has stoped the communication but the flow control primitive to + * the neighbour entity was sent. The last dti_data_ind signal must be sended + * to the entity. DTILIB change to DTI_RX_IDLE. + */ + link->rx_state = DTI_RX_IDLE; + hDTI->sig_callback(link->instance, + link->interfac, + link->channel, + DTI_REASON_DATA_RECEIVED, + dti_data_ind); + break; + + default: + trace_message_link_id(hDTI->handle, + "DTI ERROR: Wrong state for dti_data_ind primitive", + link_id, + hDTI->entity_options); + mfree_desc(hDTI, &dti_data_ind->desc_list2); + PFREE (dti_data_ind); + break; + } +} /* data_prim_received() */ + + + +#ifdef _SIMULATION_ +/* ++--------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERP | +| STATE : code ROUTINE : data_test_prim_received | ++--------------------------------------------------------------------+ + +PURPOSE : Process primitives DTI_DATA_TEST_REQ and DTI_DATA_TEST_IND + received from neighbour DTI +*/ + +GLOBAL void data_test_prim_received (DTI_HANDLE hDTI, + T_DTI2_DATA_TEST_IND *dti_data_test_ind, + U8 direction) +{ + USHORT len_buff, offset, i; + T_desc2 *test_desc; + + trace_function(hDTI->handle, + "data_test_prim_received()", + hDTI->entity_options); + + /* + * Fill in dti_data_ind the structure. + */ + { + PALLOC (dti_data_ind, DTI2_DATA_IND); + + dti_data_ind->link_id = dti_data_test_ind->link_id; + dti_data_ind->parameters = dti_data_test_ind->parameters; + + len_buff = dti_data_test_ind->sdu.l_buf>>3; + offset = dti_data_test_ind->sdu.o_buf>>3; + + /* + * Build a new desc and fill in the parameter. + */ + dti_make_new_desc(hDTI, &test_desc, len_buff, TRUE); + + for(i=0; i < len_buff; i++) + test_desc->buffer[i] = dti_data_test_ind->sdu.buf[i+offset]; + + dti_data_ind->desc_list2.list_len = len_buff; + dti_data_ind->desc_list2.first = (ULONG) test_desc; + + /* + * Handle the primitive. + */ + PFREE (dti_data_test_ind); + + data_prim_received (hDTI, dti_data_ind, direction); + } +} + +#endif /* _SIMULATION_ */ + + +/* ++-------------------------------------------------------------------------+ +| PROJECT : DTILIB MODULE : DTI_KERF | +| STATE : code ROUTINE : vsi_c_psend_ntrace | ++-------------------------------------------------------------------------+ + + * + * vsi_c_psend without traces + */ + +#ifdef MEMORY_SUPERVISION +GLOBAL SHORT vsi_c_psend_ntrace ( T_HANDLE Caller, T_HANDLE ComHandle, + T_VOID_STRUCT *ptr, ULONG MsgLen, const char *file, int line ) +#else /* MEMORY_SUPERVISION */ + GLOBAL SHORT vsi_c_psend_ntrace ( T_HANDLE Caller, T_HANDLE ComHandle, + T_VOID_STRUCT *ptr, ULONG MsgLen ) +#endif /* MEMORY_SUPERVISION */ +{ + T_QMSG QMsg; + + QMsg.Msg.Primitive.Prim = (T_VOID_STRUCT*)(D2P(ptr)); + QMsg.Msg.Primitive.PrimLen = MsgLen; + QMsg.MsgType = MSG_PRIMITIVE; + +#ifdef MEMORY_SUPERVISION + return ( vsi_c_send ( Caller, ComHandle, &QMsg, file, line) ); +#else + return ( vsi_c_send ( Caller, ComHandle, &QMsg) ); +#endif /* MEMORY_SUPERVISION */ +}