FreeCalypso > hg > fc-magnetite
view src/aci2/aci_dti_mng/dti_conn_mng.c @ 638:cab2f315827e
FFS dev.c: added Spansion PL032J to the "generic" table
With the discovery of first GTM900 and then Tango, it now appears that
Openmoko was not the only manuf after all who kept TI's TCS211 firmware
largely intact (as opposed to changing it beyond all recognition like
Compal, Chi-Mei and BenQ did), thus we are now getting new "alien" targets
on which we reuse the original manuf's FFS with IMEI and RF calibration
tables as if it were native. On these targets we use the original
device table for FFS, even though we previously thought that it would
never apply to any target other than dsample, leonardo and gtamodem.
We have previously added Samsung K5L33xxCAM (a new kind of multi-ID device)
to the generic table to support its use in Huawei GTM900-B modules; now
we got news that some slightly older GTM900-B specimen used S71PL032J
instead, so we are now adding PL032J as well.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 30 Jan 2020 17:45:48 +0000 |
parents | 93999a60b835 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : ... | Modul : dti_conn_mng.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 : Implementation of DTI Connection Manager +----------------------------------------------------------------------------- */ #ifndef DTI_CONN_MNG_C #define DTI_CONN_MNG_C #endif /*===== INCLUDES ===================================================*/ #include "aci_all.h" #include "pconst.cdg" #include "mconst.cdg" #include "cnf_aci.h" #include "mon_aci.h" #include "pei.h" #include "aci_cmh.h" #include "ati_cmd.h" #include "aci_io.h" #include "aci_cmh.h" #include "aci_lst.h" #include "aci_mem.h" #include "dti.h" #include "dti_conn_mng.h" #include "dti_cntrl_mng.h" LOCAL ULONG used_dti_channels = 0; LOCAL T_ACI_LIST *dti_channel_list = NULL; /* list_begin */ LOCAL T_DTI_CONN_PARAMS glob_params; /********************** LOCAL FUNCTIONS *****************************/ LOCAL UBYTE dti_conn_get_new_dti_id (void) { ULONG tst_id; UBYTE i; TRACE_FUNCTION("dti_conn_get_new_dti_id()"); /* create a new DTI ID */ for (i = 0; i <= MAX_DTI_CONN_CHANNELS; i++) { tst_id = (0x01 << i) & used_dti_channels; if (!tst_id) { break; } } if (tst_id) { TRACE_EVENT("No DTI ID available"); return (DTI_DTI_ID_NOTPRESENT); } used_dti_channels |= (0x01 << i); TRACE_EVENT_P1("DTI ID %d created", i); return (i); } LOCAL void dti_conn_remove_dti_id (UBYTE dti_id) { ULONG tst_id; TRACE_FUNCTION("dti_conn_remove_id()"); if (dti_id >= MAX_DTI_CONN_CHANNELS) return; tst_id = 0x01 << (dti_id); used_dti_channels &= ~tst_id; TRACE_EVENT_P1("DTI ID %d removed", dti_id); } LOCAL BOOL dti_conn_error_cb(UBYTE dti_id, T_DTI_CONN_STATE result_type) { /* theorically should not be called... Yet helpfull for testing */ TRACE_FUNCTION("dti_conn_error_cb()"); TRACE_EVENT("ERROR: DTI connection callback has not been initialized !"); return FALSE; } LOCAL void dti_conn_reset_conn_parms( T_DTI_CONN_CHANNEL *dti_channel ) { UBYTE i,j; TRACE_FUNCTION("dti_conn_reset_conn_parms()"); dti_channel->erase_channel = FALSE; dti_channel->num_of_conns = 0; dti_channel->conn_cb = dti_conn_error_cb; dti_channel->state = DTI_CONN_STATE_DISCONNECTED; for (i=0; i<MAX_DTI_CONN_TUPLES; i++) { dti_channel->tuple_list[i].state = DTI_CONN_STATE_DISCONNECTED; for (j=0; j<NUM_OF_PEERS; j++) { dti_channel->tuple_list[i].peers[j].state = DTI_CONN_STATE_DISCONNECTED; dti_channel->tuple_list[i].peers[j].ent_id = DTI_ENTITY_INVALID; } } } LOCAL BOOL DTItest_dti_id( UBYTE dti_id, void *elem) { T_DTI_CONN_CHANNEL *dti_channel = (T_DTI_CONN_CHANNEL *)elem; if (dti_channel EQ NULL) return FALSE; if (dti_channel -> dti_id EQ dti_id ) return TRUE; else return FALSE; } LOCAL T_DTI_CONN_TUPLE *dti_conn_find_dti_tuple( T_DTI_CONN_CHANNEL *dti_channel, UBYTE tuple_no) { return &(dti_channel->tuple_list[tuple_no]); } LOCAL T_DTI_CONN_CHANNEL *dti_conn_find_dti_conn( UBYTE dti_id ) { T_DTI_CONN_CHANNEL *dti_channel; TRACE_FUNCTION("dti_conn_find_dti_conn()"); /*find channel in list */ dti_channel = find_element (dti_channel_list, dti_id, DTItest_dti_id); return dti_channel; } LOCAL BOOL dti_conn_connect( T_DTI_CONN_CHANNEL* dti_channel, T_DTI_ENTITY_ID* entity_list, UBYTE num_entities, T_DTI_CONN_MODE mode ) { ULONG link_id; UBYTE tuple_no; UBYTE i; TRACE_FUNCTION("dti_conn_connect()"); dti_channel->state = DTI_CONN_STATE_CONNECTING; if (dti_channel->conn_cb) { dti_channel->conn_cb(dti_channel->dti_id, DTI_CONN_STATE_CONNECTING); } else { TRACE_EVENT("conn_cb is NULL"); } if (mode EQ APPEND) { tuple_no = dti_channel->num_of_conns; } else /* SPLIT */ { tuple_no = 0; dti_channel->num_of_conns = 0; } for (i=0; i<num_entities-1; i++) { dti_channel->tuple_list[tuple_no].peers[0].ent_id = entity_list[i]; dti_channel->tuple_list[tuple_no].peers[1].ent_id = entity_list[i+1]; if ( (dti_channel->tuple_list[tuple_no].state NEQ DTI_CONN_STATE_DISCONNECTING) AND (dti_channel->tuple_list[tuple_no].state NEQ DTI_CONN_STATE_CONNECTING) ) { dti_channel->tuple_list[tuple_no].state = DTI_CONN_STATE_CONNECTING; dti_channel->tuple_list[tuple_no].tuple_no = tuple_no; dti_channel->state = DTI_CONN_STATE_CONNECTING; link_id = dti_conn_compose_link_id(0, 0, dti_channel->dti_id, tuple_no); dti_channel->tuple_list[tuple_no].peers[0].state = DTI_CONN_STATE_CONNECTING; dti_channel->tuple_list[tuple_no].peers[1].state = DTI_CONN_STATE_CONNECTING; /* connect a tuple */ glob_params.mng_ent_cb(link_id, entity_list[i], entity_list[i+1], DTI_CONNECT); glob_params.mng_ent_cb(link_id, entity_list[i+1], entity_list[i], DTI_CONNECT); } tuple_no++; } dti_channel->num_of_conns = tuple_no; return TRUE; } LOCAL BOOL dti_conn_disconnect( T_DTI_CONN_CHANNEL* dti_channel ) { ULONG link_id; UBYTE i; TRACE_FUNCTION("dti_conn_disconnect()"); dti_channel->state = DTI_CONN_STATE_DISCONNECTING; if (dti_channel->conn_cb) { dti_channel->conn_cb(dti_channel->dti_id, DTI_CONN_STATE_DISCONNECTING); } else { TRACE_EVENT("conn_cb is NULL"); } for (i=0; i < dti_channel->num_of_conns; i++) { /* set tuple state only if it is not already DISCONNECTED */ if (dti_channel->tuple_list[i].state NEQ DTI_CONN_STATE_DISCONNECTED) { dti_channel->tuple_list[i].state = DTI_CONN_STATE_DISCONNECTING; } link_id = dti_conn_compose_link_id(0, 0, dti_channel->dti_id, i); /* disconnect only a connected entity */ if (dti_channel->tuple_list[i].peers[0].state EQ DTI_CONN_STATE_CONNECTED OR dti_channel->tuple_list[i].peers[0].state EQ DTI_CONN_STATE_CONNECTING ) { dti_channel->tuple_list[i].peers[0].state = DTI_CONN_STATE_DISCONNECTING; glob_params.mng_ent_cb(link_id, dti_channel->tuple_list[i].peers[0].ent_id, dti_channel->tuple_list[i].peers[1].ent_id, DTI_DISCONNECT); } /* disconnect only a connected entity */ if (dti_channel->tuple_list[i].peers[1].state EQ DTI_CONN_STATE_CONNECTED OR dti_channel->tuple_list[i].peers[1].state EQ DTI_CONN_STATE_CONNECTING ) { dti_channel->tuple_list[i].peers[1].state = DTI_CONN_STATE_DISCONNECTING; glob_params.mng_ent_cb(link_id, dti_channel->tuple_list[i].peers[1].ent_id, dti_channel->tuple_list[i].peers[0].ent_id, DTI_DISCONNECT); } } return TRUE; } /********************** GLOBAL FUNCTIONS *****************************/ GLOBAL T_DTI_CONN_LINK_ID dti_conn_compose_link_id(UBYTE dummy, UBYTE assoc, UBYTE dti_id, UBYTE tuple_no) { T_DTI_CONN_LINK_ID link_id = 0; link_id += dummy; link_id <<= 8; link_id += assoc; link_id <<= 8; link_id += dti_id; link_id <<= 8; link_id += tuple_no; return link_id; } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_init | +--------------------------------------------------------------------+ PURPOSE : initialise the DTI Connection Manager */ GLOBAL void dti_conn_init( T_DTI_CONN_MNG_ENT_CB* mng_ent_cb ) { TRACE_FUNCTION("dti_conn_init()"); dti_channel_list = new_list (); glob_params.conn_cb = NULL; glob_params.mng_ent_cb = mng_ent_cb; glob_params.num_entities = 0; } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_new | +--------------------------------------------------------------------+ PURPOSE : register new DTI channel */ GLOBAL UBYTE dti_conn_new(UBYTE dti_id ) { T_DTI_CONN_CHANNEL *dti_channel; TRACE_FUNCTION("dti_conn_new()"); if (dti_id EQ DTI_DTI_ID_NOTPRESENT) { dti_id = dti_conn_get_new_dti_id (); } if (dti_id EQ DTI_DTI_ID_NOTPRESENT) { return (DTI_DTI_ID_NOTPRESENT); } /* search for an existing entry with correspondant dti_id */ dti_channel = dti_conn_find_dti_conn (dti_id); if( dti_channel ) { return (DTI_DTI_ID_NOTPRESENT); /* couldn't create a new entry */ } ACI_MALLOC(dti_channel, sizeof(T_DTI_CONN_CHANNEL)); dti_conn_reset_conn_parms (dti_channel); dti_channel->dti_id = dti_id; insert_list(dti_channel_list, dti_channel); return (dti_channel->dti_id); } /* +---------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_erase_entry | +---------------------------------------------------------------------+ PURPOSE : /* erase entry from DTI channel list */ GLOBAL void dti_conn_erase_entry(UBYTE dti_id) { T_DTI_CONN_CHANNEL *dti_channel; TRACE_FUNCTION("dti_conn_erase_entry"); /* find element to be erased */ dti_channel = remove_element (dti_channel_list, dti_id, DTItest_dti_id); if( dti_channel NEQ NULL ) /* entry not erased yet */ ACI_MFREE (dti_channel); dti_conn_remove_dti_id(dti_id); } /* +-----------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_is_dti_channel_connected | +-----------------------------------------------------------------------+ PURPOSE : returns TRUE if end-to-end DTI connection is connected and the given entity is in this connection */ GLOBAL BOOL dti_conn_is_dti_channel_connected( T_DTI_ENTITY_ID ent_id, UBYTE dti_id ) { UBYTE count = 0; UBYTE i; UBYTE entity_found = FALSE; T_DTI_CONN_CHANNEL *dti_channel = dti_conn_find_dti_conn( dti_id ); TRACE_FUNCTION("dti_conn_is_dti_channel_connected()"); if (dti_channel EQ NULL) { TRACE_EVENT_P1("dti_channel for dti_id %d not found", dti_id); return FALSE; } for (i=0; i<dti_channel->num_of_conns; i++) { if ((dti_channel->tuple_list[i].peers[0].ent_id EQ ent_id) OR (dti_channel->tuple_list[i].peers[1].ent_id EQ ent_id)) { entity_found = TRUE; break; } } if (entity_found EQ FALSE) return FALSE; if (dti_channel->state EQ DTI_CONN_STATE_CONNECTED) { return TRUE; } else { for (i=0; i<dti_channel->num_of_conns; i++) { if (dti_channel->tuple_list[i].state EQ DTI_CONN_STATE_CONNECTED) { count++; } } if (count EQ dti_channel->num_of_conns) { return TRUE; } } return FALSE; } /* +--------------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_is_dti_channel_disconnected | +--------------------------------------------------------------------------+ PURPOSE : returns TRUE if end-to-end DTI connection is disconnected */ GLOBAL BOOL dti_conn_is_dti_channel_disconnected( UBYTE dti_id ) { UBYTE count = 0; UBYTE i; T_DTI_CONN_CHANNEL *dti_channel = dti_conn_find_dti_conn( dti_id ); TRACE_FUNCTION("dti_conn_is_dti_channel_disconnected()"); if (dti_channel EQ NULL) { return TRUE; } if (dti_channel->state EQ DTI_CONN_STATE_DISCONNECTED) { return TRUE; } else { for (i=0; i<dti_channel->num_of_conns; i++) { if (dti_channel->tuple_list[i].state EQ DTI_CONN_STATE_DISCONNECTED) { count++; } } if (count EQ dti_channel->num_of_conns) { return TRUE; } } return FALSE; } /* +---------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_est_dpath | +---------------------------------------------------------------------+ PURPOSE : establishes data path. */ GLOBAL BOOL dti_conn_est_dpath( UBYTE dti_id, T_DTI_ENTITY_ID* entity_list, UBYTE num_entities, T_DTI_CONN_MODE mode, T_DTI_CONN_CB* cb) { T_DTI_CONN_CHANNEL *dti_channel; TRACE_FUNCTION("dti_conn_est_dpath()"); /*find channel in list */ dti_channel = dti_conn_find_dti_conn (dti_id); if (dti_channel EQ NULL) { TRACE_EVENT_P1("[ERR] dti_conn_est_dpath: dti_channel dti_id=%x not found", dti_id); /* DTI ID not found */ return FALSE; } if ( entity_list[0] EQ DTI_ENTITY_INVALID OR entity_list[1] EQ DTI_ENTITY_INVALID) { /* improper entity list */ TRACE_EVENT("[ERR] improper entity list "); return FALSE; } /* if 'SPLIT' then the whole DTI channel must be disconnected before a * new connection is established */ if ((mode EQ SPLIT) AND (dti_channel->state NEQ DTI_CONN_STATE_DISCONNECTED)) { dti_conn_disconnect (dti_channel); /* save new entity list to entity list buffer */ memcpy(glob_params.entity_list_buf, entity_list, sizeof(T_DTI_ENTITY_ID)*num_entities); glob_params.num_entities = num_entities; glob_params.conn_cb = cb; } else { dti_channel->conn_cb = cb; dti_conn_connect (dti_channel, entity_list, num_entities, mode); } return TRUE; } /* +---------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_close_dpath | +---------------------------------------------------------------------+ PURPOSE : closes a DTI connection */ GLOBAL BOOL dti_conn_close_dpath( UBYTE dti_id ) { T_DTI_CONN_CHANNEL *dti_channel; UBYTE i=0; TRACE_FUNCTION("dti_conn_close_dpath()"); dti_channel = dti_conn_find_dti_conn( dti_id ); if (dti_channel EQ NULL) { TRACE_EVENT_P1("[ERR] dti_conn_close_dpath: dti_channel dti_id=%x not found", dti_id); return FALSE; } if (dti_channel->state NEQ DTI_CONN_STATE_DISCONNECTED) { dti_channel->state = DTI_CONN_STATE_DISCONNECTING; dti_conn_disconnect (dti_channel); } else { TRACE_EVENT("[ERR] dti_conn_close_dpath: try to close dpath which was DISCONNECTED"); return FALSE; } return TRUE; } /* +-----------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_entity_connected | +-----------------------------------------------------------------------+ PURPOSE : response after a DTI connect request. This function is called to inform the DTI Connection Manager that a connection is established. */ GLOBAL void dti_conn_entity_connected( T_DTI_CONN_LINK_ID link_id, T_DTI_ENTITY_ID ent_id, T_DTI_CONN_RESULT result ) { T_DTI_CONN_CHANNEL *dti_channel; T_DTI_CONN_TUPLE *tuple; UBYTE i; UBYTE dti_id = EXTRACT_DTI_ID(link_id); BOOL both_entities_connected = FALSE; UBYTE count = 0; TRACE_FUNCTION("dti_conn_entity_connected()"); dti_channel = dti_conn_find_dti_conn( dti_id ); if (dti_channel EQ NULL) { TRACE_EVENT_P1("[ERR] dti_conn_entity_connected: dti_channel link_id=%x not found", link_id); return; } if (result EQ DTI_ERROR) { /* mark entity as disconnected */ dti_conn_entity_disconnected( link_id, ent_id ); /* close the whole DTI channel */ dti_conn_close_dpath( dti_id ); return; } if (dti_channel->state EQ DTI_CONN_STATE_CONNECTED) { TRACE_EVENT_P1("dti channel with dti_id=%x already connected", dti_id); return; } tuple = dti_conn_find_dti_tuple( dti_channel, EXTRACT_TUPLE_NO(link_id ) ); for (i=0; i<NUM_OF_PEERS; i++) { if (tuple->peers[i].state EQ DTI_CONN_STATE_CONNECTED) { count++; } if (tuple->peers[i].ent_id EQ ent_id) { if (tuple->peers[i].state EQ DTI_CONN_STATE_CONNECTING) { tuple->peers[i].state = DTI_CONN_STATE_CONNECTED; count++; } } if (count EQ NUM_OF_PEERS) { both_entities_connected = TRUE; } } /* if both entities are CONNECTED */ if (both_entities_connected) { tuple->state = DTI_CONN_STATE_CONNECTED; /* if all other tuples CONNECTED */ if (dti_conn_is_dti_channel_connected(ent_id, dti_id)) { dti_channel->state = DTI_CONN_STATE_CONNECTED; TRACE_EVENT_P1("DTI ID %d connected", dti_id); /* call connect_cb here */ if (dti_channel->conn_cb) { dti_channel->conn_cb(dti_id, DTI_CONN_STATE_CONNECTED); } else { TRACE_EVENT("conn_cb is NULL"); } } } } /* +-----------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_entity_disconnected | +-----------------------------------------------------------------------+ PURPOSE : response after a DTI connect request. This function is called to inform the DTI Connection Manager that a connection is closed. */ GLOBAL void dti_conn_entity_disconnected( T_DTI_CONN_LINK_ID link_id, T_DTI_ENTITY_ID ent_id ) { T_DTI_CONN_CHANNEL *dti_channel; T_DTI_CONN_TUPLE *tuple; UBYTE i; UBYTE dti_id = EXTRACT_DTI_ID(link_id); UBYTE count = 0; TRACE_FUNCTION("dti_conn_entity_disconnected()"); dti_channel = dti_conn_find_dti_conn( dti_id ); if (dti_channel EQ NULL) { TRACE_EVENT_P1("[ERR] dti_conn_entity_disconnected: dti_channel link_id=%x not found", link_id); return; } if (dti_channel->state EQ DTI_CONN_STATE_DISCONNECTED) { TRACE_EVENT_P1("dti channel with dti_id=%x already diconnected", dti_id); return; } tuple = dti_conn_find_dti_tuple( dti_channel, EXTRACT_TUPLE_NO(link_id) ); for (i=0; i<NUM_OF_PEERS; i++) { if (tuple->peers[i].state EQ DTI_CONN_STATE_DISCONNECTED) { count++; } /* find disconnected entity */ if (tuple->peers[i].ent_id EQ ent_id) { tuple->peers[i].state = DTI_CONN_STATE_DISCONNECTED; tuple->peers[i].ent_id = DTI_ENTITY_INVALID; count++; tuple->state = DTI_CONN_STATE_DISCONNECTING; if (dti_channel->state EQ DTI_CONN_STATE_CONNECTED) { /* set DTI channel state */ dti_channel->state = DTI_CONN_STATE_DISCONNECTING; } } } /* if both entities are DISCONNECTED */ if (count EQ NUM_OF_PEERS) { /* set tuple state */ tuple->state = DTI_CONN_STATE_DISCONNECTED; /* if all other tuples DISCONNECTED */ if (dti_conn_is_dti_channel_disconnected(dti_id)) { dti_channel->state = DTI_CONN_STATE_DISCONNECTED; TRACE_EVENT_P1("DTI ID %d disconnected", dti_id); /* reset number of conns */ dti_channel->num_of_conns = 0; /* call disconnect_cb here */ if (dti_channel->conn_cb) { dti_channel->conn_cb(dti_id, DTI_CONN_STATE_DISCONNECTED); } else { TRACE_EVENT("conn_cb is NULL"); } if (glob_params.num_entities NEQ 0) { dti_channel->conn_cb = glob_params.conn_cb; dti_conn_connect( dti_channel, glob_params.entity_list_buf, glob_params.num_entities, SPLIT ); glob_params.num_entities = 0; } else { if (dti_channel->erase_channel EQ TRUE) { /* erase entry in DTI Conn Mng */ dti_conn_erase_entry(dti_id); } } } } } /* +-----------------------------------------------------------------------+ | PROJECT : MODULE : DTI_CONN | | STATE : code ROUTINE : dti_conn_close_all_connections| +-----------------------------------------------------------------------+ PURPOSE : This function is called to close all established DTI connections. */ GLOBAL void dti_conn_close_all_connections() { T_DTI_CONN_CHANNEL *dti_channel; TRACE_FUNCTION("dti_conn_close_all_connections()"); while(TRUE) { dti_channel = get_next_element (dti_channel_list, dti_channel); if (dti_channel EQ NULL) { return; } if (dti_channel->state EQ DTI_CONN_STATE_CONNECTED) { dti_conn_close_dpath(dti_channel->dti_id); dti_channel->erase_channel = TRUE; } else { dti_conn_erase_entry(dti_channel->dti_id); } } }