view src/g23m-fad/rlp/rlp_rbm.c @ 304:58c7961bd0b0 default tip

TCH tap: extend DL sniffing feature to support CSD modes Our debug feature for TCH DL sniffing reads the content of the DSP's a_dd_0 buffer (or a_dd_1 for TCH/H subchannel 1) at appropriate times and forwards captured bits to the host. This feature was originally implemented for TCH/FS, TCH/EFS and TCH/HS - now extend it to cover TCH/F data modes too.
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 25 Nov 2024 23:33:27 +0000
parents fa8dc04885d8
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  CSD (8411)
|  Modul   :  Rlp_rbm.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 receive buffer manager for
|             the component Radio Link Protocol of the base station
+----------------------------------------------------------------------------- 
*/ 

#ifndef RLP_RBM_C
#define RLP_RBM_C
#endif

#define ENTITY_RLP

/*==== INCLUDES ===================================================*/

#include <string.h>
#include "typedefs.h"
#include "vsi.h"
#include "custom.h"
#include "gsm.h"
#include "cus_rlp.h"
#include "prim.h"
#include "tok.h"
#include "rlp.h"

/*==== CONST =======================================================*/

/*==== TYPES =======================================================*/

/*==== VAR EXPORT ==================================================*/

/*==== VAR LOCAL ===================================================*/

/*==== FUNCTIONS ===================================================*/

/*
+------------------------------------------------------------------------------
|  Function    : rbmi_alloc_curr_prim
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


LOCAL void rbmi_alloc_curr_prim
           (
             void
           )
{
  USHORT sduSize = rlp_data->rbm.FramesPerPrim
                 * rlp_data->rbm.FrameSize * 8;

  PALLOC_SDU
  (
    rlp_data_ind,
    RLP_DATA_IND,
    sduSize
  );

  TRACE_FUNCTION ("rbmi_alloc_curr_prim()");

  rlp_data_ind->sdu.l_buf
    = rlp_data->rbm.FramesPerPrim * rlp_data->rbm.FrameSize * 8;

  rlp_data_ind->data_size = rlp_data->rbm.FrameSize - HEADER_LEN - TRAILER_LEN;

  rlp_data->rbm.CurrPrim    = rlp_data_ind;
  rlp_data->rbm.CurrPrimCou = 0;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbmi_pq_enq
+------------------------------------------------------------------------------
|  Description : A primitive is put into the primitive queue. This is done
|                in rbm_buffer_all_in_sequence_frames when the current
|                primitive is filled up.
|
|
|  Parameters  : prim -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


LOCAL void rbmi_pq_enq
           (
             T_RBM_PRIM *prim
           )
{
  TRACE_FUNCTION ("rbmi_pq_enq()");

  rlp_data->rbm.PQ_Array[rlp_data->rbm.PQ_Write] = prim;

  rlp_data->rbm.PQ_Write = (rlp_data->rbm.PQ_Write+1) % RBM_PQ_SIZE;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbmi_copy_frame_to_sdu
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : frame -
|                sdu   -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


LOCAL void rbmi_copy_frame_to_sdu(T_RBM_FRAMEPTR frame, T_sdu *sdu)
{
  TRACE_FUNCTION ("rbmi_copy_frame_to_sdu()");

  memcpy(sdu->buf+(sdu->o_buf>>3), frame, rlp_data->rbm.FrameSize);

  sdu->o_buf += rlp_data->rbm.FrameSize * 8;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbmi_buffer_frame
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : fromSlot     -
|                primIsReady  -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


LOCAL void rbmi_buffer_frame
           (
             T_RBM_BUFFER_EXTIDX  fromSlot,
             BOOL                *primIsReady
           )
{
  TRACE_FUNCTION ("rbmi_buffer_frame()");

  rbmi_copy_frame_to_sdu
  (
    rlp_data->rbm.Slot[fromSlot].Frame,
    &rlp_data->rbm.CurrPrim->sdu
  );

  if (++rlp_data->rbm.CurrPrimCou EQ rlp_data->rbm.FramesPerPrim)
  {
    rlp_data->rbm.CurrPrim->sdu.o_buf = 0;
    rbmi_pq_enq (rlp_data->rbm.CurrPrim);
    rbmi_alloc_curr_prim ();
    *primIsReady = TRUE;
  }
}


/*
+------------------------------------------------------------------------------
|  Function    : rbmi_pq_deq
+------------------------------------------------------------------------------
|  Description :  A rlp_data_ind primitive is taken from the queue. This
|                 is done when the queue is not empty and a RLP_GETDATA_REQ
|                 is executed. Of after storing a primitive in the queue,
|                 when the upper layer is waiting for data.
|
|  Parameters  : prim  -
|
|
|  Return      : TRUE  -
|                FALSE -
+------------------------------------------------------------------------------
*/


LOCAL BOOL rbmi_pq_deq
           (
             T_RBM_PRIM **prim
           )
{
  TRACE_FUNCTION ("rbmi_pq_deq()");

  if (rlp_data->rbm.PQ_Read NEQ rlp_data->rbm.PQ_Write)
  {
    *prim = rlp_data->rbm.PQ_Array[rlp_data->rbm.PQ_Read];
    rlp_data->rbm.PQ_Array[rlp_data->rbm.PQ_Read] = (T_RBM_PRIM *) NULL;

    rlp_data->rbm.PQ_Read = (rlp_data->rbm.PQ_Read+1) % RBM_PQ_SIZE;
    return TRUE;
  }
  else
  {
    /*
     * prim buffer is empty
     */
    return FALSE;
  }
}

/*
+------------------------------------------------------------------------------
|  Function    : rbmi_pq_check
+------------------------------------------------------------------------------
|  Description : The prim queue is checked.
|                rcvReady indicates that there is still more than the
|                minimum space in the queue.
|                rcvFull  indicates that the queue is completeley full.
|
|
|  Parameters  : rcvReady -
|                rcvFull  -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


LOCAL void rbmi_pq_check
           (
             BOOL *rcvReady,
             BOOL *rcvFull
           )
{
  T_RBM_PQ_INDEX writeMax, writeThresh;

  TRACE_FUNCTION ("rbmi_pq_check()");

  writeMax    = (rlp_data->rbm.PQ_Read + RBM_PQ_MAX_PRIM)
              % RBM_PQ_SIZE;

  writeThresh = (rlp_data->rbm.PQ_Read + RBM_PQ_THRE_RNR)
              % RBM_PQ_SIZE;

  /*
   * prim queue filled upto threshold?
   */

  if (!(XOR
        (
          XOR
          (
            writeThresh > rlp_data->rbm.PQ_Write,
            rlp_data->rbm.PQ_Write > writeMax
          ),
          writeThresh > writeMax
        )
       )
      )
  {
    *rcvReady = FALSE;

    *rcvFull  = (rlp_data->rbm.PQ_Write EQ writeMax);
  }
  else
  {
    *rcvFull = FALSE;
    *rcvReady = TRUE;
  }
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_set_wind_size
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : windSize -
|
|
|  Return      : TRUE  -
|                FALSE -
+------------------------------------------------------------------------------
*/


GLOBAL BOOL rbm_set_wind_size
            (
              T_RBM_BUFFER_INDEX windSize
            )
{
  BOOL resetTimers;
  T_RBM_BUFFER_INDEX n;
  T_RBM_BUFFER_INDEX nEnd;
  T_RBM_BUFFER_INDEX oldSize;

  TRACE_FUNCTION ("rbm_set_wind_size()");

  resetTimers = FALSE;
  oldSize = rlp_data->rbm.K;
  rlp_data->rbm.K = windSize;

  if (windSize < oldSize)
  {
    n = rlp_data->rbm.VR + windSize;
    if (n >= RBM_BUF_SIZE)
    {
      n -= RBM_BUF_SIZE;
    }
    nEnd = rlp_data->rbm.VR + oldSize;
    if (nEnd >= RBM_BUF_SIZE)
    {
      nEnd -= RBM_BUF_SIZE;
    }
    do
    {
      switch (rlp_data->rbm.Slot[n].R_State)
      {
      case RBM_SREJ:
      case RBM_WAIT:
        resetTimers = TRUE;
        rlp_data->rbm.Slot[n].R_State = RBM_IDLE;
        break;
      default:
        break;
      }
      n += 1;
      if (n >= RBM_BUF_SIZE)
      {
        n = 0;
      }

    } while (n NEQ nEnd);
  }
  return (resetTimers);
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_init
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : windSize      -
|                frameSize     -
|                framesPerPrim -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_init
            (
              T_RBM_BUFFER_INDEX windSize,
              USHORT             frameSize,
              USHORT             framesPerPrim
            )
{
  USHORT n;

  TRACE_FUNCTION ("rbm_init()");

  n = 0;

  rlp_data->rbm.FramesPerPrim = framesPerPrim;
  rlp_data->rbm.FrameSize     = frameSize;

  for (n = 0; n < RBM_BUF_SIZE; n++)
  {
    rlp_data->rbm.Slot[n].R_State = RBM_IDLE;

    memset
    (
      rlp_data->rbm.Slot[n].Frame,
      0,
      rlp_data->rbm.FrameSize
    );
  }

  rlp_data->rbm.VR          = 0;
  rlp_data->rbm.FrameInRiBu = FALSE;

  memset
  (
    rlp_data->rbm.Frame,
    0,
    rlp_data->rbm.FrameSize
  );

  for (n = 0; n < RBM_PQ_SIZE; n++)
    rlp_data->rbm.PQ_Array[n] = (T_RBM_PRIM *) NULL;


  rlp_data->rbm.PQ_Read  = 0;
  rlp_data->rbm.PQ_Write = 0;

  rbmi_alloc_curr_prim ();
  rlp_data->rbm.K = windSize;

  rlp_data->rbm.Initialised = TRUE;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_deinit
+------------------------------------------------------------------------------
|  Description : This function frees all allocated T_RBM_PRIM primitives
|                of the receive buffer manager.
|
|  Parameters  :
|
|
|  Return      :
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_deinit
            (
              void
            )
{
  TRACE_FUNCTION ("rbm_deinit()");

  rlp_data->rbm.Initialised = FALSE;

  if (rlp_data->rbm.CurrPrim NEQ (T_RBM_PRIM *) NULL)
  {
    PFREE (rlp_data->rbm.CurrPrim)
    rlp_data->rbm.CurrPrim = (T_RBM_PRIM *) NULL;
  }

  while (rlp_data->rbm.PQ_Read NEQ rlp_data->rbm.PQ_Write)
  {
    if (rlp_data->rbm.PQ_Array[rlp_data->rbm.PQ_Read]
    NEQ (T_RBM_PRIM *) NULL)
    {
      PFREE (rlp_data->rbm.PQ_Array[rlp_data->rbm.PQ_Read])
      rlp_data->rbm.PQ_Array[rlp_data->rbm.PQ_Read]
       = (T_RBM_PRIM *) NULL;
    }
    rlp_data->rbm.PQ_Read = (rlp_data->rbm.PQ_Read+1) % RBM_PQ_SIZE;
  }

}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_reset
+------------------------------------------------------------------------------
|  Description : This function must be called once at startup before any
|                other procedures of the RBM is invoked. (Coldstart)
|
|
|  Parameters  : rlp_data_ptr -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_reset(T_RBM *rbm)
{
  TRACE_FUNCTION ("rbm_reset()");

  rbm->CurrPrim    = (T_RBM_PRIM *) NULL;
  rbm->CurrPrimCou = 0;
  rbm->K           = 0;
  rbm->FrameInRiBu = FALSE;
  rbm->FrameSize   = FRAME_SIZE_SHORT;
  rbm->PQ_Read     = 0;
  rbm->PQ_Write    = 0;
  rbm->Initialised = FALSE;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_reset_srej_slots
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_reset_srej_slots
            (
              void
            )
{
  T_RBM_BUFFER_INDEX n;

  TRACE_FUNCTION ("rbm_reset_srej_slots()");

  for (n = 0; n < RBM_BUF_SIZE; n++)
  {
    switch (rlp_data->rbm.Slot[n].R_State)
    {
      case RBM_WAIT:
      case RBM_SREJ:
        rlp_data->rbm.Slot[n].R_State = RBM_IDLE;
        return;

      default:
        break;
    }
  }
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_reset_all_r_states
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_reset_all_r_states
            (
              void
            )
{
  T_RBM_BUFFER_INDEX n;

  TRACE_FUNCTION ("rbm_reset_all_r_states()");

  for (n = 0; n < RBM_BUF_SIZE; n++)
    rlp_data->rbm.Slot[n].R_State = RBM_IDLE;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_check_slots_srej
+------------------------------------------------------------------------------
|  Description : Checks wheter a received slot is to be SREJted.
|                Returns RBM_INVALID: IDX if No SREJ pending
|                0..n       : Slot num to be SREJted
|
|  Parameters  : -
|
|
|  Return      : n                -
|                RBM_INVALID_IDX  -
+------------------------------------------------------------------------------
*/


GLOBAL T_RBM_BUFFER_EXTIDX rbm_check_slots_srej(void)
{
  T_RBM_BUFFER_INDEX n;

  TRACE_FUNCTION ("rbm_check_slots_srej()");

  n = rlp_data->rbm.VR;

  do
  {
    switch (rlp_data->rbm.Slot[n].R_State)
    {
      case RBM_IDLE:
        return RBM_INVALID_IDX;

      case RBM_SREJ:
        return n;

      default:
        n = (n+1) % RBM_BUF_SIZE;
        break;
    }
  }
  while (n NEQ rlp_data->rbm.VR);

  return RBM_INVALID_IDX;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_set_rslot_wait
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : slot -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_set_rslot_wait
            (
              T_RBM_BUFFER_INDEX slot
            )
{
  TRACE_FUNCTION ("rbm_set_rslot_wait()");

  rlp_data->rbm.Slot[slot].R_State = RBM_WAIT;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_set_rslot_wait2srej
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : slot -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_set_rslot_wait2srej
            (
              T_RBM_BUFFER_INDEX slot
            )
{
  TRACE_FUNCTION ("rbm_set_rslot_wait2srej()");

  rlp_data->rbm.Slot[slot].R_State = RBM_SREJ;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_set_rslot_rcvd
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : slot       -
|                resetTimer -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_set_rslot_rcvd
            (
              T_RBM_BUFFER_EXTIDX  slot,
              BOOL               *resetTimer
            )
{
  TRACE_FUNCTION ("rbm_set_rslot_rcvd()");

  if(slot EQ RBM_INVALID_IDX)
    slot = rlp_data->rbm.LastVR;

  switch (rlp_data->rbm.Slot[slot].R_State)
  {
    case RBM_WAIT:
      *resetTimer = TRUE;
      break;

    default:
      *resetTimer = FALSE;
      break;
  }

  rlp_data->rbm.Slot[slot].R_State = RBM_RCVD;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_get_current_frame
+------------------------------------------------------------------------------
|  Description : This function returns the current - i.e. last stored -
|                frame of the receive buffer. The frame may be in the ring
|                buffer or in the static buffer.
|
|  Parameters  : -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL T_RBM_FRAMEPTR  rbm_get_current_frame
                       (
                         void
                       )
{

  T_RBM_FRAMEPTR frame;

  TRACE_FUNCTION ("rbm_get_current_frame()");

  if (rlp_data->rbm.FrameInRiBu)
    frame = rlp_data->rbm.Slot[rlp_data->rbm.VR].Frame;
  else
    frame = rlp_data->rbm.Frame;

  return frame;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_accept_current_frame
+------------------------------------------------------------------------------
|  Description : This function advances VR to make sure, that the next
|                frame is stored in the next free slot.
|
|  Parameters  : -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_accept_current_frame
            (
              void
            )
{
  TRACE_FUNCTION ("rbm_accept_current_frame()");

  rlp_data->rbm.LastVR = rlp_data->rbm.VR;

  do
  {
    rlp_data->rbm.VR = (rlp_data->rbm.VR +1) % RBM_BUF_SIZE;
  } while (rlp_data->rbm.Slot[rlp_data->rbm.VR].R_State EQ RBM_RCVD);
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_mark_missing_i_frames_srej
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : ns -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_mark_missing_i_frames_srej
            (
              T_RBM_BUFFER_INDEX ns
            )
{
  T_RBM_BUFFER_INDEX n;

  TRACE_FUNCTION ("rbm_mark_missing_i_frames_srej()");

  n = rlp_data->rbm.VR;

  do
  {
    switch (rlp_data->rbm.Slot[n].R_State)
    {
      case RBM_IDLE:
        rlp_data->rbm.Slot[n].R_State = RBM_SREJ;
        break;

      default:
        break;
    }

    n = (n+1) % RBM_BUF_SIZE;
  }
  while (n NEQ ns);
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_count_missing_i_frames
+------------------------------------------------------------------------------
|  Description : Counts all slots in R buffer, which will be marked by
|                rbm_mark_missing_i_frames_srej
|
|  Parameters  : ns     -
|                count  -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_count_missing_i_frames
            (
              T_RBM_BUFFER_INDEX  ns,
              T_RBM_BUFFER_INDEX *count
            )
{
  T_RBM_BUFFER_INDEX n;

  TRACE_FUNCTION ("rbm_count_missing_i_frames()");

  *count = 0;
  n      = rlp_data->rbm.VR;

  do
  {
    switch (rlp_data->rbm.Slot[n].R_State)
    {
      case RBM_IDLE:
        (*count)++;
        break;

      default:
        break;
    }

    n = (n+1) % RBM_BUF_SIZE;
  }
  while (n NEQ ns);
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_buffer_all_in_sequence_frames
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : fromSlot     -
|                primIsReady  -
|                rcvReady     -
|                rcvFull      -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_buffer_all_in_sequence_frames
            (
              T_RBM_BUFFER_EXTIDX   fromSlot,
              BOOL                 *primIsReady,
              BOOL                 *rcvReady,
              BOOL                 *rcvFull
            )
{
  TRACE_FUNCTION ("rbm_buffer_all_in_sequence_frames()");

  if(fromSlot EQ RBM_INVALID_IDX)
    fromSlot = rlp_data->rbm.LastVR;

  *primIsReady = FALSE;

  do
  {
    rbmi_buffer_frame (fromSlot, primIsReady);
    rlp_data->rbm.Slot[fromSlot].R_State = RBM_IDLE;
    fromSlot = (fromSlot + 1) % RBM_BUF_SIZE;
  } while (rlp_data->rbm.Slot[fromSlot].R_State EQ RBM_RCVD);

  rbmi_pq_check (rcvReady, rcvFull);
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_ns_check
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : ns       -
|                valid    -
|                expected -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rbm_ns_check
            (
              T_RBM_BUFFER_INDEX  ns,
              BOOL               *valid,
              BOOL               *expected
            )
{
  USHORT max_ns;

  TRACE_FUNCTION ("rbm_ns_check()");

  if(rlp_data->rbm.K EQ 0)
  {
    *valid    = FALSE;
    *expected = FALSE;
    return;
  }


  max_ns = (rlp_data->rbm.VR + rlp_data->rbm.K -1) % RBM_BUF_SIZE;
  /*
   * ns within Window?
   */
  if (!(XOR
        (
          XOR
          (
            rlp_data->rbm.VR > ns,
            ns > max_ns
          ),
          rlp_data->rbm.VR > max_ns
        )
       )
     )
  {
    *valid    = TRUE;
    *expected = (ns EQ rlp_data->rbm.VR);
  }
  else
  {
    *valid    = FALSE;
    *expected = FALSE;
  }
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_get_vr
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : -
|
|
|  Return      : VR
+------------------------------------------------------------------------------
*/


GLOBAL T_RBM_BUFFER_INDEX rbm_get_vr
                          (
                            void
                          )
{
  TRACE_FUNCTION ("rbm_get_vr()");

  return rlp_data->rbm.VR;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_get_prim
+------------------------------------------------------------------------------
|  Description : This is just a wrapper for rbmi_pq_deq. The queu is an
|                internal matter of the RBM, therefore the function
|                rbmi_pq_deq should not be used directly by the user.
|
|  Parameters  : prim     -
|                rcvReady -
|                rcvFull  -
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL BOOL rbm_get_prim
            (
              T_RBM_PRIM **prim,
              BOOL       *rcvReady,
              BOOL       *rcvFull
            )
{
  BOOL primFound;
  TRACE_FUNCTION ("rbm_get_prim()");

  primFound = rbmi_pq_deq (prim);
  if (primFound)
  {
    rbmi_pq_check(rcvReady, rcvFull);
  }
  return primFound;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_get_curr_prim
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : -
|
|
|  Return      : prim
+------------------------------------------------------------------------------
*/


GLOBAL T_RBM_PRIM *rbm_get_curr_prim
            (
              void
            )
{
  T_RBM_PRIM *prim;

  TRACE_FUNCTION ("rbm_get_curr_prim()");

  rlp_data->rbm.CurrPrim->sdu.l_buf
    = rlp_data->rbm.CurrPrimCou * rlp_data->rbm.FrameSize * 8;

  rlp_data->rbm.CurrPrim->sdu.o_buf  = 0;

  prim = rlp_data->rbm.CurrPrim;

  rbmi_alloc_curr_prim ();

  return prim;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_move_current_frame
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  :
|
|
|  Return      :
+------------------------------------------------------------------------------
*/



GLOBAL void rbm_move_current_frame
            (
              T_RBM_BUFFER_INDEX slot
            )
{
  TRACE_FUNCTION ("rbm_move_current_frame()");

  memcpy
  (
    rlp_data->rbm.Slot[slot].Frame,
    rlp_data->rbm.Slot[rlp_data->rbm.VR].Frame,
    rlp_data->rbm.FrameSize
  );
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_is_state_wait
+------------------------------------------------------------------------------
|  Description : This function is called from the HISR. It returns the
|                frame descriptor for the buffer, in which the HISR has to
|                write the received frame.
|
|
|  Parameters  : slot -
|
|
|  Return      : TRUE  -
|                FALSE -
+------------------------------------------------------------------------------
*/


GLOBAL BOOL rbm_is_state_wait
            (
              T_RBM_BUFFER_INDEX slot
            )
{
  TRACE_FUNCTION ("rbm_is_state_wait()");

  if (rlp_data->rbm.Slot[slot].R_State EQ RBM_WAIT)
    return TRUE;
  else
    return FALSE;
}

/*
+------------------------------------------------------------------------------
|  Function    : rbm_prepare_remap
+------------------------------------------------------------------------------
|  Description :
|
|  Parameters  : frameSize -
|
|
|  Return      :
+------------------------------------------------------------------------------
*/


GLOBAL T_FRAME_NUM rbm_prepare_remap
                   (
                     USHORT frameSize
                   )
{
  T_RBM_PRIM *prim;
  USHORT oldFrameSize;
  USHORT currPrimCou;

  TRACE_FUNCTION ("rbm_prepare_remap()");

  oldFrameSize = rlp_data->rbm.FrameSize;
  currPrimCou  = rlp_data->rbm.CurrPrimCou;

  rlp_data->rbm.FrameSize = frameSize;

  prim = rbm_get_curr_prim ();

  prim->sdu.l_buf = currPrimCou * oldFrameSize * 8;

  rbmi_pq_enq (prim);

  return (rbm_get_vr());
}

#ifdef _SIMULATION_
/*
+------------------------------------------------------------------------------
|  Function    : rbm_store_frame
+------------------------------------------------------------------------------
|  Description : This procedure is only used in the simulation environment
|                to store a frame in the receive buffer. 
|                In the implementation the copy is performed 
|                by the RA adaptation layer
|                which has access to the shared memory area of the DSP.
|
|  Parameters  : frame -
|
|  Return      : -
+------------------------------------------------------------------------------
*/

GLOBAL void rbm_store_frame(T_RBM_FRAMEPTR frame)
{
  TRACE_FUNCTION ("rbm_store_frame()");

  if (rlp_data->rbm.Initialised)
  {
    memcpy
    (
      rlp_data->rbm.Slot[rlp_data->rbm.VR].Frame,
      frame,
      rlp_data->rbm.FrameSize
    );

    rlp_data->rbm.FrameInRiBu = TRUE;
  }
  else
  {
    memcpy
    (
      rlp_data->rbm.Frame,
      frame,
      rlp_data->rbm.FrameSize
    );

    rlp_data->rbm.FrameInRiBu = FALSE;
  }
}
#endif

#ifdef _TARGET_
/*
+------------------------------------------------------------------------------
|  Function    : rlp_rbm_get_next_buffer
+------------------------------------------------------------------------------
|  Description : This function is called from the HISR. It returns the
|                frame descriptor for the buffer, in which the HISR has to
|                write the received frame.
|
|
|  Parameters  : frameDesc -
|
|
|  Return      : -
+------------------------------------------------------------------------------
*/


GLOBAL void rlp_rbm_get_next_buffer(T_FRAME_DESC *frameDesc)
{
  TRACE_FUNCTION ("rbm_get_next_buffer()");

  if (rlp_data->rbm.Initialised)
  {
    frameDesc->Adr[0] = rlp_data->rbm.Slot[rlp_data->rbm.VR].Frame;
    rlp_data->rbm.FrameInRiBu = TRUE;
  }
  else
  {
    frameDesc->Adr[0] = rlp_data->rbm.Frame;
    rlp_data->rbm.FrameInRiBu = FALSE;
  }

  frameDesc->Len[0] = rlp_data->rbm.FrameSize;
  frameDesc->Adr[1] = (UBYTE *) NULL;
  frameDesc->Len[1] = 0;
}
#endif