FreeCalypso > hg > fc-magnetite
view src/g23m-gprs/sndcp/sndcp_sus.c @ 222:79cb194284ca
doc/Freerunner-Howto: update for the TCS2/TCS3 hybrid development
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 16 Oct 2016 00:26:26 +0000 |
parents | 219afcfc6250 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GPRS (8441) | Modul : sndcp_sus.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 : This modul is part of the entity SNDCP and implements all | functions to handles the incoming process internal signals as | described in the SDL-documentation (SU-statemachine) +----------------------------------------------------------------------------- */ /*---- HISTORY --------------------------------------------------------------*/ #define ENTITY_SNDCP /*==== INCLUDES =============================================================*/ #include "typedefs.h" /* to get Condat data types */ #include "vsi.h" /* to get a lot of macros */ #include "macdef.h" #include "gsm.h" /* to get a lot of macros */ #include "prim.h" /* to get the definitions of used SAP and directions */ #include <string.h> /* to get memcpy() */ #include "dti.h" #include "sndcp.h" /* to get the global entity definitions */ #include "sndcp_f.h" /* to get the functions to access the global arrays*/ #include "sndcp_suf.h" /* to get internal functions of service su */ #include "sndcp_cias.h" /* to get signal functions to service cia */ #include "sndcp_nus.h" /* to get signal functions to service nu */ #include "sndcp_sus.h" /*==== CONST ================================================================*/ /*==== LOCAL VARS ===========================================================*/ /*==== PRIVATE FUNCTIONS ====================================================*/ #ifdef _SNDCP_DTI_2_ /* +------------------------------------------------------------------------------ | Function : su_add_ll_unitdesc_req_params +------------------------------------------------------------------------------ | Description : sets the parameters of the given ll_unitdata_req | | Parameters : nsapi, ll_unitdata_req* | +------------------------------------------------------------------------------ */ LOCAL void su_add_ll_unitdesc_req_params (UBYTE nsapi, T_LL_UNITDESC_REQ* ll_unitdesc_req) { T_snsm_qos snsm_qos; /* Initialized with getter later */ TRACE_FUNCTION( "su_add_ll_unitdesc_req_params" ); /* * Set quality of service. */ sndcp_get_nsapi_qos(nsapi, &snsm_qos); sndcp_snsm_qos_to_ll_qos(snsm_qos, &ll_unitdesc_req->ll_qos); /* * Set radio prio. */ sndcp_get_nsapi_prio(nsapi, &ll_unitdesc_req->radio_prio); #ifdef REL99 sndcp_get_nsapi_pktflowid(nsapi, (U16*)&ll_unitdesc_req->pkt_flow_id); #endif /*REL99*/ } /* su_add_ll_unitdesc_req_params() */ #else /* _SNDCP_DTI_2_ */ /* +------------------------------------------------------------------------------ | Function : su_add_ll_unitdata_req_params +------------------------------------------------------------------------------ | Description : sets the parameters of the given ll_unitdata_req | | Parameters : nsapi, ll_unitdata_req* | +------------------------------------------------------------------------------ */ LOCAL void su_add_ll_unitdata_req_params (UBYTE nsapi, T_LL_UNITDATA_REQ* ll_unitdata_req) { T_snsm_qos snsm_qos; /* Initialized with getter later */ TRACE_FUNCTION( "su_add_ll_unitdata_req_params" ); /* * Set quality of service. */ sndcp_get_nsapi_qos(nsapi, &snsm_qos); sndcp_snsm_qos_to_ll_qos(snsm_qos, &ll_unitdata_req->ll_qos); /* * Set radio prio. */ sndcp_get_nsapi_prio(nsapi, &ll_unitdata_req->radio_prio); #ifdef REL99 sndcp_get_nsapi_pktflowid(nsapi, &ll_unitdata_req->pkt_flow_id); #endif /*REL99*/ } /* su_add_ll_unitdata_req_params() */ #endif /* _SNDCP_DTI_2_ */ #ifdef _SNDCP_DTI_2_ /* +------------------------------------------------------------------------------ | Function : su_add_sn_header +------------------------------------------------------------------------------ | Description : sets the segment header in the given ll_unitdesc_req | | Parameters : first and/or last segment , ll_unitdesc_req*, packet type | +------------------------------------------------------------------------------ */ LOCAL void su_add_sn_header (UBYTE seg_pos, T_pdu_ref pdu_ref, T_LL_UNITDESC_REQ* ll_unitdesc_req, UBYTE packet_type) { USHORT offset = ENCODE_OFFSET_BYTE; BOOL compressed = FALSE; UBYTE sapi_index = 0; T_desc3* desc3 = NULL; U8* sndcp_header = NULL; TRACE_FUNCTION( "su_add_sn_header" ); sndcp_get_sapi_index(ll_unitdesc_req->sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; /* Get the descriptor describing the memory area with the sndcp header */ desc3 = (T_desc3*)ll_unitdesc_req->desc_list3.first; sndcp_header = (U8*)desc3->buffer; sndcp_header[offset] = 0; /* * Octet 1, F bit. */ if ((seg_pos & SEG_POS_FIRST) > 0) { sndcp_header[offset] += (1 << 6); } /* * Octet 1, 1 for SN_UNITDATA. */ sndcp_header[offset] += (1 << 5); /* * Octet 1, M bit. */ if ((seg_pos & SEG_POS_LAST) == 0) { sndcp_header[offset] += (1 << 4); } /* * Octet 1, NSAPI number. */ sndcp_header[offset] += pdu_ref.ref_nsapi; offset ++; sndcp_header[offset] = 0; if ((seg_pos & SEG_POS_FIRST) > 0) { /* * This is the first bit. * Find d/pcomp values and set them. */ /* * Octet 2, dcomp */ sndcp_header[offset] += (UBYTE)(sndcp_data->mg.cur_xid_block[sapi_index].v42.dcomp << 4); /* * Octet 2, pcomp */ sndcp_is_nsapi_header_compressed(pdu_ref.ref_nsapi, &compressed); if (compressed) { if (packet_type == TYPE_UNCOMPRESSED_TCP) { /* * Uncompressed TCP. */ sndcp_header[offset] = sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1; } else if (packet_type == TYPE_IP) { /* * IP. */ sndcp_header[offset] = 0; } else { /* * Compressed TCP. */ sndcp_header[offset] = sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2; } } offset ++; } /* * Octet 2 or 3, segment number */ sndcp_header[offset] = 0; sndcp_header[offset] += (UBYTE)(pdu_ref.ref_seg_num << 4); /* * Octet 2 or 3, N-PDU number, MSB. */ sndcp_header[offset] += ((pdu_ref.ref_npdu_num >> 8) & 0xf); offset ++; /* * Octet 3 or 4, N-PDU number, LSB. */ sndcp_header[offset] = (pdu_ref.ref_npdu_num & 0xff); } /* su_add_sn_header() */ #else /* _SNDCP_DTI_2_ */ /* +------------------------------------------------------------------------------ | Function : su_add_sn_header +------------------------------------------------------------------------------ | Description : sets the segment header in the given ll_unitdata_req | | Parameters : first and/or last segment , ll_unitdata_req*, packet type | +------------------------------------------------------------------------------ */ LOCAL void su_add_sn_header (UBYTE seg_pos, T_pdu_ref pdu_ref, T_LL_UNITDATA_REQ* ll_unitdata_req, UBYTE packet_type) { USHORT offset = ll_unitdata_req->sdu.o_buf / 8; BOOL compressed = FALSE; UBYTE sapi_index = 0; TRACE_FUNCTION( "su_add_sn_header" ); sndcp_get_sapi_index(ll_unitdata_req->sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; ll_unitdata_req->sdu.buf[offset] = 0; /* * Octet 1, F bit. */ if ((seg_pos & SEG_POS_FIRST) > 0) { ll_unitdata_req->sdu.buf[offset] += (1 << 6); } /* * Octet 1, 1 for SN_UNITDATA. */ ll_unitdata_req->sdu.buf[offset] += (1 << 5); /* * Octet 1, M bit. */ if ((seg_pos & SEG_POS_LAST) == 0) { ll_unitdata_req->sdu.buf[offset] += (1 << 4); } /* * Octet 1, NSAPI number. */ ll_unitdata_req->sdu.buf[offset] += pdu_ref.ref_nsapi; offset ++; ll_unitdata_req->sdu.buf[offset] = 0; if ((seg_pos & SEG_POS_FIRST) > 0) { /* * This is the first bit. * Find d/pcomp values and set them. */ /* * Octet 2, dcomp */ ll_unitdata_req->sdu.buf[offset] += (UBYTE)(sndcp_data->su->cur_xid_block.v42.dcomp << 4); /* * Octet 2, pcomp */ sndcp_is_nsapi_header_compressed(pdu_ref.ref_nsapi, &compressed); if (compressed) { if (packet_type == TYPE_UNCOMPRESSED_TCP) { /* * Uncompressed TCP. */ ll_unitdata_req->sdu.buf[offset] = sndcp_data->su->cur_xid_block.vj.pcomp1; } else if (packet_type == TYPE_IP) { /* * IP. */ ll_unitdata_req->sdu.buf[offset] = 0; } else { /* * Compressed TCP. */ ll_unitdata_req->sdu.buf[offset] = sndcp_data->su->cur_xid_block.vj.pcomp2; } } offset ++; } /* * Octet 2 or 3, segment number */ ll_unitdata_req->sdu.buf[offset] = 0; ll_unitdata_req->sdu.buf[offset] += (UBYTE)(pdu_ref.ref_seg_num << 4); /* * Octet 2 or 3, N-PDU number, MSB. */ ll_unitdata_req->sdu.buf[offset] += ((pdu_ref.ref_npdu_num >> 8) & 0xf); offset ++; /* * Octet 3 or 4, N-PDU number, LSB. */ ll_unitdata_req->sdu.buf[offset] = (pdu_ref.ref_npdu_num & 0xff); } /* su_add_sn_header() */ #endif /* _SNDCP_DTI_2_ */ /*==== PUBLIC FUNCTIONS =====================================================*/ #ifdef _SNDCP_DTI_2_ /* +------------------------------------------------------------------------------ | Function : sig_cia_su_cia_comp_ind +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_CIA_su_CIA_COMP_IND | | Parameters : cia_comp_ind* | +------------------------------------------------------------------------------ */ GLOBAL void sig_cia_su_cia_comp_ind (T_CIA_COMP_IND* cia_comp_ind) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_cia_su_cia_comp_ind" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(cia_comp_ind->sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE: case SU_LLC_NOT_RECEPTIVE_SUSPEND: { /* * Save seg_pos and pdu_ref from cia_comp_ind. */ UBYTE seg_pos = cia_comp_ind->seg_pos; T_pdu_ref pdu_ref = cia_comp_ind->pdu_ref; UBYTE nsapi = cia_comp_ind->pdu_ref.ref_nsapi; UBYTE packet_type = cia_comp_ind->packet_type; PALLOC(ll_unitdesc_req, LL_UNITDESC_REQ); ll_unitdesc_req->sapi = cia_comp_ind->sapi; ll_unitdesc_req->tlli = cia_comp_ind->tlli; ll_unitdesc_req->ll_qos.delay = cia_comp_ind->cia_qos.delay; ll_unitdesc_req->ll_qos.relclass = cia_comp_ind->cia_qos.relclass; ll_unitdesc_req->ll_qos.peak = cia_comp_ind->cia_qos.peak; ll_unitdesc_req->ll_qos.preced = cia_comp_ind->cia_qos.preced; ll_unitdesc_req->ll_qos.mean = cia_comp_ind->cia_qos.mean; /* attached_counter not copied */ /* cipher not copied */ ll_unitdesc_req->reserved_unitdata_req1.ref_nsapi = cia_comp_ind->pdu_ref.ref_nsapi; ll_unitdesc_req->reserved_unitdata_req1.ref_npdu_num = cia_comp_ind->pdu_ref.ref_npdu_num; ll_unitdesc_req->reserved_unitdata_req1.ref_seg_num = cia_comp_ind->pdu_ref.ref_seg_num; ll_unitdesc_req->seg_pos = cia_comp_ind->seg_pos; ll_unitdesc_req->desc_list3.list_len = cia_comp_ind->desc_list3.list_len; ll_unitdesc_req->desc_list3.first = cia_comp_ind->desc_list3.first; su_add_ll_unitdesc_req_params(nsapi, ll_unitdesc_req); su_add_sn_header(seg_pos, pdu_ref, ll_unitdesc_req, packet_type); /* All information has been transferred remove the compression primitive */ MFREE(cia_comp_ind); /* * Write the ll_unitdesc_req prim to ll_unitdesc_q, * increment write pointer. */ sndcp_data->su->ll_unitdesc_q[sndcp_data->su->ll_unitdesc_q_write] = ll_unitdesc_req; sndcp_data->su->ll_unitdesc_q_write = (sndcp_data->su->ll_unitdesc_q_write + 1) % SNDCP_SEGMENT_NUMBERS_UNACK; } break; case SU_LLC_RECEPTIVE: { /* * Save seg_pos and pdu_ref from cia_comp_ind. */ UBYTE ll_unitdesc_sapi; UBYTE seg_pos = cia_comp_ind->seg_pos; T_pdu_ref pdu_ref = cia_comp_ind->pdu_ref; UBYTE nsapi = cia_comp_ind->pdu_ref.ref_nsapi; UBYTE packet_type = cia_comp_ind->packet_type; PALLOC(ll_unitdesc_req, LL_UNITDESC_REQ); ll_unitdesc_req->sapi = cia_comp_ind->sapi; ll_unitdesc_req->tlli = cia_comp_ind->tlli; ll_unitdesc_req->ll_qos.delay = cia_comp_ind->cia_qos.delay; ll_unitdesc_req->ll_qos.relclass = cia_comp_ind->cia_qos.relclass; ll_unitdesc_req->ll_qos.peak = cia_comp_ind->cia_qos.peak; ll_unitdesc_req->ll_qos.preced = cia_comp_ind->cia_qos.preced; ll_unitdesc_req->ll_qos.mean = cia_comp_ind->cia_qos.mean; /* attached_counter not copied */ /* cipher not copied */ ll_unitdesc_req->reserved_unitdata_req1.ref_nsapi = cia_comp_ind->pdu_ref.ref_nsapi; ll_unitdesc_req->reserved_unitdata_req1.ref_npdu_num = cia_comp_ind->pdu_ref.ref_npdu_num; ll_unitdesc_req->reserved_unitdata_req1.ref_seg_num = cia_comp_ind->pdu_ref.ref_seg_num; ll_unitdesc_req->seg_pos = cia_comp_ind->seg_pos; ll_unitdesc_req->desc_list3.list_len = cia_comp_ind->desc_list3.list_len; ll_unitdesc_req->desc_list3.first = cia_comp_ind->desc_list3.first; /* All information has been transferred remove the compression primitive */ MFREE(cia_comp_ind); su_add_ll_unitdesc_req_params(nsapi, ll_unitdesc_req); su_add_sn_header(seg_pos, pdu_ref, ll_unitdesc_req, packet_type); #ifdef SNDCP_TRACE_ALL TRACE_EVENT("uplink with sn header at LL SAP: "); TRACE_EVENT_P1("%d octets", ll_unitdesc_req->desc_list3.list_len); sndcp_trace_desc_list3_content(ll_unitdesc_req->desc_list3); #endif #ifdef FLOW_TRACE sndcp_trace_flow_control(FLOW_TRACE_SNDCP, FLOW_TRACE_UP, FLOW_TRACE_BOTTOM, FALSE); #endif ll_unitdesc_sapi = ll_unitdesc_req->sapi; #ifdef _SIMULATION_ #ifndef MULTI_LAYER su_send_ll_unitdata_req_test(ll_unitdesc_req); #else PSEND(hCommLLC, ll_unitdesc_req); #endif /* MULTI_LAYER */ #else /* _SIMULATION_ */ PSEND(hCommLLC, ll_unitdesc_req); #endif /* _SIMULATION_ */ SET_STATE(SU, SU_LLC_NOT_RECEPTIVE); /* * If segment is the last of the N-PDU then send ready_ind to nsapi * and get next entry from sn q.. */ if ((seg_pos & SEG_POS_LAST) > 0) { sndcp_data->su->cia_state = CIA_IDLE; su_next_sn_unitdata_req( ll_unitdesc_sapi ); sig_su_nu_ready_ind(nsapi); } } break; default: TRACE_ERROR( "SIG_CIA_SU_CIA_COMP_IND unexpected" ); sndcp_cl_desc3_free((T_desc3*)cia_comp_ind->desc_list3.first); MFREE(cia_comp_ind); break; } } /* sig_cia_su_cia_comp_ind() */ #else /* _SNDCP_DTI_2_ */ /* +------------------------------------------------------------------------------ | Function : sig_cia_su_cia_comp_ind +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_CIA_su_CIA_COMP_IND | | Parameters : cia_comp_ind* | +------------------------------------------------------------------------------ */ GLOBAL void sig_cia_su_cia_comp_ind (T_CIA_COMP_IND* cia_comp_ind) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_cia_su_cia_comp_ind" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(cia_comp_ind->sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE: case SU_LLC_NOT_RECEPTIVE_SUSPEND: { /* * Save seg_pos and pdu_ref from cia_comp_ind. */ UBYTE seg_pos = cia_comp_ind->seg_pos; T_pdu_ref pdu_ref = cia_comp_ind->pdu_ref; UBYTE nsapi = cia_comp_ind->pdu_ref.ref_nsapi; UBYTE packet_type = cia_comp_ind->packet_type; PPASS(cia_comp_ind, ll_unitdata_req, LL_UNITDATA_REQ); su_add_ll_unitdata_req_params(nsapi, ll_unitdata_req); su_add_sn_header(seg_pos, pdu_ref, ll_unitdata_req, packet_type); /* * Write the ll_unitdata_req prim to ll_unitdata_q, * increment write pointer. */ sndcp_data->su->ll_unitdata_q[sndcp_data->su->ll_unitdata_q_write] = ll_unitdata_req; sndcp_data->su->ll_unitdata_q_write = (sndcp_data->su->ll_unitdata_q_write + 1) % SNDCP_SEGMENT_NUMBERS_UNACK; } break; case SU_LLC_RECEPTIVE: { /* * Save seg_pos and pdu_ref from cia_comp_ind. */ UBYTE ll_unitdata_sapi; UBYTE seg_pos = cia_comp_ind->seg_pos; T_pdu_ref pdu_ref = cia_comp_ind->pdu_ref; UBYTE nsapi = cia_comp_ind->pdu_ref.ref_nsapi; UBYTE packet_type = cia_comp_ind->packet_type; PPASS(cia_comp_ind, ll_unitdata_req, LL_UNITDATA_REQ); su_add_ll_unitdata_req_params(nsapi, ll_unitdata_req); su_add_sn_header(seg_pos, pdu_ref, ll_unitdata_req, packet_type); #ifdef SNDCP_TRACE_ALL TRACE_EVENT("uplink with sn header at LL SAP: "); TRACE_EVENT_P1("%d octets", (ll_unitdata_req->sdu.l_buf + 7) / 8); sndcp_trace_sdu(& ll_unitdata_req->sdu); #endif #ifdef FLOW_TRACE sndcp_trace_flow_control(FLOW_TRACE_SNDCP, FLOW_TRACE_UP, FLOW_TRACE_BOTTOM, FALSE); #endif ll_unitdata_sapi = ll_unitdata_req->sapi; PSEND(hCommLLC, ll_unitdata_req); SET_STATE(SU, SU_LLC_NOT_RECEPTIVE); /* * If segment is the last of the N-PDU then send ready_ind to nsapi * and get next entry from sn q.. */ if ((seg_pos & SEG_POS_LAST) > 0) { sndcp_data->su->cia_state = CIA_IDLE; su_next_sn_unitdata_req( ll_unitdata_sapi ); sig_su_nu_ready_ind(nsapi); } } break; default: TRACE_ERROR( "SIG_CIA_SU_CIA_COMP_IND unexpected" ); break; } } /* sig_cia_su_cia_comp_ind() */ #endif /* _SNDCP_DTI_2_ */ /* +------------------------------------------------------------------------------ | Function : sig_mg_su_delete_pdus +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_MG_SU_DELETE_PDUS | The same as the one in service sua, but everything is in the | unacknowledged version here. | | Parameters : UBYTE nsapi the affected nsapi, UBYTE sapi the affected sapi | +------------------------------------------------------------------------------ */ GLOBAL void sig_mg_su_delete_pdus (UBYTE nsapi, UBYTE sapi) { UBYTE sapi_index = 0; BOOL ll_q_affected = FALSE; TRACE_ISIG( "sig_mg_su_delete_pdus" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; sndcp_data->su->cia_state = CIA_IDLE; switch( GET_STATE( SU ) ) { case SU_LLC_NOT_RECEPTIVE_SUSPEND: case SU_LLC_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE: case SU_LLC_RECEPTIVE: { /* * Delete affected N-PDUS from sn_unitdata_q. */ BOOL still = TRUE; UBYTE index = sndcp_data->su->sn_unitdata_q_read; while (still) { if (index == sndcp_data->su->sn_unitdata_q_write) { break; } if (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) { /* * The index for the prims to be shifted when 1 entry is deleted. */ UBYTE i = 0; if (sndcp_data->su->sn_unitdata_q[index] != NULL) { #ifdef _SNDCP_DTI_2_ MFREE_PRIM(sndcp_data->su->sn_unitdata_q[index]); #else /*_SNDCP_DTI_2_*/ PFREE_DESC(sndcp_data->su->sn_unitdata_q[index]); #endif /*_SNDCP_DTI_2_*/ sndcp_data->su->sn_unitdata_q[index] = NULL; } for (i = index; i != sndcp_data->su->sn_unitdata_q_write; i = (i + 1) % SN_UNITDATA_Q_LEN) { sndcp_data->su->sn_unitdata_q[i] = sndcp_data->su->sn_unitdata_q[(i + 1) % SN_UNITDATA_Q_LEN]; sndcp_data->su->sn_unitdata_q[(i + 1) % SN_UNITDATA_Q_LEN] = NULL; } sndcp_data->su->sn_unitdata_q_write = (sndcp_data->su->sn_unitdata_q_write - 1 + SN_UNITDATA_Q_LEN) % SN_UNITDATA_Q_LEN; } else { index = (index + 1) % SN_UNITDATA_Q_LEN; } /* else (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) */ } #ifdef _SNDCP_DTI_2_ /* * Delete affected SN-PDUS from ll_unitdata_q. */ still = TRUE; index = sndcp_data->su->ll_unitdesc_q_read; while (still) { if (index == sndcp_data->su->ll_unitdesc_q_write) { break; } if (su_get_nsapi(sndcp_data->su->ll_unitdesc_q[index]) == nsapi) { /* * The index for the prims to be shifted when 1 entry is deleted. */ UBYTE i = 0; ll_q_affected = TRUE; /* * Free the deleted primitive. */ if (sndcp_data->su->ll_unitdesc_q[index] != NULL) { T_desc3 *free_help, *help = (T_desc3 *)sndcp_data->su->ll_unitdesc_q[index]->desc_list3.first; while(help != NULL) { sndcp_cl_desc3_free(help); free_help = help; help = (T_desc3 *)free_help->next; MFREE(free_help); } sndcp_data->su->ll_unitdesc_q[index]->desc_list3.first = NULL; PFREE(sndcp_data->su->ll_unitdesc_q[index]); sndcp_data->su->ll_unitdesc_q[index] = NULL; } for (i = index; i != sndcp_data->su->ll_unitdesc_q_write; i = (i + 1) % SNDCP_SEGMENT_NUMBERS_UNACK) { sndcp_data->su->ll_unitdesc_q[i] = sndcp_data->su->ll_unitdesc_q [(i + 1) % SNDCP_SEGMENT_NUMBERS_UNACK]; } sndcp_data->su->ll_unitdesc_q_write = (sndcp_data->su->ll_unitdesc_q_write - 1 + SNDCP_SEGMENT_NUMBERS_UNACK) % SNDCP_SEGMENT_NUMBERS_UNACK; } else { index = (index + 1) % SNDCP_SEGMENT_NUMBERS_UNACK; } /* else (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) { */ } #else /* _SNDCP_DTI_2_ */ /* * Delete affected SN-PDUS from ll_unitdata_q. */ still = TRUE; index = sndcp_data->su->ll_unitdata_q_read; while (still) { if (index == sndcp_data->su->ll_unitdata_q_write) { break; } if (su_get_nsapi(sndcp_data->su->ll_unitdata_q[index]) == nsapi) { /* * The index for the prims to be shifted when 1 entry is deleted. */ UBYTE i = 0; ll_q_affected = TRUE; /* * Free the deleted primitive. */ if (sndcp_data->su->ll_unitdata_q[index] != NULL) { PFREE(sndcp_data->su->ll_unitdata_q[index]); sndcp_data->su->ll_unitdata_q[index] = NULL; } for (i = index; i != sndcp_data->su->ll_unitdata_q_write; i = (i + 1) % SNDCP_SEGMENT_NUMBERS_UNACK) { sndcp_data->su->ll_unitdata_q[i] = sndcp_data->su->ll_unitdata_q [(i + 1) % SNDCP_SEGMENT_NUMBERS_UNACK]; } sndcp_data->su->ll_unitdata_q_write = (sndcp_data->su->ll_unitdata_q_write - 1 + SNDCP_SEGMENT_NUMBERS_UNACK) % SNDCP_SEGMENT_NUMBERS_UNACK; } else { index = (index + 1) % SNDCP_SEGMENT_NUMBERS_UNACK; } /* else (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) { */ } #endif /* _SNDCP_DTI_2_ */ } /* * if the segments in LL queue were from the affected nsapi then the * next N-PDU is directed to cia. */ if (ll_q_affected) { su_next_sn_unitdata_req (sapi); } break; default: TRACE_ERROR( "SIG_MG_SU_DELETE_PDUS unexpected" ); break; } } /* sig_mg_su_delete_pdus() */ /* +------------------------------------------------------------------------------ | Function : sig_mg_su_n201 +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_MG_SU_N201 | | Parameters : UBYTE sapi the affected sapi, USHORT n201 | +------------------------------------------------------------------------------ */ GLOBAL void sig_mg_su_n201 (UBYTE sapi, USHORT n201) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_mg_su_n201" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_NOT_RECEPTIVE_SUSPEND: case SU_LLC_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE: case SU_LLC_RECEPTIVE: sndcp_data->su->n201_u = n201; break; default: TRACE_ERROR( "SIG_MG_SU_N201 unexpected" ); break; } } /* sig_mg_su_n201() */ /* +------------------------------------------------------------------------------ | Function : sig_mg_su_suspend +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_MG_SU_SUSPEND | | Parameters : UBYTE sapi the affected sapi | +------------------------------------------------------------------------------ */ GLOBAL void sig_mg_su_suspend (UBYTE sapi) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_mg_su_suspend" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_NOT_RECEPTIVE_SUSPEND: break; case SU_LLC_RECEPTIVE_SUSPEND: break; case SU_LLC_NOT_RECEPTIVE: SET_STATE (SU, SU_LLC_NOT_RECEPTIVE_SUSPEND); break; case SU_LLC_RECEPTIVE: SET_STATE (SU, SU_LLC_RECEPTIVE_SUSPEND); break; default: TRACE_ERROR( "SIG_MG_SU_SUSPEND unexpected" ); break; } } /* sig_mg_su_suspend() */ /* +------------------------------------------------------------------------------ | Function : sig_mg_su_reset_ind +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_MG_SU_RESET_IND | | Parameters : UBYTE sapi the affected sapi | +------------------------------------------------------------------------------ */ GLOBAL void sig_mg_su_reset_ind (UBYTE sapi) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_mg_su_reset_ind" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_NOT_RECEPTIVE_SUSPEND: case SU_LLC_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE: case SU_LLC_RECEPTIVE: break; default: TRACE_ERROR( "SIG_MG_SU_RESET_IND unexpected" ); break; } } /* sig_mg_su_reset_ind() */ #ifdef _SNDCP_DTI_2_ /* +------------------------------------------------------------------------------ | Function : sig_mg_su_resume +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_MG_SU_RESUME | | Parameters : UBYTE sapi the affected sapi | +------------------------------------------------------------------------------ */ GLOBAL void sig_mg_su_resume (UBYTE sapi) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_mg_su_resume" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_NOT_RECEPTIVE_SUSPEND: SET_STATE (SU, SU_LLC_NOT_RECEPTIVE); break; case SU_LLC_RECEPTIVE_SUSPEND: /* * Is queue with LL_UNITDESC_REQ empty? */ if (sndcp_data->su->ll_unitdesc_q_write == sndcp_data->su->ll_unitdesc_q_read) { SET_STATE(SU, SU_LLC_RECEPTIVE); } else { /* * Get next segment from queue and send it. */ U8 ll_unitdesc_seg_pos; U8 ll_unitdesc_nsapi; U8 ll_unitdesc_sapi; T_LL_UNITDESC_REQ* ll_unitdesc_req = sndcp_data->su->ll_unitdesc_q[sndcp_data->su->ll_unitdesc_q_read]; sndcp_data->su->ll_unitdesc_q[sndcp_data->su->ll_unitdesc_q_read] = NULL; sndcp_data->su->ll_unitdesc_q_read = (sndcp_data->su->ll_unitdesc_q_read + 1) % SNDCP_SEGMENT_NUMBERS_UNACK; /* * trace output */ #ifdef SNDCP_TRACE_ALL TRACE_EVENT("uplink with sn header at LL SAP: "); TRACE_EVENT_P1("%d octets", ll_unitdesc_req->desc_list3.list_len); sndcp_trace_desc_list3_content(ll_unitdesc_req->desc_list3); #endif #ifdef FLOW_TRACE sndcp_trace_flow_control(FLOW_TRACE_SNDCP, FLOW_TRACE_UP, FLOW_TRACE_BOTTOM, FALSE); #endif ll_unitdesc_seg_pos = ll_unitdesc_req->seg_pos; ll_unitdesc_nsapi = su_get_nsapi(ll_unitdesc_req); ll_unitdesc_sapi = ll_unitdesc_req->sapi; #ifdef _SIMULATION_ su_send_ll_unitdata_req_test(ll_unitdesc_req); #else /* _SIMULATION_ */ PSEND(hCommLLC, ll_unitdesc_req); #endif /* _SIMULATION_ */ SET_STATE(SU, SU_LLC_NOT_RECEPTIVE); /* * If segment is the last of the N-PDU then send ready_ind to nsapi * and get next entry from sn q.. */ if ((ll_unitdesc_seg_pos & SEG_POS_LAST) > 0) { sndcp_data->su->cia_state = CIA_IDLE; su_next_sn_unitdata_req( ll_unitdesc_sapi ); sig_su_nu_ready_ind( ll_unitdesc_nsapi ); } } break; case SU_LLC_NOT_RECEPTIVE: break; case SU_LLC_RECEPTIVE: break; default: TRACE_ERROR( "SIG_MG_SU_RESUME unexpected" ); break; } } /* sig_mg_su_resume() */ #else /* _SNDCP_DTI_2_ */ /* +------------------------------------------------------------------------------ | Function : sig_mg_su_resume +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_MG_SU_RESUME | | Parameters : UBYTE sapi the affected sapi | +------------------------------------------------------------------------------ */ GLOBAL void sig_mg_su_resume (UBYTE sapi) { UBYTE sapi_index = 0; TRACE_ISIG( "sig_mg_su_resume" ); /* * Set service instance according to sapi in signal. */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_NOT_RECEPTIVE_SUSPEND: SET_STATE (SU, SU_LLC_NOT_RECEPTIVE); break; case SU_LLC_RECEPTIVE_SUSPEND: /* * Is queue with LL_UNITDATA_REQ empty? */ if (sndcp_data->su->ll_unitdata_q_write == sndcp_data->su->ll_unitdata_q_read) { SET_STATE(SU, SU_LLC_RECEPTIVE); } else { /* * Get next segment from queue and send it. */ UBYTE ll_unitdata_seg_pos; UBYTE ll_unitdata_nsapi; UBYTE ll_unitdata_sapi; T_LL_UNITDATA_REQ* ll_unitdata_req = sndcp_data->su->ll_unitdata_q[sndcp_data->su->ll_unitdata_q_read]; sndcp_data->su->ll_unitdata_q[sndcp_data->su->ll_unitdata_q_read] = NULL; sndcp_data->su->ll_unitdata_q_read = (sndcp_data->su->ll_unitdata_q_read + 1) % SNDCP_SEGMENT_NUMBERS_UNACK; /* * trace output */ #ifdef SNDCP_TRACE_ALL TRACE_EVENT("uplink with sn header at LL SAP: "); TRACE_EVENT_P1("%d octets", (ll_unitdata_req->sdu.l_buf + 7) / 8); sndcp_trace_sdu(& ll_unitdata_req->sdu); #endif #ifdef FLOW_TRACE sndcp_trace_flow_control(FLOW_TRACE_SNDCP, FLOW_TRACE_UP, FLOW_TRACE_BOTTOM, FALSE); #endif ll_unitdata_seg_pos = ll_unitdata_req->seg_pos; ll_unitdata_nsapi = su_get_nsapi(ll_unitdata_req); ll_unitdata_sapi = ll_unitdata_req->sapi; PSEND(hCommLLC, ll_unitdata_req); SET_STATE(SU, SU_LLC_NOT_RECEPTIVE); /* * If segment is the last of the N-PDU then send ready_ind to nsapi * and get next entry from sn q.. */ if ((ll_unitdata_seg_pos & SEG_POS_LAST) > 0) { sndcp_data->su->cia_state = CIA_IDLE; su_next_sn_unitdata_req( ll_unitdata_sapi ); sig_su_nu_ready_ind( ll_unitdata_nsapi ); } } break; case SU_LLC_NOT_RECEPTIVE: break; case SU_LLC_RECEPTIVE: break; default: TRACE_ERROR( "SIG_MG_SU_RESUME unexpected" ); break; } } /* sig_mg_su_resume() */ #endif /* _SNDCP_DTI_2_ */ /* +------------------------------------------------------------------------------ | Function : sig_nu_su_unitdata_req +------------------------------------------------------------------------------ | Description : Handles the internal signal SIG_NU_SU_UNITDATA_REQ | | Parameters : T_SN_UNITDATA_REQ , N-PDU to be sent to sapiup in form of | prim struct | USHORT, the send N-PDU number of this N-PDU | UBYTE, the number of the NSAPI who sent the N-PDU | UBYTE), the SAPI that is supposed to compute the N-PDU | | +------------------------------------------------------------------------------ */ GLOBAL void sig_nu_su_unitdata_req (T_SN_UNITDATA_REQ* sn_unitdata_req, USHORT npdu_number, UBYTE nsapi, UBYTE sapi ) { UBYTE sapi_index = 0; #ifdef _SNDCP_MEAN_TRACE_ #ifdef _SNDCP_DTI_2_ sndcp_mean_trace(nsapi, SNDCP_MEAN_UP, SNDCP_MEAN_UNACK, sn_unitdata_req->desc_list2.list_len); #else /*_SNDCP_DTI_2_*/ sndcp_mean_trace(nsapi, SNDCP_MEAN_UP, SNDCP_MEAN_UNACK, sn_unitdata_req->desc_list.list_len); #endif /*_SNDCP_DTI_2_*/ #endif /* _SNDCP_MEAN_TRACE_ */ TRACE_ISIG( "sig_nu_su_unitdata_req" ); /* * set service instance according to sapi in signal */ sndcp_get_sapi_index(sapi, &sapi_index); sndcp_data->su = & sndcp_data->su_base[sapi_index]; switch( GET_STATE( SU ) ) { case SU_LLC_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE_SUSPEND: case SU_LLC_NOT_RECEPTIVE: case SU_LLC_RECEPTIVE: /* * If queue with NPDUs is empty, and cia is not busy, * send the NPDU to cia, else * add it to the queue. */ if ((sndcp_data->su->sn_unitdata_q_read == sndcp_data->su->sn_unitdata_q_write) && (sndcp_data->su->ll_unitdesc_q_read == sndcp_data->su->ll_unitdesc_q_write) && sndcp_data->su->cia_state == CIA_IDLE) { /* * Send the NPDU to cia. */ sndcp_data->su->cia_state = CIA_BUSY; sig_su_cia_cia_comp_req(sn_unitdata_req, npdu_number, nsapi, sapi); } else { /* Queue with NPDUs is not empty or cia is busy. */ /* * Write the sn_unitdata_req prim to sn_unitdata_q, * increment write pointer. */ sndcp_data->su->sn_unitdata_q[sndcp_data->su->sn_unitdata_q_write] = sn_unitdata_req; sndcp_data->su->npdu_number_q[sndcp_data->su->sn_unitdata_q_write] = npdu_number; sndcp_data->su->sn_unitdata_q_write = (sndcp_data->su->sn_unitdata_q_write + 1) % SN_UNITDATA_Q_LEN; } /* Queue with NPDUs is not empty or cia is busy. */ break; default: TRACE_ERROR( "SIG_NU_SU_UNITDATA_REQ unexpected" ); #ifdef _SNDCP_DTI_2_ MFREE_PRIM(sn_unitdata_req); #else /*_SNDCP_DTI_2_*/ PFREE_DESC(sn_unitdata_req); #endif /*_SNDCP_DTI_2_*/ break; } } /* sig_nu_su_unitdata_req() */ #ifdef _SIMULATION_ #ifdef _SNDCP_DTI_2_ /* +------------------------------------------------------------------------------ | Function : su_send_ll_unitdata_req_test +------------------------------------------------------------------------------ | Description : Only for test purposes. | The given LL_UNITDESC_REQ is copied to an | LL_UNITDATA_REQ and sent for the simulated test environment. | | Parameters : | +------------------------------------------------------------------------------ */ void su_send_ll_unitdata_req_test(T_LL_UNITDESC_REQ* ll_unitdesc_req) { T_desc3* descriptor = NULL; U8* p_data = NULL; U16 offset = ENCODE_OFFSET_BYTE; PALLOC_SDU(ll_unitdata_req, LL_UNITDATA_REQ, (U16)( ll_unitdesc_req->desc_list3.list_len* 8)); /* * Set parameters in ll_unitdata_req primitive */ ll_unitdata_req->sapi = ll_unitdesc_req->sapi; ll_unitdata_req->tlli = ll_unitdesc_req->tlli; ll_unitdata_req->ll_qos = ll_unitdesc_req->ll_qos; ll_unitdata_req->radio_prio = ll_unitdesc_req->radio_prio; ll_unitdata_req->cipher = ll_unitdesc_req->cipher; ll_unitdata_req->reserved_unitdata_req1 = ll_unitdesc_req->reserved_unitdata_req1; ll_unitdata_req->seg_pos = ll_unitdesc_req->seg_pos; ll_unitdata_req->attached_counter = ll_unitdesc_req->attached_counter; ll_unitdata_req->reserved_unitdata_req4 = ll_unitdesc_req->reserved_unitdata_req4; #ifdef REL99 ll_unitdata_req->pkt_flow_id = ll_unitdesc_req->pkt_flow_id; #endif /*REL99*/ /* * Set the ENCODE_OFFSET in the uplink sdu, set sdu.l_buf */ ll_unitdata_req->sdu.o_buf = ENCODE_OFFSET; ll_unitdata_req->sdu.l_buf = ll_unitdesc_req->desc_list3.list_len* 8; /* * Copy the data. */ descriptor = (T_desc3*)ll_unitdesc_req->desc_list3.first; while (descriptor != NULL) { T_desc3* help = descriptor; p_data = (U8*)descriptor->buffer; if (descriptor->len>0) { memcpy(&ll_unitdata_req->sdu.buf[offset], &p_data[descriptor->offset], descriptor->len); } offset += descriptor->len; descriptor = (T_desc3*)descriptor->next; sndcp_cl_desc3_free(help); MFREE(help); help = NULL; } PSEND(hCommLLC, ll_unitdata_req); PFREE(ll_unitdesc_req); // MAYBE REMEMBER is this the correct free? } /* su_send_ll_unitdata_req_test */ #endif /* _SNDCP_DTI_2_ */ #endif /* _SIMULATION_ */