FreeCalypso > hg > fc-tourmaline
view src/g23m-gprs/llc/llc_irxf.c @ 51:04aaa5622fa7
disable deep sleep when Iota LEDB is on
TI's Iota chip docs say that CLK13M must be running in order for
LEDB to work, and practical experience on Mot C139 which uses
Iota LEDB for its keypad backlight concurs: if Calypso enters
deep sleep while the keypad backlight is turned on, the light
flickers visibly as the chipset goes into and out of deep sleep.
TI's original L1 sleep manager code had logic to disable deep sleep
when LT_Status() returns nonzero, but that function only works
for B-Sample and C-Sample LT, always returns 0 on BOARD 41 - no
check of Iota LEDB status anywhere. Change this code for our
current hardware: disable deep sleep when Iota LEDB has been
turned on through LLS.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 19 Oct 2020 05:11:29 +0000 |
parents | fa8dc04885d8 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | 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 LLC and implements all | procedures and functions as described in the | SDL-documentation (IRX-statemachine) +----------------------------------------------------------------------------- */ #ifndef LLC_IRXF_C #define LLC_IRXF_C #endif #define ENTITY_LLC /*==== INCLUDES =============================================================*/ #include <string.h> #include "typedefs.h" /* to get Condat data types */ #include "vsi.h" /* to get a lot of macros */ #include "macdef.h" #include "gprs.h" #include "gsm.h" /* to get a lot of macros */ #include "cnf_llc.h" /* to get cnf-definitions */ #include "mon_llc.h" /* to get mon-definitions */ #include "prim.h" /* to get the definitions of used SAP and directions */ #include "llc.h" /* to get the global entity definitions */ #include "llc_itxs.h" /* to get ITX signal definitions */ #include "llc_irxf.h" /* to get IRX local functions */ /*==== CONST ================================================================*/ /*==== LOCAL VARS ===========================================================*/ /*==== PRIVATE FUNCTIONS ====================================================*/ /*==== PUBLIC FUNCTIONS =====================================================*/ /* +------------------------------------------------------------------------------ | Function : irx_init +------------------------------------------------------------------------------ | Description : This procedure initialises all necessary variables of | i_frames_rx for all SAPIs. | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_init (void) { UBYTE inc; TRACE_FUNCTION( "irx_init" ); /* * Initialise all 4 SAPIs */ SWITCH_SERVICE (llc, irx, 0); INIT_STATE (IRX_0, IRX_TLLI_UNASSIGNED); SWITCH_SERVICE (llc, irx, 1); INIT_STATE (IRX_1, IRX_TLLI_UNASSIGNED); SWITCH_SERVICE (llc, irx, 2); INIT_STATE (IRX_2, IRX_TLLI_UNASSIGNED); SWITCH_SERVICE (llc, irx, 3); INIT_STATE (IRX_3, IRX_TLLI_UNASSIGNED); /* * Initialise the IRX data structure */ for (inc = 0; inc < IRX_NUM_INC; inc++) { SWITCH_SERVICE (llc, irx, inc); /* * Free old used resources (in case of an LLC restart): * memory, stored primitives, running timer. */ irx_queue_clean (); llc_data->irx->ll_send_ready = FALSE; llc_data->irx->last_ns = NS_EQUAL_VR; llc_data->irx->queue = NULL; } return; } /* irx_init() */ /* +------------------------------------------------------------------------------ | Function : irx_init_sapi +------------------------------------------------------------------------------ | Description : This procedure initialises all necessary variables of | i_frames_rx for the given SAPI. | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_init_sapi (void) { TRACE_FUNCTION( "irx_init_sapi" ); llc_data->sapi->va = 0; llc_data->sapi->vs = 0; llc_data->sapi->vr = 0; llc_data->irx->vf = 0; llc_data->irx->last_ns = NS_EQUAL_VR; llc_data->irx->B_rx = 0; return; } /* irx_init_sapi() */ /* +------------------------------------------------------------------------------ | Function : irx_init_abm +------------------------------------------------------------------------------ | Description : This procedure initialises all necessary variables of | i_frames_rx for the given SAPI when switching into ABM. | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_init_abm (void) { TRACE_FUNCTION( "irx_init_abm" ); llc_data->sapi->va = 0; llc_data->sapi->vs = 0; llc_data->sapi->vr = 0; llc_data->irx->vf = 0; llc_data->irx->last_ns = NS_EQUAL_VR; /* * Reset OCs for acknowledged transfer. */ llc_data->sapi->oc_i_tx = 0L; llc_data->sapi->oc_i_rx = 0L; return; } /* irx_init_abm() */ /* +------------------------------------------------------------------------------ | Function : irx_queue_store +------------------------------------------------------------------------------ | Description : This procedure stores the primitive into the per ns sorted | queue. If the queue is full, is_busy set to TRUE will be | returnd. | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_queue_store (T_LL_UNITDATA_IND *ll_unitdata_ind, T_FRAME_NUM ns, BOOL *is_busy) { T_IRX_QUEUE** entry = &(llc_data->irx->queue); T_IRX_QUEUE* next; T_FRAME_NUM n = llc_data->irx->vf; ULONG M = *(llc_data->md) * 16; TRACE_FUNCTION( "irx_queue_store" ); /* * First skip already for L3 ready waiting entries */ while (*entry && (*entry)->ns == n) { n++; n %= (MAX_SEQUENCE_NUMBER+1); if ((*entry)->ns == ns) { /* * Ignore duplicate frame */ *is_busy = FALSE; TRACE_0_INFO( "Unexpected duplicate frame number" ); PFREE (ll_unitdata_ind); return; } entry = &((*entry)->next); } /* * Now find the inserting position (queue sorted per ns, * 'lower' frame numbers stored first) */ while (*entry) { if ((*entry)->ns == ns) { /* * Ignore duplicate frame */ *is_busy = FALSE; TRACE_0_INFO( "Duplicate frame number received" ); PFREE (ll_unitdata_ind); return; } /* * n <= ns <= (*entry)->ns - 1 */ if (FRAME_NUM_VALID( n, ns, (*entry)->ns - 1)) { /* * Found a nice place in between */ break; } entry = &((*entry)->next); } /* * Position found - save ptr to next entry */ next = *entry; /* * Allocate memory */ MALLOC( *entry, sizeof(T_IRX_QUEUE) ); if( *entry ) { /* * Memory successful allocated. Fill in struct entries. */ (*entry)->next = next; (*entry)->ns = ns; (*entry)->frame = ll_unitdata_ind; /* * Increase amount of stored Information in rx queue */ llc_data->irx->B_rx += BYTELEN(ll_unitdata_ind->sdu.l_buf); /* * Determine 'own receiver busy' condition */ if ((M == 0) || (*(llc_data->n201_i) <= M - llc_data->irx->B_rx)) { *is_busy = FALSE; } else { *is_busy = TRUE; } } else { /* * Out of memory */ *is_busy = TRUE; TRACE_ERROR( "Out of memory in irx_queue_store()" ); PFREE (ll_unitdata_ind); } } /* irx_queue_store() */ /* +------------------------------------------------------------------------------ | Function : irx_update_vr +------------------------------------------------------------------------------ | Description : This procedure increments V(R) if the next following frames | are already stored in the queue. | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_update_vr (void) { T_IRX_QUEUE* entry = llc_data->irx->queue; TRACE_FUNCTION( "irx_update_vr" ); /* * Search the queue from the beginning to entry V(R) */ while (entry) { if (entry->ns == llc_data->sapi->vr) { /* * Increment V(R) and continue searching */ llc_data->sapi->vr++; if (llc_data->sapi->vr > MAX_SEQUENCE_NUMBER) { llc_data->sapi->oc_i_rx += (MAX_SEQUENCE_NUMBER+1); llc_data->sapi->vr = 0; } } entry = entry->next; } } /* irx_update_vr() */ /* +------------------------------------------------------------------------------ | Function : irx_get_last_queued_ns +------------------------------------------------------------------------------ | Description : This procedure returns the frame number of the last queue entry | | Parameters : *found - set to TRUE if ns found, FALSE otherwise | +------------------------------------------------------------------------------ */ GLOBAL void irx_get_last_queued_ns (BOOL *found, T_FRAME_NUM *num) { T_IRX_QUEUE* entry = llc_data->irx->queue; TRACE_FUNCTION( "irx_get_last_queued_ns" ); /* * Search the queue from the beginning to last entry */ while (entry AND entry->next) entry = entry->next; if (entry) { *found = TRUE; *num = entry->ns; } else { *found = FALSE; *num = 0; } } /* irx_get_last_queued_ns() */ /* +------------------------------------------------------------------------------ | Function : irx_queue_retrieve +------------------------------------------------------------------------------ | Description : If the next frame in sequence is stored in the queue then this | procedure will return the primitive pointer, sets found to | TRUE and removes the frame from the queue. | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_queue_retrieve (T_LL_UNITDATA_IND **ll_unitdata_ind, BOOL *found) { T_IRX_QUEUE** entry = &(llc_data->irx->queue); TRACE_FUNCTION( "irx_queue_retrieve" ); /* * Take the first queue entry, if this is the next one (queue is sorted per ns) */ if ((*entry != NULL) && ((*entry)->ns == llc_data->irx->vf)) { /* * Store pointer to the entry */ T_IRX_QUEUE* current = *entry; /* * Remove entry from the queue (make second to first) */ *entry = current->next; *ll_unitdata_ind = current->frame; /* * Decrease amount of stored Information in rx queue */ if (llc_data->irx->B_rx >= (ULONG)(BYTELEN((*ll_unitdata_ind)->sdu.l_buf))) { llc_data->irx->B_rx -= BYTELEN((*ll_unitdata_ind)->sdu.l_buf); } else { llc_data->irx->B_rx = 0; TRACE_0_INFO("Unexpected SDU lenght handled"); } /* * Free retrieved entry */ MFREE (current); *found = TRUE; /* * Increment V(f) (= Next frame number to forward to L3) */ llc_data->irx->vf += 1; llc_data->irx->vf %= (MAX_SEQUENCE_NUMBER+1); return; } /* * Set default return values */ *ll_unitdata_ind = NULL; *found = FALSE; } /* +------------------------------------------------------------------------------ | Function : irx_queue_clean +------------------------------------------------------------------------------ | Description : This procedure removes all entries from the IRX queue | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_queue_clean (void) { T_IRX_QUEUE** entry = &(llc_data->irx->queue); TRACE_FUNCTION( "irx_queue_clean" ); while (*entry) { /* * get pointer to next (=first) entry */ T_IRX_QUEUE* current = *entry; /* * Free frame, if one is attached to the entry */ if (current->frame != NULL) { PFREE (current->frame); } /* * remove next entry from the entry (make second to first) */ *entry = current->next; /* * free the removed entry */ MFREE (current); } /* * Adjust amount of stored Information in rx queue */ llc_data->irx->B_rx = 0; } /* irx_queue_clean() */ /* +------------------------------------------------------------------------------ | Function : irx_build_sack_bitmap +------------------------------------------------------------------------------ | Description : This procedure builds a SACK bitmap, depending on current | status | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_build_sack_bitmap ( T_SACK_BITMAP *bitmap ) { T_IRX_QUEUE* entry = llc_data->irx->queue; int start_ns = (llc_data->sapi->vr + 1) % (MAX_SEQUENCE_NUMBER+1); T_FRAME_NUM num = llc_data->irx->vf; USHORT d; TRACE_FUNCTION( "irx_build_sack_bitmap" ); /* * Init bitmap to 0 (= frame not successfully received) */ memset (bitmap, 0, sizeof(T_SACK_BITMAP)); /* * Skip already for L3 ready waiting entries */ while (entry && entry->ns == num) { num++; num %= (MAX_SEQUENCE_NUMBER+1); entry = entry->next; } /* * Check the queue for successful received entries */ while (entry) { /* * If frame is successful received, mark it in bitmap */ d = FRAME_NUM_DISTANCE(start_ns, entry->ns); if (d < (S_FRAME_SACK_MAX_CTRL_OCTETS * 8)) { bitmap->data[d>>3] |= 0x80>>(d%8); } entry = entry->next; } } /* irx_build_sack_bitmap () */ /* +------------------------------------------------------------------------------ | Function : irx_ack_all_to +------------------------------------------------------------------------------ | Description : This procedure handles the acknowledgement of transmitted I- | frames from va to n (which is equal to nr -1) | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_ack_all_to (T_FRAME_NUM n) { TRACE_FUNCTION( "irx_ack_all_to" ); n %= (MAX_SEQUENCE_NUMBER+1); if (FRAME_WIN_VALID(n, llc_data->sapi->va, *(llc_data->ku))) { while (llc_data->sapi->va != (n+1)%(MAX_SEQUENCE_NUMBER+1)) { sig_irx_itx_ack_ind (TRUE, llc_data->sapi->va); llc_data->sapi->va++; llc_data->sapi->va %= (MAX_SEQUENCE_NUMBER+1); } /* * Sending L3 Data confirmations */ sig_irx_itx_cnf_l3data_req (); } } /* irx_ack_all_to () */ /* +------------------------------------------------------------------------------ | Function : irx_handle_sack +------------------------------------------------------------------------------ | Description : This procedure handles the acknowledge bits of a SACK | supervisory frame and strips the SACK bitmap from the SDU | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_handle_sack (T_FRAME_NUM nr, T_LL_UNITDATA_IND *ll_unitdata_ind, T_PDU_TYPE frame_type) { int i, n, bytes; T_FRAME_NUM rn = 0; T_SACK_BITMAP *bm; TRACE_FUNCTION( "irx_handle_sack" ); /* * Extract SACK bitmap and number of Ptr to bits from sdu: */ if (frame_type == I_FRAME) { bm = (T_SACK_BITMAP*)&(ll_unitdata_ind->sdu.buf[ (ll_unitdata_ind->sdu.o_buf >> 3) + 1]); bytes = ll_unitdata_ind->sdu.buf[ (ll_unitdata_ind->sdu.o_buf >> 3)] & 0xF1; } else { bm = (T_SACK_BITMAP*)&(ll_unitdata_ind->sdu.buf[ (ll_unitdata_ind->sdu.o_buf >> 3)]); bytes = ll_unitdata_ind->sdu.l_buf >> 3; } /* * Little Protection */ if ( bytes > S_FRAME_SACK_MAX_CTRL_OCTETS ) { bytes = S_FRAME_SACK_MAX_CTRL_OCTETS; TRACE_ERROR ("Illegal SACK bitmap size received"); } /* * For each bit, which is set, send an acknowledge to ITX */ for (i = 0; i < bytes; i++) { for (n = 7; n >= 0; n--) { /* * first increment rn (must begin with 1) */ rn++; /* * check if bit is set from MSB to LSB */ if ( bm->data[i] & (1 << n) ) { /* * set frame acknowledged */ sig_irx_itx_ack_ind ( TRUE, (T_FRAME_NUM)(nr + rn)); } else { /* * mark frame for retransmission */ sig_irx_itx_ack_ind ( FALSE, (T_FRAME_NUM)(nr + rn)); } } } /* * send L3 data confirmation */ sig_irx_itx_cnf_l3data_req (); /* * Strip SACK bitmap from I frame SDUs to get clean L3 PDU */ if (frame_type == I_FRAME) { ll_unitdata_ind->sdu.o_buf += bytes << 3; ll_unitdata_ind->sdu.l_buf -= bytes << 3; } } /* irx_handle_sack () */ /* +------------------------------------------------------------------------------ | Function : irx_send_ack +------------------------------------------------------------------------------ | Description : This procedure handles the detection of sequence errors and | the sending of appropriate acknowledgements | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_send_ack (T_BIT a_bit) { TRACE_FUNCTION( "irx_send_ack" ); /* * Send S frame depending on last N(S) / V(R) condition */ switch (llc_data->irx->last_ns) { case NS_EQUAL_VR: /* * Send an RR only, if requested */ if (a_bit) { sig_irx_itx_send_rr_req (ABIT_NO_REQ); } else { /* * Trigger ITX to check queue and send frames * This is done inside the other signals, too. */ sig_irx_itx_trigger_ind (); } break; case NS_EQUAL_VR_PLUS_1: /* * Sequence error - one missing */ sig_irx_itx_send_ack_req (ABIT_NO_REQ); break; case NS_NO_SEQUENCE_ERROR: /* * Send an SACK only, if requested */ if (a_bit) { T_SACK_BITMAP bitmap; irx_build_sack_bitmap( &bitmap ); sig_irx_itx_send_sack_req (ABIT_NO_REQ, &bitmap); } else { /* * Trigger ITX to check queue and send frames * This is done inside the other signals, too. */ sig_irx_itx_trigger_ind (); } break; default: /* * Sequence error - one or more missing */ { T_SACK_BITMAP bitmap; irx_build_sack_bitmap( &bitmap ); sig_irx_itx_send_sack_req (ABIT_NO_REQ, &bitmap); } break; } } /* irx_send_ack () */ /* +------------------------------------------------------------------------------ | Function : irx_send_rnr +------------------------------------------------------------------------------ | Description : This procedure sends an RNR to ITX | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void irx_send_rnr () { TRACE_FUNCTION( "irx_send_rnr" ); sig_irx_itx_send_rnr_req (ABIT_NO_REQ); } /* irx_send_rnr() */