diff gsm-fw/g23m-aci/gdd_dio/gdd_dio_con_mgr.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/gdd_dio/gdd_dio_con_mgr.c	Sun Oct 12 01:45:14 2014 +0000
@@ -0,0 +1,378 @@
+/*
++-----------------------------------------------------------------------------
+|  File     : gdd_dio_con_mgr.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  : Implements connection management functions
++-----------------------------------------------------------------------------
+*/
+
+
+#define ENTITY_GDD_DIO
+
+/*==== INCLUDES =============================================================*/
+
+#include "typedefs.h"   /* to get Condat data types */
+#include "vsi.h"        /* to get a lot of macros */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#include "dti.h"
+
+#include "gdd_dio.h"       /* to get the global entity definitions */
+#include "gdd_dio_queue.h"
+#include "gdd_dio_con_mgr.h"
+
+#include <string.h>
+
+
+/*==== DEFINITIONS ==========================================================*/
+
+#define	ENTER_CRITICAL_SECTION(sem) if (gdd_enter_critical_section(sem))return -1;
+#define	LEAVE_CRITICAL_SECTION(sem) if (gdd_leave_critical_section(sem))return -1;
+
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+static T_HANDLE   sem_GDD_DIO_CON;
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+LOCAL int get_free_connection_slot(T_GDD_DIO_DATA * gdd_dio_data,
+                                    T_GDD_DIO_CON_DATA ** con_data /*output*/);
+static void gdd_semaphore_err (void);
+static int gdd_enter_critical_section (T_HANDLE sem);
+static int gdd_leave_critical_section (T_HANDLE sem);
+
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+/*  Initializes the connection manager */
+
+GLOBAL void gdd_dio_con_mgr_init (T_GDD_DIO_DATA * gdd_dio_data)
+{
+  int i;
+  T_GDD_DIO_CON_DATA * con_data = gdd_dio_data->con_arr;
+  
+  TRACE_FUNCTION( "[GDD] conn_init()" );
+
+  for(i = 0; i < gdd_dio_data->max_con; ++i, ++con_data)
+  {
+    con_data->con_state = GDD_DIO_CON_DEAD;
+  }
+
+  sem_GDD_DIO_CON  = vsi_s_open (VSI_CALLER "SEM_GDD_CON",1);
+  if (sem_GDD_DIO_CON EQ VSI_ERROR)
+    vsi_o_ttrace(VSI_CALLER TC_EVENT, "canīt open semaphore \"SEM_GDD_CON\"");
+}
+
+
+/* Setup a new DIO connection */
+
+GLOBAL GDD_RESULT gdd_dio_con_mgr_new
+( T_GDD_DIO_DATA * gdd_dio_data,
+  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_CON_DATA * con_data = 0;
+
+  TRACE_FUNCTION("[GDD] conn_new()");
+
+  if(get_free_connection_slot(gdd_dio_data, &con_data) NEQ 0)
+  {
+    TRACE_ERROR("Failed to get new connection slot");
+    return GDD_NO_CONNECTION_SLOT;
+  }
+
+  gdd_dio_queue_clear(&con_data->rx_queue);
+  gdd_dio_queue_clear(&con_data->tx_queue);
+
+  con_data->wait_send_buf = FALSE;
+
+  con_data->rcv_cb = rcv_cb;
+  con_data->sig_cb = sig_cb;
+
+  con_data->dio_cap.device_type = DIO_TYPE_PKT;
+  con_data->dio_cap.device_flags = 0;
+  con_data->dio_cap.mtu_control = 0;
+  con_data->dio_cap.mtu_data = (U16)((T_GDD_DIO_CAP *)cap)->mtu_size;
+  con_data->dio_cap.driver_name = "GDD";
+  
+  (*con_handle) = con_data->dio_device;
+
+
+  gdd_dio_send_signal_to_dio(con_data, DRV_SIGTYPE_CONNECT);
+
+  return GDD_OK;
+}
+
+
+/* Close a connection */
+
+GLOBAL GDD_RESULT gdd_dio_con_mgr_close
+( T_GDD_CON_HANDLE con_handle )
+{
+  T_GDD_INST_ID inst = (T_GDD_INST_ID)inst_num_from_dev_id(con_handle);
+  T_GDD_DIO_CON_DATA * con_data;
+
+  TRACE_FUNCTION( "[GDD] gdd_dio_con_mgr_close()" );
+
+  con_data = get_con_data(&(gdd_dio_data_base[inst]), con_handle);  
+  if(con_data EQ NULL)
+  {
+    TRACE_ERROR("Failed to get connection data");
+    return GDD_INTERNAL_ERROR;
+  }
+
+  con_data->con_state = GDD_DIO_CON_CLOSE;
+
+  gdd_dio_send_signal_to_dio(con_data, DRV_SIGTYPE_DISCONNECT);
+
+  return GDD_OK;
+}
+
+
+/* Mark a connection as dead */
+
+GDD_RESULT gdd_dio_con_mgr_mark_dead( T_GDD_CON_HANDLE con_handle )
+{
+  T_GDD_INST_ID inst = (T_GDD_INST_ID)inst_num_from_dev_id(con_handle);
+  T_GDD_DIO_CON_DATA * con_data;
+
+  TRACE_FUNCTION( "[GDD] gdd_dio_con_mgr_mark_dead()" );
+
+  con_data = get_con_data(&(gdd_dio_data_base[inst]), con_handle);  
+  if(con_data EQ NULL)
+  {
+    TRACE_ERROR("Failed to get connection data");
+    return GDD_INTERNAL_ERROR;
+  }
+
+  /* Clear the connection slot
+     - it's sufficient to set state and nullify handle */
+  con_data->con_state = GDD_DIO_CON_DEAD;
+
+  return GDD_OK;
+}
+
+
+/* Check if any of the connections is (still) open or in connecting state. */
+
+BOOL gdd_dio_con_mgr_has_open_connection
+( const T_GDD_DIO_DATA * gdd_dio_data )
+{
+  int i;
+  T_GDD_DIO_CON_DATA * con_data = gdd_dio_data->con_arr;
+  
+  TRACE_FUNCTION( "[GDD] gdd_dio_con_mgr_has_open_connection()" );
+
+  for(i = 0; i < gdd_dio_data->max_con; ++i, ++con_data)
+  {
+    if(con_data->con_state EQ GDD_DIO_CON_READY ||
+       con_data->con_state EQ GDD_DIO_CON_SENDING ||
+       con_data->con_state EQ GDD_DIO_CON_CONNECT)
+    {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
+/* Get the connection data for a given instance & handle */
+
+GLOBAL T_GDD_DIO_CON_DATA * get_con_data(const T_GDD_DIO_DATA * gdd_dio_data, 
+                                         T_GDD_CON_HANDLE con_handle)
+{
+  int i;
+
+  /* Deliberately NO tracing */
+
+  for(i=0; i<gdd_dio_data->max_con; ++i)
+  {
+    if(gdd_dio_data->con_arr[i].dio_device EQ con_handle)
+      return &gdd_dio_data->con_arr[i];
+  }
+  return NULL;
+}
+
+
+
+/* Get the connection data for a given handle only */
+
+GLOBAL T_GDD_DIO_CON_DATA * get_con_data_from_handle(T_GDD_CON_HANDLE con_handle)
+{
+  T_GDD_INST_ID inst;
+
+  /* Deliberately NO tracing */
+
+  inst = (T_GDD_INST_ID)inst_num_from_dev_id(con_handle);
+
+  if(inst < 0 || inst >= GDD_NUM_INSTS)
+  {
+    return 0;
+  }
+
+  return get_con_data(&(gdd_dio_data_base[inst]), con_handle);
+}
+
+
+/* Send a DIO signal via the specificed connection */
+
+void gdd_dio_send_signal_to_dio
+(T_GDD_DIO_CON_DATA * con_data, U16 sig_type)
+{
+  T_DRV_SIGNAL      drv_signal;
+  T_GDD_DIO_DATA * inst_data;
+  char * sig_type_str;
+
+  TRACE_USER_CLASS(TC_FUNC_DATA_FLOW, "[GDD] gdd_dio_send_signal_to_dio()");
+
+  inst_data = &gdd_dio_data_base[inst_num_from_dev_id(con_data->dio_device)];
+
+  switch (sig_type)
+  {
+  case DRV_SIGTYPE_WRITE:      sig_type_str = "DRV_SIGTYPE_WRITE"; break;
+  case DRV_SIGTYPE_READ:       sig_type_str = "DRV_SIGTYPE_READ"; break;
+  case DRV_SIGTYPE_CONNECT:    sig_type_str = "DRV_SIGTYPE_CONNECT"; break;
+  case DRV_SIGTYPE_DISCONNECT: sig_type_str = "DRV_SIGTYPE_DISCONNECT"; break;
+  default: sig_type_str = "ununsed signal type"; break;
+  }  
+
+  TRACE_USER_CLASS_P2(TC_SIGNALS, "[GDD] Sending signal %s to DIO IL (con_handle=0x%4x)", sig_type_str, con_data->dio_device);
+
+  drv_signal.SignalType = sig_type;
+  drv_signal.DrvHandle  = inst_data->drv_handle;
+  drv_signal.DataLength = sizeof(U32);
+  drv_signal.UserData   = &(con_data->dio_device);
+  (*(inst_data->signal_callback))(&drv_signal);
+}
+
+
+/*==== PRIVATE FUNCTIONS =====================================================*/
+
+/*
++------------------------------------------------------------------------------
+| Function    : get_free_connection_slot
++------------------------------------------------------------------------------
+| Description : Find the next free connection slot for given instance.
+|
+| Parameters  : gdd_dio_data  - pointer to instance data
+|               con_data      - pointer to pointer to connection data (output)
+|
+| Returns     : 0      - Success (con_data has been set)
+|              -1      - Failed (no slot found)
++------------------------------------------------------------------------------
+*/
+LOCAL int get_free_connection_slot(T_GDD_DIO_DATA * gdd_dio_data,
+                                    T_GDD_DIO_CON_DATA ** con_data /*output*/)
+{
+  int i;
+    
+  TRACE_FUNCTION( "[GDD] get_free_connection_slot()" );
+
+  ENTER_CRITICAL_SECTION(sem_GDD_DIO_CON);
+
+  for(i = 0; i < gdd_dio_data->max_con; ++i)
+  {
+    if(gdd_dio_data->device_range_start+i <= gdd_dio_data->device_range_end)
+    {
+      if(gdd_dio_data->con_arr[i].con_state EQ GDD_DIO_CON_DEAD)
+      {
+        gdd_dio_data->con_arr[i].dio_device = gdd_dio_data->device_range_start+i;
+        *con_data = &(gdd_dio_data->con_arr[i]);
+        (*con_data)->con_state = GDD_DIO_CON_CONNECT;
+
+        LEAVE_CRITICAL_SECTION(sem_GDD_DIO_CON);        
+        return 0;
+      }
+    }
+  }
+
+  LEAVE_CRITICAL_SECTION(sem_GDD_DIO_CON);
+
+  return -1;
+}
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : gdd_semaphore_err
++------------------------------------------------------------------------------
+| Description : Handle a semaphore error
++------------------------------------------------------------------------------
+*/
+static void gdd_semaphore_err (void)
+{
+  static UCHAR out = 0;
+  if (!out)
+  {
+    out = 1;
+    vsi_o_ttrace(VSI_CALLER TC_EVENT, "semaphore error");
+  }
+}
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : gdd_enter_critical_section
++------------------------------------------------------------------------------
+| Description : Enters a critical section.
+|
+| Parameters  : sem    - Semaphore handle
+|
+| Returns     : 0      - Success
+|              -1      - Failure
++------------------------------------------------------------------------------
+*/
+static int gdd_enter_critical_section (T_HANDLE sem)
+{
+  if (vsi_s_get (VSI_CALLER sem) NEQ VSI_OK)
+  {
+    gdd_semaphore_err();
+    return -1;
+  }
+  else
+  {
+    return 0;
+  }
+}
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : gdd_leave_critical_section
++------------------------------------------------------------------------------
+| Description : Leaves a critical section.
+|
+| Parameters  : sem    - Semaphore handle
+|
+| Returns     : 0      - Success
+|              -1      - Failure
++------------------------------------------------------------------------------
+*/
+static int gdd_leave_critical_section (T_HANDLE sem)
+{
+  if (vsi_s_release (VSI_CALLER sem) NEQ VSI_OK)
+  {
+    gdd_semaphore_err();
+    return -1;
+  }
+  else
+  {
+    return 0;
+  }
+}