FreeCalypso > hg > fc-magnetite
view src/g23m-fad/l2r/l2r_upf.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 | 90eb61ecd093 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : CSD (8411) | Modul : L2r_upf.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 defines the procedures and functions for | the component L2R of the base station +----------------------------------------------------------------------------- */ #ifndef L2R_UPF_C #define L2R_UPF_C #endif #define ENTITY_L2R /*==== INCLUDES ===================================================*/ #include <string.h> #include "typedefs.h" #include "pconst.cdg" #include "vsi.h" #include "macdef.h" #include "custom.h" #include "gsm.h" #include "cus_l2r.h" #include "cnf_l2r.h" #include "mon_l2r.h" #include "prim.h" #include "pei.h" #include "tok.h" #include "dti.h" /* functionality of the dti library */ #include "cl_ribu.h" #include "l2r.h" /*==== CONST =======================================================*/ /*==== TYPES =======================================================*/ /*==== VAR EXPORT ==================================================*/ /*==== VAR LOCAL ===================================================*/ /*==== FUNCTIONS ===================================================*/ /* +------------------------------------------------------------------------------ | Function : up_init +------------------------------------------------------------------------------ | Description : initialise the l2r data for the uplink process | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_init(T_UP *dup) { register ULONG i; TRACE_FUNCTION ("up_init()"); dup->FlowCtrlUsed = FALSE; dup->DnFlow = FL_INACTIVE; dup->UpFlow = FL_INACTIVE; dup->ULFlow = FL_INACTIVE; dup->LLFlow = FL_INACTIVE; dup->MrgFlow = FL_INACTIVE; dup->FlowThreshLo = MAX_UPRIM_RIBU_SIZE/2; dup->FlowThreshHi = 3*MAX_UPRIM_RIBU_SIZE/4; dup->DataSize = 0; dup->FrameSize = 0; dup->OldFrameSize = 0; dup->FramesPerPrim = L2R_FRAMES_PER_PRIM_MAX; dup->LastRcvdSa = 0; dup->LastRcvdSb = 0; dup->LastSentSa = 0; dup->LastSentSb = 0; dup->LastSentFlow = FL_INACTIVE; dup->StoreDataActive = FALSE; dup->UrgentMsg = FALSE; dup->DiscardRemapData = FALSE; dup->QRemapRead = 0; dup->QRemapWrite = 0; dup->BRemapAdr = NULL; dup->BRemapLen = 0; dup->BRemapSa = 0; dup->BRemapSb = 0; dup->BRemapLastState = 0; dup->QRemapPrimDesc.prim = NULL; for (i = 0; i < MAX_UP_REMAP_QUEUE_SIZE; i++) { dup->QRemap[i] = NULL; } for (i = 0; i < UP_REMAP_BUFFER_SIZE; i++) { dup->BRemap[i] = 0; } dup->RiBu.idx.depth = MAX_UPRIM_RIBU_SIZE; INIT_STATE (UP_UL, IW_IDLE); INIT_STATE (UP_LL, ISW_IDLE); INIT_STATE (UP, UP_DISCONNECTED); } /* +------------------------------------------------------------------------------ | Function : up_alloc_prim +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ LOCAL void up_alloc_prim(void) { T_UP *dup = &l2r_data->up; T_PRIM_INDEX m; T_P_UPRIM_DESCRIPTOR primDesc; USHORT sduSize; TRACE_FUNCTION ("up_alloc_prim()"); sduSize = dup->FramesPerPrim * dup->FrameSize * 8; primDesc = dup->RiBu.primDesc[dup->RiBu.alloc]; { PALLOC_SDU(data_req, RLP_DATA_REQ, sduSize); primDesc->prim = data_req; } #ifdef _SIMULATION_ /* Clear SDU for test environment */ { UBYTE *p; UBYTE *pend; p = &primDesc->prim->sdu.buf[0]; pend = p + (sduSize >> 3); while (p < pend) { *p++ = 0; } } #endif primDesc->prim->sdu.o_buf = 0; primDesc->prim->sdu.l_buf = sduSize; primDesc->nFr = dup->FramesPerPrim; primDesc->index = 0; primDesc->offset = 0; primDesc->off_status = 0; primDesc->full = FALSE; primDesc->sa = FL_INACTIVE; primDesc->sb = FL_INACTIVE; /*lint -e416 (Warning -- Likely creation of out-of-bounds) */ for (m = 0; m != dup->FramesPerPrim; m++) { (*primDesc->adr)[m] = (T_P_L2R_FRAME)(primDesc->prim->sdu.buf +L2R_ENCODING_OFFSET + m * dup->FrameSize); } /*lint +e416 (Warning -- Likely creation of out-of-bounds) */ dup->RiBu.alloc++; if (dup->RiBu.alloc EQ dup->RiBu.idx.depth) { dup->RiBu.alloc = 0; } } /* +------------------------------------------------------------------------------ | Function : up_send_prim_timeout +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_send_prim_timeout(void) { T_UP *dup = &l2r_data->up; TRACE_FUNCTION ("up_send_prim_timeout()"); if (!dup->RiBu.idx.filled) { if (dup->RiBu.alloc EQ dup->RiBu.idx.wi) { /* No primitive is there, so we allocate one */ up_alloc_prim(); } /* No primitive is ready, so we take one away from the relay entity */ cl_ribu_write_index(&dup->RiBu.idx); /* point to next primitive */ } up_send_current_prim(); } /* +------------------------------------------------------------------------------ | Function : up_next_remap_frame +------------------------------------------------------------------------------ | Description : Local function, which is used by up_copy_data_from_l2r | to advance to the next frame in the primitive. | The variable primDesc of the calling function is updated. | | Parameters : primDesc - | | Return : 1 - | 0 - +------------------------------------------------------------------------------ */ LOCAL UBYTE up_next_remap_frame(T_RPRIM_DESCRIPTOR *primDesc) { T_UP *dup = &l2r_data->up; U8 i; T_P_RLP_REMAP_DATA_IND prim; /* next frame */ primDesc->index++; if (primDesc->index >= primDesc->nFr) { /* primitive is completely read out */ PFREE(dup->QRemap [dup->QRemapRead]); /* next primitive */ (dup->QRemapRead)++; if (dup->QRemapRead >= MAX_UP_REMAP_QUEUE_SIZE) { dup->QRemapRead = 0; } if (dup->QRemapRead EQ dup->QRemapWrite) { /* no primitive is ready */ primDesc->prim = NULL; return (1); } /* point to next primitive descriptor */ prim = dup->QRemap[dup->QRemapRead]; primDesc->prim = prim; primDesc->nFr = prim->sdu.l_buf / (8 * prim->data_size + HT_LEN); primDesc->index = 0; for (i = 0; i < primDesc->nFr; i++) { primDesc->adr[i] = (T_P_L2R_FRAME)(prim->sdu.buf + (prim->sdu.o_buf>>3) + HEADER_LEN + i * (prim->data_size + HT_LEN)); } } primDesc->offset = 0; primDesc->off_status = 0; return (0); } /* +------------------------------------------------------------------------------ | Function : up_copy_data_from_rq +------------------------------------------------------------------------------ | Description : | | Parameters : buf - | len - | sa - | sb - | bytesCopied - | | Return : - +------------------------------------------------------------------------------ */ LOCAL void up_copy_data_from_rq(U8 *buf, U16 len, U8 *sa, U8 *sb, U16 *bytesCopied) { T_UP *dup = &l2r_data->up; register ULONG i; register T_P_UBYTE pFrame; register T_P_UBYTE pBuf; register T_P_UBYTE pStat; T_P_RLP_REMAP_DATA_IND prim; T_P_L2R_FRAME frame; T_P_UBYTE pEnd; USHORT bytesToCopy; USHORT blocklen; UBYTE statOct; UBYTE lastState; T_RPRIM_DESCRIPTOR *primDesc = &dup->QRemapPrimDesc; #ifdef _SIMULATION_ TRACE_FUNCTION ("up_copy_data_from_rq()"); #endif bytesToCopy = len; if (primDesc->prim EQ NULL) { prim = dup->QRemap[dup->QRemapRead]; primDesc->prim = prim; primDesc->nFr = prim->sdu.l_buf / ((prim->data_size<<3) + HT_LEN); primDesc->index = 0; primDesc->offset = 0; primDesc->off_status = 0; for (i = 0; i < primDesc->nFr; i++) { primDesc->adr[i] = (T_P_L2R_FRAME)(prim->sdu.buf + (prim->sdu.o_buf>>3) + HEADER_LEN + i * (prim->data_size + HT_LEN)); } } /* skip empty primitive */ if (primDesc->nFr EQ 0) { *bytesCopied = 0; return; } frame = primDesc->adr[primDesc->index]; /* point to current l2r frame in primitive */ pBuf = buf; /* point to destination buffer */ pFrame = &((*frame)[primDesc->offset]); pStat = &((*frame)[primDesc->off_status]); if (pFrame EQ pStat) { /* current byte is status octet */ dup->BRemapLastState = *pFrame & SO_STATUS_BITS_MASK; } lastState = dup->BRemapLastState; *sa = GET_SO_SA_BIT(lastState); *sb = GET_SO_SB_BIT(lastState); /************************************************************************************ * loop until either * - no more data are available or * - status in L2R frame changes or * - buffer for data is full ************************************************************************************/ for (;;) { #ifdef _SIMULATION_ TRACE_FUNCTION ("loop"); #endif blocklen = pStat - pFrame; if (blocklen EQ 0) { /* * current byte is status octet * (only in the first pass of the loop, there may be no status octet) */ /***************************** * evaluate status bits *****************************/ statOct = *pFrame; if (lastState NEQ (statOct & SO_STATUS_BITS_MASK)) { /* * status has changed. We have to stop, * since only one state can be transmitted to the upper layer */ primDesc->offset = primDesc->off_status = pFrame - (T_P_UBYTE)frame; *bytesCopied = len - bytesToCopy; return; } pFrame++; /************************************ * evaluate addrss bits ************************************/ statOct &= SO_ADR_MASK; switch (statOct) { case SO_BREAK_ACK: case SO_BREAK_REQ: case SO_END_EMPTY: /* no more data in this frame */ if (up_next_remap_frame(primDesc) EQ 1) { /* no more data available */ *bytesCopied = len - bytesToCopy; /* this much data could be copied */ return; } frame = primDesc->adr[primDesc->index]; pFrame = (T_P_UBYTE)frame; pStat = (T_P_UBYTE)frame; continue; /* continue with next frame */ case SO_END_FULL: pStat = &((*frame)[primDesc->prim->data_size]); blocklen = pStat - pFrame; break; case SO_TWO_OCTET: blocklen = *pFrame++ & SO_ADR_MASK_TWO_OCT; pStat = pFrame + blocklen; break; default: blocklen = statOct; pStat = pFrame + blocklen; break; } } if (bytesToCopy < blocklen) { /*************************************** * There is not enough space in the * buffer to copy the complete block ***************************************/ pEnd = pFrame + bytesToCopy; while (pFrame < pEnd) { *pBuf++ = *pFrame++; } if (pFrame EQ &((*frame)[primDesc->prim->data_size])) { /* end of frame reached */ up_next_remap_frame(primDesc); } else { primDesc->offset = pFrame - (T_P_UBYTE)frame; primDesc->off_status = pStat - (T_P_UBYTE)frame; } *bytesCopied = len; /* this much data could be copied */ return; } else { /*************************************** * Copy the complete block ***************************************/ bytesToCopy -= blocklen; while (pFrame < pStat) { *pBuf++ = *pFrame++; } if (pFrame EQ &((*frame)[primDesc->prim->data_size])) { /* end of frame reached */ if (up_next_remap_frame(primDesc) EQ 1) { /* no more data available */ *bytesCopied = len - bytesToCopy; /* this much data could be copied */ return; } frame = primDesc->adr[primDesc->index]; pFrame = (T_P_UBYTE)frame; pStat = (T_P_UBYTE)frame; } if (bytesToCopy EQ 0) { primDesc->offset = pFrame - (T_P_UBYTE)frame; primDesc->off_status = pStat - (T_P_UBYTE)frame; *bytesCopied = len; /* this much data could be copied */ return; } } } } /* +------------------------------------------------------------------------------ | Function : up_fill_in_status_octet +------------------------------------------------------------------------------ | Description : local function, which is used patch a status octet into a | l2r frame. This function takes into acount the two octet | format for 14400. | | Parameters : pFrame - points to begin of l2r frame | offstat1 - offset of status octet to be patched | offstat2 - offset of next status octet | | Return : +------------------------------------------------------------------------------ */ LOCAL BOOL up_fill_in_status_octet(T_P_UBYTE pFrame, UBYTE offstat1, UBYTE offstat2) { register T_P_UBYTE pStat, pSrc, pDes, pEnd; register UBYTE dataLen; dataLen = offstat2 - offstat1 - 1; /* number of data bytes between status octets */ pStat = pFrame + offstat1; if (dataLen <= DATA_SIZE_SHORT-2) { *pStat |= dataLen; return (FALSE); } else { /* this is only possible with 14400 */ if (offstat2 < DATA_SIZE_LONG - 1) { /* a two octet status must be inserted */ pSrc = pFrame + offstat2; pDes = pSrc + 1; pEnd = pFrame + offstat1; while (pSrc > pEnd) { *--pDes = *--pSrc; } *pStat |= SO_TWO_OCTET; pStat++; *pStat = dataLen; } else { /* a additional status octet (FULL) must be inserted somewhere in the frame */ pSrc = pFrame + offstat2; pDes = pSrc + 1; pEnd = pFrame + offstat1 + DATA_SIZE_SHORT - 1; while (pSrc > pEnd) { *--pDes = *--pSrc; } *pStat |= DATA_SIZE_SHORT - 2; *pEnd = *pStat & SO_STATUS_BITS_MASK | SO_END_FULL; } return (TRUE); } } /* +------------------------------------------------------------------------------ | Function : up_next_frame +------------------------------------------------------------------------------ | Description : local function, which is used by up_copy_data_into_l2r to | advance to the next frame in the primitive | The variables primDesc, frame and pFrame of the calling function | are updated. Moreover the return values of the calling function | primToSend and bytesCopied are set. | | | Parameters : primDesc - | primToSend - | | Return : +------------------------------------------------------------------------------ */ LOCAL UBYTE up_next_frame(T_P_UPRIM_DESCRIPTOR *primDesc, BOOL *primToSend) { T_UP *dup = &l2r_data->up; TRACE_FUNCTION("up_next_frame()"); (*primDesc)->index++; (*primDesc)->offset = 0; if ((*primDesc)->index >= dup->FramesPerPrim) /* primitive is filled */ { (*primDesc)->full = TRUE; *primToSend = TRUE; cl_ribu_write_index(&dup->RiBu.idx); /* point to next primitive */ if (dup->RiBu.alloc EQ dup->RiBu.idx.wi) { /* no primitive is ready */ return (1); } /* point to next primitive descriptor */ *primDesc = dup->RiBu.primDesc[dup->RiBu.idx.wi]; (*primDesc)->index = 0; } return (0); } LOCAL void up_copy_data_into_l2r(U8 *buf, U16 len, U8 sa, U8 sb, U8 x, BOOL *primToSend, U16 *bytesCopied) { T_UP *dup = &l2r_data->up; T_P_UPRIM_DESCRIPTOR primDesc; T_P_L2R_FRAME frame; register T_P_UBYTE pFrame; register T_P_UBYTE pEnd; register T_P_UBYTE pBuf; USHORT bytesToCopy; UBYTE frameCount; T_FLOW flow = FL_INVALID; #ifdef _SIMULATION_ TRACE_FUNCTION ("up_copy_data_into_l2r()"); #endif switch (x) { case DTI_FLOW_ON: flow = FL_INACTIVE; break; case DTI_FLOW_OFF: flow = FL_ACTIVE; break; } #ifdef _TARGET_ if (dup->DataSize > DATA_SIZE_SHORT) { frameCount = 1; } else { frameCount = 2; } #else { frameCount = 100; } #endif up_store_status(sa, sb, flow); if (dup->LastSentFlow EQ dup->MrgFlow) { *primToSend = FALSE; } else { *primToSend = TRUE; } /* don't copy into primitive if no primitive is ready */ if (dup->RiBu.alloc EQ dup->RiBu.idx.wi) { *bytesCopied = 0; return; } bytesToCopy = len; primDesc = dup->RiBu.primDesc[dup->RiBu.idx.wi]; /* point to current primitive descriptor */ frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */ pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */ pBuf = buf; /* point to source buffer */ /************************************************************************************ * * Handle a partly filled frame, which has been written in the primitive previously * ************************************************************************************/ if (primDesc->offset NEQ 0) { /* partly filled frame is there */ if (bytesToCopy EQ 0) /* no data to copy -> quit without writing status octet */ { *bytesCopied = len; return; } if (sa NEQ primDesc->sa OR sb NEQ primDesc->sb) { /* * status has changed since last time */ /* finish previous status octet */ if ( up_fill_in_status_octet( (T_P_UBYTE)frame, primDesc->off_status, primDesc->offset ) ) { /* frame data has been moved to make space for two octet status */ pFrame++; (primDesc->offset)++; if (primDesc->offset >= (dup->DataSize)) { /* frame is just filled by patching the previous status frame */ if (up_next_frame(&primDesc, primToSend) EQ 1) { /* no more space for data */ *bytesCopied = 0; /* no data could be copied */ return; } frameCount--; #ifdef _TARGET_ if (frameCount EQ 0) { *bytesCopied = 0; /* no data could be copied */ return; } #endif frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */ pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */ } } if (primDesc->offset NEQ 0) { /* write status octet */ *pFrame++ = (U8)(sa << SO_SA_BIT | sb << SO_SB_BIT | 0 << SO_X_BIT); /* x is set to 0 (inactive) by default */ /* store current status for next call */ primDesc->sa = sa; primDesc->sb = sb; primDesc->off_status = primDesc->offset; (primDesc->offset)++; if (primDesc->offset >= (dup->DataSize)) { /* frame is just filled by the status octet */ /* finish previous status octet */ (*frame)[primDesc->off_status] |= SO_END_EMPTY; if (up_next_frame(&primDesc, primToSend) EQ 1) { /* no more space for data */ *bytesCopied = 0; /* no data could be copied */ return; } frameCount--; if (frameCount EQ 0) { *bytesCopied = 0; /* no data could be copied */ return; } frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */ pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */ } } } /* * write data into partly filled frame */ if (primDesc->offset NEQ 0) { if (bytesToCopy >= dup->DataSize - primDesc->offset) { /* enough data to fill frame completly */ for (pEnd = pFrame + dup->DataSize - primDesc->offset; pFrame < pEnd; ) { *pFrame++ = *pBuf++; } /* finish previous status octet */ (*frame)[primDesc->off_status] |= SO_END_FULL; bytesToCopy -= dup->DataSize - primDesc->offset; if (up_next_frame(&primDesc, primToSend) EQ 1) { /* no more space for data */ *bytesCopied = len - bytesToCopy; /* this much data could be copied */ return; } frameCount--; if (frameCount EQ 0) { *bytesCopied = len - bytesToCopy; /* this much data could be copied */ return; } frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */ pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */ } else { /* not enough data to fill frame completly */ for (pEnd = pFrame + bytesToCopy; pFrame < pEnd; ) { *pFrame++ = *pBuf++; } primDesc->offset += bytesToCopy; *bytesCopied = len; return; /* Nothing else to do */ } } } /************************************************************************************ * * Handle consecutive frames, which are filled starting with byte 0 * ************************************************************************************/ while (bytesToCopy > 0) { if (bytesToCopy >= dup->DataSize - 1) { /* * There are enough data to fill a frame completely */ *pFrame++ = sa << SO_SA_BIT | sb << SO_SB_BIT | 0 << SO_X_BIT | SO_END_FULL; /* x is set to 0 (inactive) by default */ /* store current status for next call */ primDesc->sa = sa; primDesc->sb = sb; for (pEnd = pFrame + dup->DataSize - 1; pFrame < pEnd; ) { *pFrame++ = *pBuf++; } bytesToCopy -= dup->DataSize - 1; /* advance to next frame */ if (up_next_frame(&primDesc, primToSend) EQ 1) { /* running out of primitives */ *bytesCopied = len - bytesToCopy; /* this much data could be copied */ return; } frameCount--; if (frameCount EQ 0) { *bytesCopied = len - bytesToCopy; /* this much data could be copied */ return; } frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */ pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */ } else { /* * There are some data, but not enough to fill a frame completely */ *pFrame++ = (U8)(sa << SO_SA_BIT | sb << SO_SB_BIT | 0 << SO_X_BIT); /* x is set to 0 (inactive) by default */ /* store current status for next call */ primDesc->sa = sa; primDesc->sb = sb; for (pEnd = pFrame + bytesToCopy; pFrame < pEnd; ) { *pFrame++ = *pBuf++; } primDesc->off_status = 0; primDesc->offset = bytesToCopy + 1; bytesToCopy = 0; } } *bytesCopied = len; } /* +------------------------------------------------------------------------------ | Function : up_copy_remap_data +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ LOCAL void up_copy_remap_data(void) { T_UP *dup = &l2r_data->up; USHORT bytesCopied; BOOL dummy; #ifdef _SIMULATION_ TRACE_FUNCTION ("up_copy_remap_data()"); #endif do { if (dup->BRemapLen EQ 0) { dup->BRemapAdr = dup->BRemap; up_copy_data_from_rq ( dup->BRemapAdr, UP_REMAP_BUFFER_SIZE, &dup->BRemapSa, &dup->BRemapSb, &dup->BRemapLen ); if (dup->BRemapLen EQ 0) { up_check_flow(); return; } } up_copy_data_into_l2r ( dup->BRemapAdr, dup->BRemapLen, dup->BRemapSa, dup->BRemapSb, DTI_FLOW_OFF, &dummy, &bytesCopied ); dup->BRemapAdr += bytesCopied; dup->BRemapLen -= bytesCopied; } while (bytesCopied NEQ 0); } /* +------------------------------------------------------------------------------ | Function : up_check_alloc +------------------------------------------------------------------------------ | Description : This procedure allocates new primitives until there are | UP_RIBU_PREALLOC primitives ready. | | I.e.: alloc = write + UP_RIBU_PREALLOC | | It may be less than this, if otherwise the alloc pointer | would reach the read pointer. | | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_check_alloc(void) { T_UP *dup = &l2r_data->up; S8 i_from, i_to; TRACE_FUNCTION ("up_check_alloc()"); i_to = dup->RiBu.idx.ri - dup->RiBu.idx.wi - 1; if (i_to < 0) { i_to = i_to + dup->RiBu.idx.depth; } if (i_to > UP_RIBU_PREALLOC) { i_to = UP_RIBU_PREALLOC; } i_from = dup->RiBu.alloc - dup->RiBu.idx.wi; if (i_from < 0) { i_from = i_from + dup->RiBu.idx.depth; } if (i_from >= i_to) { return; } do { up_alloc_prim(); i_from++; } while (i_from < i_to); if (dup->QRemapRead NEQ dup->QRemapWrite) { up_copy_remap_data(); return; } switch (GET_STATE (UP_UL)) { case IW_WAIT: break; case IW_IDLE: if (dup->StoreDataActive EQ FALSE AND dup->Prim NEQ NULL) { up_store_data(); } break; } } /* +------------------------------------------------------------------------------ | Function : up_check_flow +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_check_flow(void) { T_UP *dup = &l2r_data->up; U8 primCount; TRACE_FUNCTION ("up_check_flow()"); if (!dup->FlowCtrlUsed) { return; } primCount = dup->RiBu.idx.filled; switch (dup->UpFlow) { case FL_ACTIVE: if (primCount < dup->FlowThreshLo) { dup->UpFlow = FL_INACTIVE; } else { return; } break; case FL_INACTIVE: if (primCount >= dup->FlowThreshHi) { dup->UpFlow = FL_ACTIVE; } else { return; } break; } sig_up_dn_flow(dup->UpFlow); } /* +------------------------------------------------------------------------------ | Function : up_store_data +------------------------------------------------------------------------------ | Description : This procedure copies data from a dti_data_req primitive | into the uplink ring buffer. | | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_store_data(void) { T_UP *dup = &l2r_data->up; T_P_UBYTE adr; USHORT len; BOOL primToSend; USHORT bytesCopied; USHORT i, j; T_desc2 *desc; TRACE_FUNCTION ("up_store_data()"); dup->StoreDataActive = TRUE; do { desc = (T_desc2*)dup->Prim->desc_list2.first; if (desc) { len = desc->len; adr = desc->buffer; } else { len = 0; adr = NULL; } up_copy_data_into_l2r (adr, len, dup->Prim->parameters.st_lines.st_line_sa, dup->Prim->parameters.st_lines.st_line_sb, dup->Prim->parameters.st_lines.st_flow, &primToSend, &bytesCopied); dup->Prim->desc_list2.list_len -= bytesCopied; if (desc) { if ((bytesCopied EQ len)) { /* * Block has been copied successfully */ dup->Prim->desc_list2.first = desc->next; MFREE (desc); } else if (bytesCopied > 0) { /* * remaining data must be copied to begin of block */ /*lint -e{661} (Warning -- Likely creation of out-of-bounds) */ for (i=0, j = bytesCopied; j < len; i++, j++) { desc->buffer[i] = desc->buffer[j]; } desc->len -= bytesCopied; } } up_check_alloc(); } while (dup->Prim->desc_list2.first NEQ 0 AND dup->RiBu.alloc NEQ dup->RiBu.idx.wi); if (dup->Prim->desc_list2.first EQ 0) { PFREE (dup->Prim); dup->Prim = NULL; up_send_ready(); } dup->StoreDataActive = FALSE; } /* +------------------------------------------------------------------------------ | Function : up_send_ready +------------------------------------------------------------------------------ | Description : only used in test environment | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_send_ready(void) { TRACE_FUNCTION ("up_send_ready()"); if (GET_STATE (UP_UL) EQ IW_IDLE) { if (l2r_data->up.DtiConnected EQ FALSE) { TRACE_EVENT("DTI not connected, but up_send_ready() called -> break"); return; /* jk: DTI_READY_IND primitive cannot be sent when DTI disconnected (!) */ } dti_start ( l2r_hDTI, L2R_DTI_UP_DEF_INSTANCE, L2R_DTI_UP_INTERFACE, L2R_DTI_UP_CHANNEL ); SET_STATE (UP_UL, IW_WAIT); } } LOCAL void clear_primDesc(T_P_UPRIM_DESCRIPTOR primDesc) { primDesc->prim = NULL; primDesc->nFr = 0; primDesc->index = 0; primDesc->offset = 0; primDesc->off_status = 0; primDesc->full = FALSE; primDesc->sa = FL_INACTIVE; primDesc->sb = FL_INACTIVE; } /* +------------------------------------------------------------------------------ | Function : up_free_prim +------------------------------------------------------------------------------ | Description : | | Parameters : primDesc | | | Return : - +------------------------------------------------------------------------------ */ LOCAL void up_free_prim(T_P_UPRIM_DESCRIPTOR primDesc) { TRACE_FUNCTION ("up_free_prim()"); if (primDesc->prim NEQ NULL) { PFREE (primDesc->prim); clear_primDesc(primDesc); } } /* +------------------------------------------------------------------------------ | Function : up_deinit_ribu +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_deinit_ribu(void) { T_UP *dup = &l2r_data->up; T_PRIM_DESC_RIBU_INDEX n; T_P_UPRIM_DESCRIPTOR primDesc; TRACE_FUNCTION ("up_deinit_ribu()"); for (n = 0; n < dup->RiBu.idx.depth; n++) { primDesc = dup->RiBu.primDesc[n]; if (primDesc->prim NEQ NULL) { up_free_prim(primDesc); } } if (GET_STATE (UP_LL) EQ ISW_SEND) { SET_STATE (UP_LL, ISW_IDLE); } } /* +------------------------------------------------------------------------------ | Function : up_send_status +------------------------------------------------------------------------------ | Description : | | Parameters : sa - | sb - | flow - | adr - | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_send_status ( T_BIT sa, T_BIT sb, T_FLOW flow, UBYTE adr ) { T_UP *dup = &l2r_data->up; T_P_UPRIM_DESCRIPTOR primDesc; T_P_L2R_FRAME frame; T_BIT x = 0; TRACE_FUNCTION ("up_send_status()"); primDesc = dup->RiBu.primDesc[dup->RiBu.idx.wi]; frame = (*primDesc->adr)[0]; switch (flow) { case FL_ACTIVE: x = 1; break; case FL_INACTIVE: x = 0; break; } (*frame)[0] = sa << SO_SA_BIT | sb << SO_SB_BIT | x << SO_X_BIT | adr; /* jk:030501 - TEST CASE 251 - new funktion parameter 'adr' was introduced in order to cancel the older function 'up_send_break(...)' */ primDesc->sa = sa; /* the status has to be saved in order to be correctly stored later */ primDesc->sb = sb; /* on into "dup->LastSentSa/Sb" [up_send current_prim()] */ primDesc->index = 1; primDesc->offset = 0; cl_ribu_write_index(&dup->RiBu.idx); /* point to next primitive */ } /* +------------------------------------------------------------------------------ | Function : up_set_flow_in_prim +------------------------------------------------------------------------------ | Description : | | Parameters : prim - | | | Return : - +------------------------------------------------------------------------------ */ LOCAL void up_set_flow_in_prim(T_P_RLP_DATA_REQ prim) { T_UP *dup = &l2r_data->up; if (dup->MrgFlow EQ FL_INACTIVE) { TRACE_FUNCTION ("up_set_flow_in_prim(INACTIVE)"); } else { T_PRIM_INDEX frames; T_PRIM_INDEX ind; UBYTE off; register UBYTE statOct; T_P_L2R_FRAME frame; TRACE_FUNCTION ("up_set_flow_in_prim(ACTIVE)"); frames = prim->sdu.l_buf / (8 * dup->FrameSize); frame = (T_P_L2R_FRAME) (prim->sdu.buf + (prim->sdu.o_buf / 8) + HEADER_LEN); off = 0; ind = 0; while (ind < frames) { statOct = (*frame)[off]; SET_BIT(statOct, SO_X_BIT); (*frame)[off] = statOct; switch (statOct & SO_ADR_MASK) { case SO_BREAK_REQ: case SO_BREAK_ACK: case SO_END_EMPTY: case SO_END_FULL: ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + dup->FrameSize); off = 0; break; case SO_TWO_OCTET: off++; off += ((*frame)[off] & SO_ADR_MASK_TWO_OCT) + 1; if (off >= dup->DataSize) { ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + dup->FrameSize); off = 0; } break; default: off += (statOct & SO_ADR_MASK) + 1; if (off >= dup->DataSize) { ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + dup->FrameSize); off = 0; } break; } } } dup->LastSentFlow = dup->MrgFlow; } /* +------------------------------------------------------------------------------ | Function : up_send_current_prim +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_send_current_prim(void) { T_UP *dup = &l2r_data->up; T_P_UPRIM_DESCRIPTOR primDesc = dup->RiBu.primDesc[dup->RiBu.idx.ri]; TRACE_FUNCTION ("up_send_current_prim()"); if (!primDesc->full AND primDesc->index < primDesc->nFr) { TRACE_FUNCTION ("prim is not full"); if (primDesc->offset > 0) { if (up_fill_in_status_octet((T_P_UBYTE)(*primDesc->adr)[primDesc->index], primDesc->off_status, primDesc->offset)) { primDesc->offset++; if (primDesc->offset >= dup->DataSize) { primDesc->offset = 0; primDesc->index++; } } } if (primDesc->offset > 0 OR primDesc->index EQ 0) { /* * Add status octet, if there is a partly filled frame * or if status has changed since last write */ (*(*primDesc->adr)[primDesc->index])[primDesc->offset] = dup->LastRcvdSa << SO_SA_BIT | dup->LastRcvdSb << SO_SB_BIT | 0 << SO_X_BIT | SO_END_EMPTY; primDesc->sa = dup->LastRcvdSa; primDesc->sb = dup->LastRcvdSb; primDesc->index++; } primDesc->prim->sdu.l_buf = primDesc->index * dup->FrameSize * 8; } dup->LastSentSa = primDesc->sa; dup->LastSentSb = primDesc->sb; up_set_flow_in_prim(primDesc->prim); PSENDX (RLP, primDesc->prim); clear_primDesc(primDesc); /* this primitive doesn't belong to us any longer */ cl_ribu_read_index(&dup->RiBu.idx); /* point to next primitive */ dup->UrgentMsg = FALSE; up_check_alloc(); up_check_flow(); } /* +------------------------------------------------------------------------------ | Function : up_send_prim_cond +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_send_prim_cond(void) { TRACE_FUNCTION ("up_send_prim_cond()"); switch (GET_STATE (UP_LL)) { case ISW_WAIT: TIMERSTOP (TIMER_TUP_SND); up_send_current_prim(); SET_STATE (UP_LL, ISW_IDLE); break; default: l2r_data->up.UrgentMsg = TRUE; up_check_flow(); up_check_alloc(); SET_STATE (UP_LL, ISW_SEND); break; } } /* +------------------------------------------------------------------------------ | Function : up_init_ribu +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_init_ribu(void) { T_UP *dup = &l2r_data->up; T_PRIM_DESC_RIBU_INDEX n; T_PRIM_INDEX m; TRACE_FUNCTION ("up_init_ribu()"); dup->RiBu.alloc = 0; cl_ribu_init(&dup->RiBu.idx, dup->RiBu.idx.depth); for (n = 0; n < dup->RiBu.idx.depth; n++) { dup->RiBu.primDesc[n] = &(dup->PrimDesc[n]); dup->PrimDesc[n].nFr = 0; dup->PrimDesc[n].adr = (T_P_ADR_VECTOR)&(dup->AdrVec[n]); dup->PrimDesc[n].index = 0; dup->PrimDesc[n].offset = 0; dup->PrimDesc[n].off_status = 0; dup->PrimDesc[n].full = FALSE; dup->PrimDesc[n].sa = FL_INACTIVE; dup->PrimDesc[n].sb = FL_INACTIVE; dup->PrimDesc[n].prim = NULL; for(m = 0;m < L2R_FRAMES_PER_PRIM_MAX; m++) { dup->AdrVec[n][m] = NULL; } if (dup->RiBu.alloc < UP_RIBU_PREALLOC) { up_alloc_prim(); } } } /* +------------------------------------------------------------------------------ | Function : up_store_status +------------------------------------------------------------------------------ | Description : | | Parameters : sa | sb | flow | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_store_status ( T_BIT sa, T_BIT sb, T_FLOW flow ) { T_UP *dup = &l2r_data->up; #ifdef _SIMULATION_ TRACE_FUNCTION ("up_store_status()"); #endif dup->LastRcvdSa = sa; dup->LastRcvdSb = sb; if (dup->FlowCtrlUsed EQ FALSE OR flow EQ dup->ULFlow) { return; } dup->ULFlow = flow; up_merge_flow(); sig_up_dn_ul_flow(dup->ULFlow); } /* +------------------------------------------------------------------------------ | Function : up_send_empty_frame +------------------------------------------------------------------------------ | Description : | | Parameters : sa - | sb - | flow - | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_send_empty_frame(T_BIT sa, T_BIT sb, T_FLOW flow) { T_UP *dup = &l2r_data->up; T_BIT x = 0; USHORT sduSize = dup->FrameSize << 3; PALLOC_SDU(data_req, RLP_DATA_REQ, sduSize); TRACE_FUNCTION ("up_send_empty_frame()"); #ifdef _SIMULATION_ /* Clear SDU for test environment */ { UBYTE *p; UBYTE *pend; p = &data_req->sdu.buf[0]; pend = p + dup->FrameSize; while (p < pend) { *p++ = 0; } } #endif data_req->sdu.o_buf = 0; data_req->sdu.l_buf = sduSize; switch (flow) { case FL_ACTIVE: x = 1; break; case FL_INACTIVE: x = 0; break; } /*lint -e416 (Warning -- Likely creation of out-of-bounds pointer) */ /*lint -e415 (Warning -- Likely access of out-of-bounds pointer) */ data_req->sdu.buf[L2R_ENCODING_OFFSET] = sa << SO_SA_BIT | sb << SO_SB_BIT | x << SO_X_BIT | SO_END_EMPTY; /*lint +e416 (Warning -- Likely creation of out-of-bounds pointer) */ /*lint +e415 (Warning -- Likely access of out-of-bounds pointer) */ dup->LastSentFlow = flow; dup->LastSentSa = sa; dup->LastSentSb = sb; PSENDX (RLP, data_req); } /* +------------------------------------------------------------------------------ | Function : up_merge_flow +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_merge_flow(void) { T_UP *dup = &l2r_data->up; #ifdef _SIMULATION_ TRACE_FUNCTION ("up_merge_flow()"); #endif if (dup->FlowCtrlUsed AND (dup->DnFlow EQ FL_ACTIVE OR dup->ULFlow EQ FL_ACTIVE)) { /* flow control active */ dup->MrgFlow = FL_ACTIVE; } else { /* flow control inactive */ dup->MrgFlow = FL_INACTIVE; } } /* +------------------------------------------------------------------------------ | Function : up_rq_init +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void up_rq_init(void) { #ifdef _SIMULATION_ TRACE_FUNCTION ("up_rq_init()"); #endif l2r_data->up.QRemapWrite = 0; l2r_data->up.QRemapRead = 0; } /* +------------------------------------------------------------------------------ | Function : up_some_data_to_send +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : TRUE - | FALSE - +------------------------------------------------------------------------------ */ GLOBAL BOOL up_some_data_to_send(void) { T_UP *dup = &l2r_data->up; #ifdef _SIMULATION_ TRACE_EVENT ("check if any data to send"); #endif if ( dup->RiBu.idx.filled OR (dup->RiBu.primDesc[dup->RiBu.idx.ri]->index > 0) OR (dup->RiBu.primDesc[dup->RiBu.idx.ri]->offset > 0) OR (dup->LastRcvdSa NEQ dup->LastSentSa) OR (dup->LastRcvdSb NEQ dup->LastSentSb) ) { return (TRUE); } return (FALSE); }