FreeCalypso > hg > freecalypso-sw
diff gsm-fw/g23m-aci/bat/bat_l2p.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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/g23m-aci/bat/bat_l2p.c Sun Oct 12 01:45:14 2014 +0000 @@ -0,0 +1,398 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : BAT ++----------------------------------------------------------------------------- +| Copyright 2005 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. ++----------------------------------------------------------------------------- +| Purpose : This Modul holds the functions +| for the L2P interface ++----------------------------------------------------------------------------- +*/ + +#define _BAT_L2P_C_ + +/*==== INCLUDES =============================================================*/ +#include "typedefs.h" +#include "gdd.h" +#include "gdd_sys.h" /* to get semaphore access */ +#include "l2p_types.h" +#include "l2p.h" +#include "bat.h" +#include "bat_ctrl.h" +#include "bat_intern.h" + +/*==== DEFINES ===========================================================*/ +#define ENTER_CRITICAL_SECTION(sem) if (bat_enter_critical_section(sem))return (NULL); +#define LEAVE_CRITICAL_SECTION(sem) if (bat_leave_critical_section(sem))return -1; + +/*==== LOCAL VARS ===========================================================*/ + + +/*==== LOCAL FUNCTIONS =====================================================*/ + +LOCAL void bat_semaphore_err (void) +{ + static U8 out = 0; + if (!out) + { + out = 1; + BAT_TRACE_ERROR("semaphore error"); + } +} + + +LOCAL int bat_enter_critical_section (T_HANDLE sem) +{ + if (gdd_sys_sem_down (sem) NEQ VSI_OK) + { + bat_semaphore_err(); + return -1; + } + else + { + return 0; + } +} + + +LOCAL int bat_leave_critical_section (T_HANDLE sem) +{ + if (gdd_sys_sem_up(sem) NEQ VSI_OK) + { + bat_semaphore_err(); + return -1; + } + else + { + return 0; + } +} + +/* + * we have to maintain some stuff for L2P_Receive(). + */ +LOCAL void bat_update_l2p_mt (T_BAT_instance_maintain *inst_mt, T_GDD_SEGMENT *desc, U16 length, BOOL substract) +{ + BAT_TRACE_EVENT_P1("bat_update_l2p_mt(): segment len is %d", length); + inst_mt->l2p_mt.desc = desc; + if (substract) + { + inst_mt->l2p_mt.length = inst_mt->l2p_mt.length - length; + } + else + { + inst_mt->l2p_mt.length = length; + } +} + + +LOCAL T_GDD_SEGMENT *bat_get_from_l2p_mt_desc (T_BAT_instance_maintain *inst_mt) +{ + return (inst_mt->l2p_mt.desc); +} + +LOCAL U16 bat_get_from_l2p_mt_length (T_BAT_instance_maintain *inst_mt) +{ + return (inst_mt->l2p_mt.length); +} + + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : MODULE : BINARY AT COMMAND LIBRARY | +| STATE : code ROUTINE : bat_l2p_receive | ++----------------------------------------------------------------------------+ +PURPOSE : + This function is a wrapper around L2P_Receive to have all L2P related stuff + in one module. +*/ + +BOOL bat_l2p_receive (U8 inst_hndl, T_GDD_BUF *buf) +{ + T_BAT_instance_maintain *inst_mt = NULL; + T_GDD_SEGMENT *seg = NULL; + U16 length = 0; + T_L2P_STATUS l2p_status; + + if (bat_get_instance_from_instance_handle(inst_hndl, &inst_mt)) + { + BAT_TRACE_ERROR ("bat_l2p_receive(): inst_hndl is not correct!"); + return (FALSE); + } + + inst_mt->buffer.gdd_buf_rcv = buf; + BAT_TRACE_EVENT_P2 ("bat_l2p_receive(): data length: %d, has c_segment %d", buf->length, buf->c_segment); + + seg = buf->ptr_gdd_segment; + ++seg; /* Skip first segment which is the protocol ID and not needed */ + + length = buf->length; + + bat_update_l2p_mt (inst_mt, seg, length, FALSE); + + /* + * for the case that the BAT Module at ACI was not able to send BAT responses/indications, + * it builds up a linked list of responses/indications, + * which then is sent at once when BAT Module was able again. + * That is why we have here to iterate over the GDD list. + */ + do + { + /* + * within L2P_Receive() is called bat_l2p_get_next_buf_seg() if neccessary (fragmentation) + * and finally it is called bat_l2p_message_rxd(). + * Within bat_l2p_message_rxd() is called the application's callback. + */ + BAT_TRACE_EVENT("bat_l2p_receive() loop..."); + l2p_status = L2P_Receive(inst_hndl, seg->ptr_data, seg+1, length, seg->c_data); + switch (l2p_status) + { + case (L2P_STAT_SUCCESS): + { + /* for the next iteration get the updated parameter for L2P_Receive() */ + seg = bat_get_from_l2p_mt_desc(inst_mt); + length = bat_get_from_l2p_mt_length(inst_mt); + break; + } + default: /* any error */ + { + BAT_TRACE_EVENT_P1("bat_l2p_receive(): L2P status = %d", l2p_status); + return (FALSE); + } + } + } while(seg); + + return (TRUE); +} + + +/*==== functions exported to L2P ============================================*/ + +/* + * This function is called by L2P_Send() and L2P_Receive() + */ +void *bat_l2p_get_next_buf_seg (U8 inst_hndl, void *seg_hdr, void **seg_hdr_ptr, U16 *segSize) +{ + T_BAT_instance_maintain *inst_mt = NULL; + T_GDD_SEGMENT *gdd_seg = (T_GDD_SEGMENT *)seg_hdr; + T_GDD_SEGMENT *seg = NULL; + + if (seg_hdr EQ NULL) + { + BAT_TRACE_EVENT ("bat_l2p_get_next_buf_seg(): GDD buffer is complete"); + return (NULL); + } + + if (bat_get_instance_from_instance_handle(inst_hndl, &inst_mt)) + { + BAT_TRACE_ERROR ("bat_l2p_get_next_buf_seg(): inst_hndl is not correct!"); + return (NULL); + } + + /* check whether we are in RX context (it is called for TX as well) */ + seg = bat_get_from_l2p_mt_desc(inst_mt); + + if (seg AND ((seg+1) EQ gdd_seg)) + { + bat_update_l2p_mt(inst_mt, gdd_seg+1, gdd_seg->c_data, TRUE); + } + + return (void*)(gdd_seg->ptr_data); +} + + +void *bat_l2p_get_tx_buffer(T_BAT_instance inst_hndl, U16 data_size, + void **seg_hdr_ptr, U16 *total_size, U16 *seg_size) +{ + T_BAT_instance_maintain *inst_mt = NULL; + T_GDD_BUF *buf = NULL; + T_GDD_SEGMENT * seg = NULL; + + BAT_TRACE_FUNCTION ("bat_l2p_get_tx_buffer()"); + + if (bat_get_instance_from_instance_handle(inst_hndl, &inst_mt)) + { + BAT_TRACE_ERROR ("bat_l2p_get_tx_buffer(): inst_hndl is not correct!"); + return (NULL); + } + + if (data_size >= (int)(inst_mt->config->adapter.cap.dio_cap.mtu_size)) + { + BAT_TRACE_ERROR ("bat_l2p_get_tx_buffer(): requested buffer too big!"); + return (NULL); + } + + /* + * according to GR we have to make + * gdd_get_send_buffer() and gdd_send_data() "atomic", + * which means we release the semaphore in bat_l2p_send_frame() + */ + ENTER_CRITICAL_SECTION(inst_mt->sem_BAT); + + if (inst_mt->config->adapter.gdd_if.gdd_get_send_buffer + ((T_GDD_CON_HANDLE)(inst_mt->con_handle), &buf, data_size) NEQ GDD_OK) + { + BAT_TRACE_ERROR ("bat_l2p_get_tx_buffer(): call to get gdd buffer failed!"); + return (NULL); + } + /* To memorize the buffer address for later sending */ + inst_mt->buffer.gdd_buf = buf; + /* the first 2 bytes are not used */ + *total_size = (U16)(buf->length - 2); + /*store the pointer pointing to the next seg, ignore the first ptr bec it is for other purpose*/ + + seg = buf->ptr_gdd_segment; + ++seg; /* Skip first segment which is the protocol ID and not needed */ + *seg_hdr_ptr = (void*)(seg+1); + *seg_size = seg->c_data; + + return (void*)(seg->ptr_data); +} + + +int bat_l2p_send_frame(T_BAT_instance inst_hndl) +{ + T_BAT_instance_maintain *inst_mt = NULL; + + BAT_TRACE_FUNCTION ("bat_l2p_send_frame()"); + + + if (bat_get_instance_from_instance_handle(inst_hndl, &inst_mt)) + { + BAT_TRACE_ERROR ("bat_l2p_send_frame(): inst_hndl is not correct!"); + return (0); + } + + if (inst_mt->config->adapter.gdd_if.gdd_send_data + ((T_GDD_CON_HANDLE)(inst_mt->con_handle), inst_mt->buffer.gdd_buf) NEQ GDD_OK) + { + BAT_TRACE_ERROR ("bat_l2p_send_frame(): call to send gdd buffer failed!"); + LEAVE_CRITICAL_SECTION(inst_mt->sem_BAT); + return (-1); + } + + LEAVE_CRITICAL_SECTION(inst_mt->sem_BAT); + /*return OK*/ + return (0); +} + + +void *bat_l2p_get_rx_buffer(U8 inst_hndl) +{ + T_BAT_instance_maintain *inst_mt = NULL; + + BAT_TRACE_FUNCTION ("bat_l2p_get_rx_buffer()"); + + if (bat_get_instance_from_instance_handle(inst_hndl, &inst_mt)) + { + BAT_TRACE_ERROR ("bat_l2p_get_rx_buffer(): inst_hndl is not correct!"); + return (NULL); + } + /* set the state of the buffer */ + bat_change_buffer_state(inst_mt, BAT_BUF_FILLING); + + return (inst_mt->buffer.data); +} + + +void bat_l2p_message_rxd (U8 inst_hndl, U8 client_id, U32 data_tag, void *data_ptr, U16 data_size) +{ + T_BAT_instance_maintain *inst_mt = NULL; + T_BATC_confirm cnf; + T_BAT_return ret = BAT_ERROR; + T_GDD_SEGMENT * seg = NULL; + + data_size = data_size; /* prevent compiler warnings */ + + BAT_TRACE_FUNCTION ("bat_l2p_message_rxd()"); + + if (bat_get_instance_from_instance_handle(inst_hndl, &inst_mt)) + { + BAT_TRACE_ERROR ("bat_l2p_message_rxd(): inst_hndl is not correct!"); + return; + } + + bat_change_buffer_state(inst_mt, BAT_BUF_FILLED); + + switch (client_id) + { + case (BAT_CONTROL_CHANNEL): + { + cnf.rsp.ptr_bat_open_client_cnf = data_ptr; + cnf.rsp_params = (T_BATC_rsp_param)data_tag; + ret = bat_control_confirm_rcv (inst_hndl, cnf); + break; + } + case (BAT_BROADCAST_CHANNEL): + { + inst_mt->buffer.rsp.ctrl_response = (T_BAT_ctrl_response)data_tag; + inst_mt->buffer.rsp.response.ptr_at_ok = data_ptr; + ret = bat_unsolicited_code_rcv (inst_hndl, &(inst_mt->buffer.rsp)); + break; + } + default: + { + inst_mt->buffer.rsp.ctrl_response = (T_BAT_ctrl_response)data_tag; + inst_mt->buffer.rsp.response.ptr_at_ok = data_ptr; + ret = bat_command_response_rcv (inst_hndl, client_id, &(inst_mt->buffer.rsp)); + break; + } + } + switch (ret) + { + case (BAT_OK): + case (BAT_BUSY_RESOURCE): + { + break; + } + case (BAT_ERROR): + { + BAT_TRACE_ERROR ("bat_l2p_message_rxd(): received data have not been processed!"); + break; + } + } + + seg = bat_get_from_l2p_mt_desc(inst_mt); + + if (seg) + { + /* Get next segment */ + int cur_idx = seg - inst_mt->buffer.gdd_buf_rcv->ptr_gdd_segment; + T_GDD_SEGMENT * next_seg; + + BAT_TRACE_EVENT_P1("buffer starts at 0x%08x", inst_mt->buffer.gdd_buf_rcv->ptr_gdd_segment); + BAT_TRACE_EVENT_P1("seg is 0x%08x", seg); + + BAT_TRACE_EVENT_P1("cur_idx is %d", cur_idx); + + if(cur_idx >= inst_mt->buffer.gdd_buf_rcv->c_segment-1) + next_seg = 0; + else + next_seg = ++seg; + + if (next_seg EQ NULL) + { + bat_update_l2p_mt(inst_mt, NULL, 0, FALSE); + } + else + { + /* + * update to the next GDD descriptor, which has a L2P header + * and reduce the overall L2P data length by the currently processed data length + */ + bat_update_l2p_mt(inst_mt, next_seg, seg->c_data, TRUE); + } + } +} +