FreeCalypso > hg > fc-magnetite
diff src/g23m-aci/gdd_dio/gdd_dio_if.c @ 162:53929b40109c
src/g23m-aci: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 11 Oct 2016 02:02:43 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-aci/gdd_dio/gdd_dio_if.c Tue Oct 11 02:02:43 2016 +0000 @@ -0,0 +1,399 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : ++----------------------------------------------------------------------------- +| Copyright 2004 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 : Implementation of the GDD interface with DIOv4 ++----------------------------------------------------------------------------- +*/ + +#define GDD_DIO_IF_C + +/*==== INCLUDES =============================================================*/ + +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include "typedefs.h" +#include "pcm.h" +#include "vsi.h" +#include "custom.h" +#include "gsm.h" +#include "pei.h" + +#include "gdd.h" +#include "gdd_dio_data.h" +#include "gdd_dio.h" + +#include "gdd_dio_con_mgr.h" +#include "gdd_dio_queue.h" + +#include "gdd_dio_dtxf.h" +#include "gdd_dio_drxf.h" + + +/*==== CONSTANTS ============================================================*/ + +/*==== TYPES ================================================================*/ + +/*==== PROTOTYPES ===========================================================*/ + +/*==== GLOBAL VARS ==========================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +/*==== LOCAL FUNCTIONS=======================================================*/ + +/*==== EXPORTED FUNCTIONS====================================================*/ + +/** gdd_init_dio - see header "gdd.h" for comment and description */ + +GDD_RESULT gdd_init_dio +( + T_GDD_INST_ID inst, + void * mem, + U16 num_con + ) +{ + T_GDD_DIO_DATA * gdd_dio_data; + + TRACE_FUNCTION("[GDD] gdd_init_dio()"); + + /* Check params */ + if(inst < GDD_INST_BAT || inst >= GDD_NUM_INSTS) + { + TRACE_ERROR("[GDD] Instance id out of bounds"); + return GDD_INVALID_PARAMS; + } + + gdd_dio_data = &gdd_dio_data_base[inst]; + + if(gdd_dio_init_flag[inst]) + { + TRACE_ERROR("[GDD] Attempted to call gdd_init_dio() twice for same instance"); + return GDD_ALREADY_INITIALIZED; + } + + if(num_con < 1 || num_con > gdd_dio_data->max_con) + { + TRACE_ERROR("[GDD] Number of connections out of bounds"); + return GDD_INVALID_PARAMS; + } + + if(mem) + { + gdd_dio_data->con_arr = mem; + gdd_dio_data->con_arr_mem_allocated = FALSE; + } + else + { + gdd_dio_data->con_arr = 0; + MALLOC(gdd_dio_data->con_arr, GDD_DIO_SIZEOF_CONDATA * num_con); + if(gdd_dio_data->con_arr EQ 0) + { + TRACE_ERROR("[GDD] memory allocation failed"); + return GDD_NO_MEMORY; + } + + gdd_dio_data->con_arr_mem_allocated = TRUE; + } + + gdd_dio_data->max_con = num_con; + + /* Initialize the connection manager */ + gdd_dio_con_mgr_init(gdd_dio_data); + + gdd_dio_init_flag[inst] = TRUE; + + return GDD_OK; +} + + +/** gdd_deinit - see header "gdd.h" for comment and description*/ +GDD_RESULT gdd_deinit_dio +( + T_GDD_INST_ID inst + ) +{ + T_GDD_DIO_DATA * gdd_dio_data = 0; + + TRACE_FUNCTION("[GDD] gdd_deinit_dio()"); + + if(inst < GDD_INST_BAT || inst >= GDD_NUM_INSTS) + { + TRACE_ERROR("[GDD] instance id out of bounds"); + return GDD_INVALID_PARAMS; + } + + gdd_dio_data = &gdd_dio_data_base[inst]; + + + /* If we allocated our own memory, free it. */ + if(gdd_dio_data->con_arr_mem_allocated EQ FALSE) + { + MFREE(gdd_dio_data->con_arr); + gdd_dio_data->con_arr = 0; + gdd_dio_data->con_arr_mem_allocated = FALSE; + } + + gdd_dio_init_flag[inst] = FALSE; + + return GDD_OK; +} + + +/** gdd_connect - see header "gdd.h" for comment and description */ +GDD_RESULT gdd_connect_dio +( + T_GDD_INST_ID inst, + T_GDD_CON_HANDLE * con_handle, + const T_GDD_CAP * cap, + T_GDD_RECEIVE_DATA_CB rcv_cb, + T_GDD_SIGNAL_CB sig_cb + ) +{ + T_GDD_DIO_DATA * gdd_dio_data; + + TRACE_FUNCTION("[GDD] gdd_connect_dio()"); + + /** + * Do the necessary checks. + */ + + if(inst < GDD_INST_BAT || inst >= GDD_NUM_INSTS) + { + TRACE_ERROR("[GDD] instance id out of bounds"); + return GDD_INVALID_PARAMS; + } + + gdd_dio_data = &gdd_dio_data_base[inst]; + + if (gdd_dio_data->ker.state NEQ GDD_DIO_KER_READY) + { + TRACE_ERROR("[GDD] DIO driver not initialized"); + return DRV_INTERNAL_ERROR; + } + + /* Check if we are already initialized. If we not, we do it ourselfs! */ + /* This is specific to the DIO implementation of GDD */ + if(gdd_dio_init_flag[inst] EQ FALSE) + { + gdd_init_dio(inst, 0, gdd_dio_data->max_con); + } + + if(con_handle EQ 0) + { + TRACE_ERROR("[GDD] Connection handle pointer cannot be 0"); + return GDD_INVALID_PARAMS; + } + + if(cap EQ 0) + { + TRACE_ERROR("[GDD] Capabilities pointer cannot be 0"); + return GDD_INVALID_PARAMS; + } + + if(rcv_cb EQ 0 || sig_cb EQ 0) + { + TRACE_ERROR("[GDD] Callback function pointer cannot be 0"); + return GDD_INVALID_PARAMS; + } + + /** + * We are ready to create the DIO connection + */ + return gdd_dio_con_mgr_new(gdd_dio_data, con_handle, cap, rcv_cb, sig_cb); +} + +/** gdd_disconnect - see header "gdd.h" for comment and description */ +GDD_RESULT gdd_disconnect_dio +( + T_GDD_CON_HANDLE con_handle + ) +{ + if(con_handle EQ 0) + { + TRACE_ERROR("[GDD] Connection handle cannot be 0"); + return GDD_INVALID_PARAMS; + } + + /* + * Inform the connection manager + */ + return gdd_dio_con_mgr_close(con_handle); +} + + +/** gdd_get_send_buffer - see header "gdd.h" for comment and description */ +GDD_RESULT gdd_get_send_buffer_dio +( + T_GDD_CON_HANDLE con_handle, + T_GDD_BUF ** buf, + U16 data_size + ) +{ + TRACE_USER_CLASS(TC_FUNC_DATA_FLOW, "[GDD] gdd_get_send_buffer_dio()"); + + if(con_handle EQ 0) + { + TRACE_ERROR("[GDD] Connection handle cannot be 0"); + return GDD_INVALID_PARAMS; + } + if(buf EQ NULL) + { + TRACE_ERROR("[GDD] buf cannot be NULL"); + return GDD_INVALID_PARAMS; + } + + return gdd_dio_dtx_get_send_buffer(con_handle, buf, data_size); +} + + +/** gdd_send_data - see header "gdd.h" for comment and description */ +GDD_RESULT gdd_send_data_dio +( + T_GDD_CON_HANDLE con_handle, + T_GDD_BUF * buf + ) +{ + TRACE_USER_CLASS(TC_FUNC_DATA_FLOW, "[GDD] gdd_send_data_dio()"); + + if(con_handle EQ 0) + { + TRACE_ERROR("[GDD] Connection handle cannot be 0"); + return GDD_INVALID_PARAMS; + } + if(buf EQ NULL) + { + TRACE_ERROR("[GDD] buf cannot be NULL"); + return GDD_INVALID_PARAMS; + } + + return gdd_dio_dtx_send_buffer(con_handle, buf); +} + + +/** gdd_signal_ready_rcv - see header "gdd.h" for comment and description */ +void gdd_signal_ready_rcv_dio( T_GDD_CON_HANDLE con_handle ) +{ + TRACE_FUNCTION("[GDD] gdd_signal_ready_rcv_dio()"); + + if(con_handle NEQ 0) + { + return; + } + + gdd_dio_drx_ready_to_rcv(con_handle); +} + + +/** Exported function table for DIO implementation of GDD */ +T_GDD_FUNC gdd_func_dio = +{ + gdd_init_dio, + gdd_deinit_dio, + gdd_connect_dio, + gdd_disconnect_dio, + gdd_get_send_buffer_dio, + gdd_send_data_dio, + gdd_signal_ready_rcv_dio +}; + + +/*==== EXPORTED HELPER FUNCTIONS=============================================*/ + +S32 gdd_write_buf_with_pid(const U8 * src_buf, + U16 src_size, + T_GDD_BUF * dest_buf, + U8 protocol_id) +{ + int idx_seg; + int remaining; + + /* Check that we have more than one segment and that the first one + is the PID segment which. */ + TRACE_ASSERT(dest_buf->c_segment > 1); + TRACE_ASSERT(dest_buf->ptr_gdd_segment[0].c_data EQ GDD_DIO_PID_SEG_SIZE); + + if( dest_buf->c_segment < 2 || + dest_buf->ptr_gdd_segment[0].c_data NEQ GDD_DIO_PID_SEG_SIZE ) + { + return -1; + } + + /* Set the protocol ID, which is carried in the first buffer segment */ + /* Note: the DTI2 interface in the stack uses only 8 bits for the p_id. */ + dest_buf->ptr_gdd_segment[0].ptr_data[0] = 0x0;/* not used, see note above */ + dest_buf->ptr_gdd_segment[0].ptr_data[1] = protocol_id; + + + remaining = src_size; + + for(idx_seg=1; idx_seg<dest_buf->c_segment; ++idx_seg) + { + T_GDD_SEGMENT * seg = &(dest_buf->ptr_gdd_segment[idx_seg]); + int bytes_to_copy = remaining < seg->c_data ? remaining : seg->c_data; + + memcpy(seg->ptr_data, src_buf + src_size - remaining, bytes_to_copy); + remaining -= bytes_to_copy; + if(remaining EQ 0) + break; + } + + dest_buf->length = src_size - remaining + GDD_DIO_PID_SEG_SIZE; + return remaining; +} + +#define DTI_PID_IP (0x21) /* simple ip packet (IPv4) */ + +S32 gdd_write_buf(const U8 * src_buf, U16 src_size, T_GDD_BUF * dest_buf) +{ + return gdd_write_buf_with_pid(src_buf, src_size, dest_buf, DTI_PID_IP); +} + +S32 gdd_read_buf(const T_GDD_BUF * src_buf, U8 * dest_buf, U16 dest_size) +{ + int idx_seg; + int remaining; + + /* Check that we have more than one segment and that the first one + is the PID segment which. */ + + TRACE_ASSERT(src_buf->c_segment > 1); + TRACE_ASSERT(src_buf->ptr_gdd_segment[0].c_data EQ GDD_DIO_PID_SEG_SIZE); + if( src_buf->c_segment < 2 || + src_buf->ptr_gdd_segment[0].c_data NEQ GDD_DIO_PID_SEG_SIZE ) + { + return -1; + } + + remaining = src_buf->length - GDD_DIO_PID_SEG_SIZE; + if(remaining > dest_size) + { + remaining = dest_size; + } + + for(idx_seg=1; idx_seg<src_buf->c_segment; ++idx_seg) + { + T_GDD_SEGMENT * seg = &(src_buf->ptr_gdd_segment[idx_seg]); + int bytes_to_copy = remaining < seg->c_data ? remaining : seg->c_data; + + memcpy(dest_buf + dest_size - remaining, seg->ptr_data, bytes_to_copy); + remaining -= bytes_to_copy; + if(remaining EQ 0) + break; + } + + return remaining; +}