fce85ce1fbcc64b394a4f7bb09229017c23099ca
[o-du/l2.git] / src / 5gnrmac / rg_mux.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     LTE-MAC layer
22   
23      Type:     C source file
24   
25      Desc:     C source code for Entry point fucntions
26   
27      File:     rg_mux.c 
28   
29 **********************************************************************/
30
31 /** @file rg_mux.c
32 @brief MAC Multiplexing API.
33 */
34
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_FILE_ID=229;
37 static int RLOG_MODULE_ID=4096;
38
39 /* header include files -- defines (.h) */
40 #include "envopt.h"        /* environment options */
41 #include "envdep.h"        /* environment dependent */
42 #include "envind.h"        /* environment independent */
43   
44 #include "gen.h"           /* general */
45 #include "ssi.h"           /* system services */
46
47 #include "cm_tkns.h"       /* Common Token Defines */
48 #include "cm_llist.h"      /* Common Link List Defines */
49 #include "cm_hash.h"       /* Common Hash List Defines */
50 #include "cm_mblk.h"       /* memory management */
51 #include "cm_lte.h"        /* Common LTE Defines */
52
53 #include "rg_env.h"        /* MAC Environment Defines */
54 #include "tfu.h"           /* TFU Interface defines */
55 #include "crg.h"           /* CRG Interface defines */
56 #include "rg_sch_inf.h"           /* RGR Interface defines */
57 #include "rgu.h"           /* RGU Interface defines */
58 #include "lrg.h"           /* LRG Interface defines */
59
60 #include "rg_err.h"        /* MAC error defines */
61 #include "rg.h"            /* MAC defines */
62
63 /* header/extern include files (.x) */
64 #include "gen.x"           /* general */
65 #include "ssi.x"           /* system services */
66 #include "cm5.x"           /* system services */
67 #include "cm_tkns.x"       /* Common Token Definitions */
68 #include "cm_llist.x"      /* Common Link List Definitions */
69 #include "cm_lib.x"        /* Common Library Definitions */
70 #include "cm_hash.x"       /* Common Hash List Definitions */
71 #include "cm_mblk.x"       /* memory management */
72 #include "cm_lte.x"        /* Common LTE Definitions */
73
74 #include "rgu.x"           /* RGU Interface includes */
75 #include "tfu.x"           /* CRG Interface includes */
76 #include "crg.x"           /* CRG Interface includes */
77 #include "rg_sch_inf.x"    /* SCH Interface includes */
78 #include "rg_prg.x"        /* PRG Interface includes */
79 #include "rgu.x"           /* RGU Interface includes */
80 #include "lrg.x"           /* LRG Interface includes */
81
82 #include "du_app_mac_inf.h"
83 #include "rg.x"            /* MAC includes */
84 #include "ss_queue.h"
85 #include "ss_queue.x"
86 #include "ss_task.x"
87 #include "ss_msg.x"            /* MAC includes */
88 /* local defines */
89 #ifndef T2K_MEM_LEAK_DBG
90 EXTERN  S16 ssGetDBufOfSize(Region region,Size size,Buffer **dBuf);
91 #else
92 char* file = __FILE__;
93 U32 line = __LINE__;
94 #endif
95
96 /* local typedefs */
97
98 /* global variables */
99 U32 rgDlrate_rgu;
100
101 /* local externs */
102
103 PRIVATE Void rgMUXGet20bitRarGrnt ARGS((U8 ulBw,
104                                         RgInfRarUlGrnt *msg3Grnt,
105                                         U8 *grnt));
106 EXTERN U16 rgMUXCalcRiv ARGS((U8 bw,
107                                 U8 rbStart,
108                                 U8 numRb));
109  
110 #ifndef MS_MBUF_CORRUPTION
111 #define MS_BUF_ADD_ALLOC_CALLER()
112 #endif
113 /* forward references */
114
115 #define RG_PACK_SHDR_FIXD_SZ(_subHdr, _lcId, _mBuf, _ret) {\
116    _subHdr.shLen = RG_FIXDSZ_CE_SHDR_LEN;\
117    _subHdr.shData[0] = (0x3F & _lcId);\
118    MS_BUF_ADD_ALLOC_CALLER(); \
119    _ret = SAddPstMsgMult(&_subHdr.shData[0], _subHdr.shLen, _mBuf);\
120 }
121
122 #define RG_PACK_CE(_ce, _len, _ceBuf, _ret) {\
123    MS_BUF_ADD_ALLOC_CALLER(); \
124    _ret = SAddPstMsgMult((U8 *)(&(_ce)), _len, _ceBuf);\
125 }
126
127 #define RG_MUX_CALC_LEN(_len,_lenBytes,_elmTotLen) {\
128    U8 _hdrLen;\
129    _lenBytes    = (_len <= 255) ? 1 : 2;\
130    _hdrLen      = _lenBytes + RG_SDU_SHDR_LEN;\
131    _elmTotLen   = _hdrLen + _len;\
132 }
133
134 #define RG_PACK_VAR_SZ_CE_SDU_SHDR(_subHdr, _lcId, _len,_mBuf, _ret) {\
135    _ret = ROK;\
136    if(_len <= 255)\
137    {\
138       _subHdr.shData[0] = (0x3F & _lcId);\
139       _subHdr.shLen = 2;\
140       _subHdr.shData[1] = (0xFF & _len);\
141       _subHdr.shData[2] = 0;\
142    }\
143    else\
144    {\
145    _subHdr.shData[0] = (0x7F & ((0x40) | _lcId));\
146       _subHdr.shLen = 3;\
147       _subHdr.shData[1] = (0xFF & (_len >> 8));\
148       _subHdr.shData[2] = (0xFF & _len);\
149    }\
150    MS_BUF_ADD_ALLOC_CALLER(); \
151    _ret = SAddPstMsgMult(&_subHdr.shData[0], _subHdr.shLen, _mBuf);\
152 }
153
154 #define RG_PACK_PAD_SHDR(_mBuf, _ret) {\
155       _ret = SAddPreMsg(0x3F, _mBuf);\
156 }
157
158 #define RG_PACK_RAR_SHDR(_byte, _mBuf, _ret) {\
159    _ret = SAddPstMsg(_byte, _mBuf);\
160 }
161
162
163 /**
164  * @brief Function to add ces along with subhdrs.
165  * This function packs first CE sub-hdr and then CE in ceBuf pointer 
166  *
167  * @details
168  *
169  *     Function : rgMUXAddCes
170  *     
171  *  @param[in]  Inst        inst
172  *  @param[in] RgBldPduInfo   *pdu
173  *  @param[in] Buffer        *ceBuf 
174  *  @param[in] RgErrInfo     *err 
175  *  @return    S16
176  *      -# ROK 
177  *      -# RFAILED 
178  **/
179 #ifdef ANSI
180 PRIVATE S16 rgMUXAddCes
181 (
182 Inst           inst,
183 RgBldPduInfo   *pdu,
184 Buffer         *ceBuf,
185 RgErrInfo      *err
186 )
187 #else
188 PRIVATE S16 rgMUXAddCes(inst,pdu, ceShdrBuf, ceBuf, err)
189 Inst           inst;
190 RgBldPduInfo   *pdu;
191 Buffer         *ceBuf;
192 RgErrInfo      *err;
193 #endif
194 {
195    S16            ret;
196    RgMUXSubHdr    subHdr;
197
198    TRC2(rgMUXAddCes)
199
200    if (NULLP != pdu->contResId)
201    {
202       if(pdu->schdTbSz >= RG_CRES_ELM_LEN)
203       {
204          RG_PACK_SHDR_FIXD_SZ(subHdr, RG_CRES_LCID_IDX, ceBuf, ret);
205
206          if(ret != ROK)
207          {
208             err->errCause = RGERR_MUX_BLD_CEHDR_FAIL;
209             RLOG0(L_ERROR, "Muxing of Contention Resolution CE sub-header is failed");
210             RETVALUE(RFAILED);
211          }
212
213          RG_PACK_CE(pdu->contResId->resId[0], RG_CRES_LEN, ceBuf, ret);
214
215          if(ret != ROK)
216          {
217             err->errCause = RGERR_MUX_BLD_CE_FAIL;
218             RLOG0(L_ERROR, "Muxing of Contention Resolution CE is failed")
219             RETVALUE(RFAILED);
220          }
221          pdu->schdTbSz -= RG_CRES_ELM_LEN;
222       }
223    }
224    if (TRUE == pdu->ta.pres)
225    {
226       if(pdu->schdTbSz >= RG_TA_ELM_LEN)
227       {
228          U8 taVal; /* Moving from outer scope to available scope */
229          RG_PACK_SHDR_FIXD_SZ(subHdr, RG_TA_LCID_IDX, ceBuf, ret);
230
231          if(ret != ROK)
232          {
233             err->errCause = RGERR_MUX_BLD_CEHDR_FAIL;
234             RLOG0(L_ERROR, "Muxing of TA CE sub-hdr is failed")
235             RETVALUE(RFAILED);
236          }
237
238          taVal = pdu->ta.val;
239          RG_PACK_CE(taVal, RG_TA_LEN, ceBuf, ret);
240
241          if(ret != ROK)
242          {
243             err->errCause = RGERR_MUX_BLD_CE_FAIL;
244             RLOG0(L_ERROR, "Muxing of TA CE is failed")
245             RETVALUE(RFAILED);
246          }
247          pdu->schdTbSz -= RG_TA_ELM_LEN;
248          RLOG1(L_DEBUG,"TA muxed by MAC: %u", pdu->ta.val);
249       }
250    }
251 #ifdef LTE_ADV
252    if(TRUE == pdu->sCellActCe.pres)
253    {
254       if(pdu->schdTbSz >= RG_SCELL_CE_ELM_LEN)
255       {
256          /* Adding the subheader for ACT CE */
257          RG_PACK_SHDR_FIXD_SZ(subHdr, RG_SCELL_LCID_IDX, ceBuf, ret);
258
259          if(ret != ROK)
260          {
261             err->errCause = RGERR_MUX_BLD_CEHDR_FAIL;
262             RLOG0(L_ERROR, "Muxing of SCELL Activation CE sub-hdr is failed")
263             RETVALUE(RFAILED);
264          }
265
266          /* Adding the ACT CE */
267          RG_PACK_CE(pdu->sCellActCe.val, RG_SCELL_ACT_CE_LEN, ceBuf, ret);
268
269          if(ret != ROK)
270          {
271             err->errCause = RGERR_MUX_BLD_CE_FAIL;
272             RLOG0(L_ERROR, "Muxing of SCELL Activation CE is failed")
273             RETVALUE(RFAILED);
274          }
275          pdu->schdTbSz -= RG_SCELL_CE_ELM_LEN;
276
277       }
278    }
279 #endif
280   
281   /*LcId is not yet decided in 5G-NR spec for MAC CEs Hence, not writing code
282    * new MAC CEs. */
283
284    RETVALUE(ROK);
285 } /* rgMUXAddCes */
286
287 /**
288  * @brief Function to insert SDU along with sub headers.
289  *
290  * @details
291  *
292  *     Function : rgMUXInsSdu
293  *     
294  *  @param[in]       Inst        inst
295  *  @param[in]       MsgLen      *schdTbSz
296  *  @param[in]       U8          lcId
297  *  @param[in]       Buffer      *sdu
298  *  @param[out]      Buffer      *sduBuf 
299  *  @param[out]      RgErrInfo   *err 
300  *  @return    S16
301  *      -# ROK 
302  *      -# RFAILED
303  **/
304 #ifdef ANSI
305 PRIVATE S16 rgMUXInsSdu
306 (
307 Inst           inst,
308 MsgLen         *schdTbSz,
309 U8             lcId,
310 Buffer         *sdu,
311 Buffer         *sduBuf,
312 RgErrInfo      *err
313 )
314 #else
315 PRIVATE S16 rgMUXInsSdu(inst,schdTbSz, lcId, sdu, sduBuf, err)
316 Inst           inst;
317 MsgLen         *schdTbSz;
318 U8             lcId;
319 Buffer         *sdu;
320 Buffer         *sduBuf;
321 RgErrInfo      *err;
322 #endif
323 {
324    S16            ret;
325    MsgLen         msgLen = 0;
326    U8             lenBytes;
327    MsgLen         elmTotLen;
328
329    TRC2(rgMUXInsSdu)
330    SFndLenMsg(sdu, &msgLen);
331
332    RG_MUX_CALC_LEN(msgLen,lenBytes,elmTotLen);
333    
334    if (lcId == 3)
335    {
336      rgDlrate_rgu += msgLen; 
337    }
338    if (*schdTbSz >= elmTotLen)
339    {
340       RgMUXSubHdr    subHdr;
341       RG_PACK_VAR_SZ_CE_SDU_SHDR(subHdr, lcId, msgLen,sduBuf, ret);
342       if(ret != ROK)
343       {
344          err->errCause = RGERR_MUX_BLD_SDUHDR_FAIL;
345          RLOG1(L_ERROR, "RGERR_MUX_BLD_SDUHDR_FAIL for LCID:%d",lcId);
346          RETVALUE(RFAILED);
347       }
348
349 #ifndef L2_OPTMZ /* no need to pack as passing not muxing all LCs PDUs to 1*/
350       RG_PACK_SDU(sduBuf, sdu, ret);
351 #else
352   //UDAY
353       ret = ROK;
354       UNUSED(sduBuf);
355 #endif
356
357       if(ret != ROK)
358       {
359          err->errCause = RGERR_MUX_BLD_SDU_FAIL;
360          RLOG1(L_ERROR, "RGERR_MUX_BLD_SDU_FAIL for LCID:%d",lcId);
361          RETVALUE(RFAILED);
362       }
363
364       *schdTbSz -= elmTotLen;
365    }
366    else
367    {
368       /* This Sub-PDU can not be accodmodated at all */
369       RLOG4(L_ERROR, "Failed lcId %u, elmTotLen %d lenBytes %d LCID:%d",
370                lcId, ((S16)elmTotLen), lenBytes,lcId);
371       RLOG3(L_ERROR, "msglen %d schdTbSz %d LCID:%d",
372                ((S16)msgLen), ((S16)*schdTbSz),lcId);
373       RETVALUE(RFAILED);
374    }
375    RETVALUE(ROK);
376 }
377
378 /**
379  * @brief Function to insert SDU along with sub headers.
380  *
381  * @details
382  *
383  *     Function : rgMUXAddPadd
384  *     
385  *  @param[in]  Inst        inst
386  *  @param[in]       RgBldPduInfo   *pdu
387  *  @param[out]      Buffer        *mBuf 
388  *  @param[out]      Buffer        *sduBuf 
389  *  @return    S16
390  *      -# ROK 
391  *      -# RFAILED
392  **/
393 #ifdef L2_OPTMZ
394 U32 padSize = 0;
395 #endif
396 #ifdef ANSI
397 PUBLIC S16 rgMUXAddPadd
398 (
399 Inst           inst,
400 MsgLen         *schdTbSz,
401 Buffer         *sduBuf,
402 Bool           isRar,
403 RgErrInfo      *err
404 )
405 #else
406 PUBLIC S16 rgMUXAddPadd(inst,schdTbSz, sduBuf, isRar, err)
407 Inst           inst;
408 MsgLen         *schdTbSz;
409 Buffer         *sduBuf;
410 Bool           isRar;
411 RgErrInfo      *err;
412 #endif
413 {
414    S16     ret = ROK;
415    Buffer         *padBuf = NULLP;
416    RgMUXSubHdr    subHdr;
417    TRC2(rgMUXAddPadd)
418
419 #ifdef L2_OPTMZ
420    padSize = 0;
421 #endif
422    if(*schdTbSz)
423    {
424 #ifndef L2_OPTMZ
425       if(FALSE == isRar)
426 #else
427       if((FALSE == isRar) && (NULL != sHdrBuf))
428 #endif
429
430       {
431          RG_PACK_SHDR_FIXD_SZ(subHdr, RG_PAD_LCID_IDX, sduBuf, ret);  
432
433          if(ret != ROK)
434          {
435             err->errCause = RGERR_MUX_BLD_PADHDR_FAIL;
436             RLOG0(L_ERROR, "RGERR_MUX_BLD_PADHDR_FAIL");
437             RETVALUE(RFAILED);
438          }
439
440          *schdTbSz -= 1;
441       }
442
443       if (*schdTbSz)
444       {
445          if (*schdTbSz <= RG_MAX_PAD_ARR_SZ)
446          {
447 #ifndef L2_OPTMZ
448             RG_PACK_PAD(padBuf,*schdTbSz,sduBuf);
449 #else
450             if(sduBuf)
451             {
452                RG_PACK_PAD(padBuf,*schdTbSz,sduBuf);
453             }
454             else
455                padSize += *schdTbSz;
456 #endif
457             if(ret != ROK)
458             {
459                err->errCause = RGERR_MUX_BLD_PAD_FAIL;
460                RLOG0(L_ERROR, "RGERR_MUX_BLD_PAD_FAIL");
461                RETVALUE(RFAILED);
462             }
463             *schdTbSz = 0;
464          }
465          else
466          {
467             while (*schdTbSz)
468             {
469                if (*schdTbSz > RG_MAX_PAD_ARR_SZ)
470                {
471 #ifndef L2_OPTMZ
472                   RG_PACK_PAD(padBuf,RG_MAX_PAD_ARR_SZ,sduBuf);
473 #else
474                   if(sduBuf)
475                   {
476                      RG_PACK_PAD(padBuf,RG_MAX_PAD_ARR_SZ,sduBuf);
477                   }
478                   else
479                      padSize += RG_MAX_PAD_ARR_SZ;
480 #endif
481
482                   if(ret != ROK)
483                   {
484                      err->errCause = RGERR_MUX_BLD_PAD_FAIL;
485                      RLOG0(L_ERROR, "RGERR_MUX_BLD_PAD_FAIL");
486                      RETVALUE(RFAILED);
487                   }
488
489                   *schdTbSz -= RG_MAX_PAD_ARR_SZ;
490                }
491                else
492                {
493 #ifndef L2_OPTMZ
494                   RG_PACK_PAD(padBuf,*schdTbSz,sduBuf);
495 #else
496                   if(sduBuf)
497                   {
498                      RG_PACK_PAD(padBuf,*schdTbSz,sduBuf);
499                   }
500                   else
501                      padSize += *schdTbSz;
502 #endif
503
504                   if(ret != ROK)
505                   {
506                      err->errCause = RGERR_MUX_BLD_PAD_FAIL;
507                      RLOG0(L_ERROR, "RGERR_MUX_BLD_PAD_FAIL");
508                      RETVALUE(RFAILED);
509
510                   }
511                   *schdTbSz = 0;
512                }
513             }
514          }
515       }
516    }
517
518    RETVALUE(ROK);
519 } /* rgMUXAddPadd */
520
521 #ifndef L2_OPTMZ
522 /**
523  * @brief Function to add SDU along with sub headers.
524  *
525  * @details
526  *
527  *     Function : rgMUXAddSdus
528  *     
529  *  @param[in]  Inst        inst
530  *  @param[in]       RgBldPduInfo   *pdu
531  *  @param[out]      Buffer        *mBuf 
532  *  @param[out]      Buffer        *sduBuf 
533  *  @return    S16
534  *      -# ROK 
535  *      -# RFAILED
536  **/
537 #ifdef ANSI
538 PRIVATE S16 rgMUXAddSdus
539 (
540 Inst           inst,
541 RgBldPduInfo   *pdu,
542 Buffer         *sduBuf,
543 RgErrInfo      *err
544 )
545 #else
546 PRIVATE S16 rgMUXAddSdus(inst,pdu, sduBuf, err)
547 Inst           inst;
548 RgBldPduInfo   *pdu;
549 Buffer         *sduBuf;
550 RgErrInfo      *err;
551 #endif
552 {
553    RgRguDDatReqPerUe *dDatReq;
554    RgRguCmnDatReq    *cDatReq;
555
556    TRC2(rgMUXAddSdus)
557
558    switch(pdu->reqType)
559    {
560       case EVTRGUCDATREQ:
561          cDatReq = (RgRguCmnDatReq *)(pdu->datReq);
562          /* Add sdu(s) to the Message Buffer */
563          if (NULLP != cDatReq)
564          {
565             if(rgMUXInsSdu(inst,&pdu->schdTbSz, 
566                      RG_CCCH_LCID, cDatReq->pdu, sduBuf, err) != ROK)
567             {
568                RETVALUE(RFAILED);
569             }
570             RG_FREE_MSG(cDatReq->pdu);
571          }
572          break;
573
574       case EVTRGUDDATREQ:
575          dDatReq = (RgRguDDatReqPerUe *)(pdu->datReq);
576          /* Add sdu(s) to the Message Buffer */
577          if (NULLP != dDatReq)
578          {
579             if(pdu->tbIndex == 1)
580             {
581                U16 idx1, idx2;
582                /* Adding this temporary variable for optimization */
583                RguDatReqTb *datReqTb = &dDatReq->datReqTb[0];
584
585                for (idx1=0; (idx1 < datReqTb->nmbLch); idx1++)
586                {
587                   for(idx2=0;
588                      (idx2 < datReqTb->lchData[idx1].pdu.numPdu);
589                      idx2++)
590                   {
591                      if(pdu->schdTbSz)
592                      {
593                         if(rgMUXInsSdu(inst,&pdu->schdTbSz,
594                            datReqTb->lchData[idx1].lcId, 
595                            datReqTb->lchData[idx1].pdu.mBuf[idx2],
596                            sduBuf, err) != ROK)
597                         {
598                            RLOG1(L_ERROR, "FAILED for LCID:%d",datReqTb->lchData[idx1].lcId);
599                            RETVALUE(RFAILED);
600                         }
601                      }
602                      RG_FREE_MSG(datReqTb->lchData[idx1].pdu.mBuf[idx2]);
603                   }
604                }
605             }
606             else if(pdu->tbIndex == 2)
607             {
608                U16 idx1, idx2;
609                RguDatReqTb *datReqTb = &dDatReq->datReqTb[1];
610                for (idx1=0; (idx1 < datReqTb->nmbLch); idx1++)
611                {
612                   for(idx2=0;
613                      (idx2 < datReqTb->lchData[idx1].pdu.numPdu);
614                      idx2++)
615                   {
616                      if(pdu->schdTbSz)
617                      {
618                         if(rgMUXInsSdu(inst,&pdu->schdTbSz,
619                            datReqTb->lchData[idx1].lcId, 
620                            datReqTb->lchData[idx1].pdu.mBuf[idx2],
621                            sduBuf, err) != ROK)
622                         {
623                            RLOG2(L_ERROR, "FAILED TB Size %d LCID:%d",
624                                     ((S16)pdu->schdTbSz),datReqTb->lchData[idx1].lcId);
625                            RETVALUE(RFAILED);
626                         }
627                      }
628                      RG_FREE_MSG(datReqTb->lchData[idx1].pdu.mBuf[idx2]);
629                   }
630                }
631             }
632          }
633          break;
634
635       case EVENT_SLOT_IND_TO_MAC:
636          break;
637       default:
638          break;
639    } /* End of switch(reqType) */
640    if(rgMUXAddPadd(inst,&pdu->schdTbSz, sduBuf, FALSE, err) != ROK)
641    {
642       RLOG1(L_ERROR, "FAILED for TB Size:%d",(S16)pdu->schdTbSz);
643       RETVALUE(RFAILED);
644    }
645    RETVALUE(ROK);
646 }
647
648 /**
649  * @brief Function to create MAC PDU from RLC SDUs and control elements, if any. 
650  *
651  * @details
652  *
653  *     Function : rgMUXBldPdu
654  *     
655  *     -# This function shall be invoked by Downlink Harq Module as soon as a
656  *        Data request is received from RLC for a UE along with its stored 
657  *        control elements to create a MAC PDU.
658  *     -# It shall create subheaders for the control elements (timing advance
659  *        and contention resolution ID) and pack sub-header before each CE,
660  *        if given, and then shall run through all the logical channels and
661  *        create subheader for each of the SDUs given on that logical channel
662  *        and pack corresponding sub-header before the each SDU 
663  *     -# It shall invoke rgMUXPadPdu if the total length of the created 
664  *        buffer is less than the scheduled TB size. 
665  *     
666  *           
667  *  @param[in]  Inst           *inst
668  *  @param[in]  RgBldPduInfo   *bldPdu
669  *  @param[in]  Buffer         **txPdu
670  *  @param[out] RgErrInfo      *err
671  *  @return  S16
672  *      -# ROK 
673  *      -# RFAILED 
674  **/
675 #ifdef ANSI
676 PUBLIC S16 rgMUXBldPdu
677 (
678 Inst           inst,
679 RgBldPduInfo   *pdu,
680 Buffer         **txPdu,
681 RgErrInfo      *err
682 )
683 #else
684 PUBLIC S16 rgMUXBldPdu(inst, pdu, txPdu, err)
685 Inst           inst;
686 RgBldPduInfo   *pdu;
687 Buffer         **txPdu;
688 RgErrInfo      *err;
689 #endif
690 {
691    Buffer         *mBuf = NULLP;
692
693    TRC2(rgMUXBldPdu)
694
695  
696    if (rgGetMsg(inst, &mBuf) != ROK)
697    {
698       /* Buffer couldnt get allocated. Return a failure */
699       err->errCause = RGERR_MUX_MEM_ALLOC_FAIL;
700       err->errType = RGERR_MUX_BLD_PDU;
701       RLOG1(L_FATAL, "Memory allocation failed during MUXing of MAC TB: MacInst %d", inst);
702       RETVALUE(RFAILED);
703    }
704
705    if(rgMUXAddCes(inst, pdu, mBuf, err) != ROK)
706    {
707       RG_FREE_MSG(mBuf);
708       err->errType = RGERR_MUX_BLD_PDU;
709       RLOG1(L_ERROR, "Failed to Multiplex MAC CEs: MacInst %d", inst);
710       RETVALUE(RFAILED);
711    }
712
713    if(rgMUXAddSdus(inst, pdu, mBuf, err) != ROK)
714    {
715       RG_FREE_MSG(mBuf);
716       err->errType = RGERR_MUX_BLD_PDU;
717       RLOG1(L_ERROR, "FAILED to Multiplex MAC SDU: MacInst %d", inst);
718       RETVALUE(RFAILED);
719    }
720
721    *txPdu = mBuf;
722
723    RETVALUE(ROK);
724
725 }  /* rgMUXBldPdu */
726
727 #else /* else of ifndef L2_OPTMZ */
728
729 /**
730  * @brief Function to add SDU along with sub headers.
731  *
732  * @details
733  *
734  *     Function : rgMUXAddSdus
735  *     
736  *  @param[in]       RgBldPduInfo   *pdu
737  *  @param[out]      Buffer        *mBuf 
738  *  @param[out]      Buffer        *sduBuf 
739  *  @return    S16
740  *      -# ROK 
741  *      -# RFAILED
742  **/
743 #ifdef ANSI
744 PRIVATE S16 rgMUXAddSdus
745 (
746 Inst                inst,
747 RgBldPduInfo        *pdu,
748 Buffer              *sHdrBuf,
749 RgTfuDatReqTbInfo   *tb,
750 RgErrInfo           *err
751 )
752 #else
753 PRIVATE S16 rgMUXAddSdus(pdu, sHdrBuf, tb, err)
754 Inst                inst;
755 RgBldPduInfo        *pdu;
756 Buffer              *sHdrBuf;
757 RgTfuDatReqTbInfo   *tb;
758 RgErrInfo           *err;
759 #endif
760 {
761    RgRguDDatReqPerUe  *dDatReq;
762    RgRguCmnDatReq     *cDatReq;
763    U32 lchIdx, pduIdx;
764
765    TRC2(rgMUXAddSdus)
766
767    switch(pdu->reqType)
768    {
769       case EVTRGUCDATREQ:
770          cDatReq = (RgRguCmnDatReq *)(pdu->datReq);
771          /* Add sdu(s) to the Message Buffer */
772          if (NULLP != cDatReq)
773          {
774             if(rgMUXInsSdu(inst, &pdu->schdTbSz, 
775                      RG_CCCH_LCID, cDatReq->pdu, 
776                      sHdrBuf, NULLP, err) != ROK)
777             {
778                RETVALUE(RFAILED);
779             }
780             /* L2 Optimization for mUe/Tti: RLC pdu mbuf pointer will be passed
781              * to CL it is stored in DlHqProc->TbInfo and it will be used in
782              * case of harq retransmission. Store CCCH data at 0th index of
783              * lch array*/
784             tb->lchInfo[tb->numLch].mBuf[(tb->lchInfo[tb->numLch].numPdu)]\
785                = cDatReq->pdu;
786             tb->lchInfo[tb->numLch].numPdu++;
787             tb->numLch++;
788            RLOG3(L_INFO,"MSG4 is muxed  numLch=%ld numPdu=%ld tbaddr =%p", tb->numLch,tb->lchInfo[tb->numLch-1].numPdu, (U32)tb);
789          }
790          break;
791
792       case EVTRGUDDATREQ:
793          dDatReq = (RgRguDDatReqPerUe *)(pdu->datReq);
794          /* Add sdu(s) to the Message Buffer */
795          if (NULLP != dDatReq)
796          {
797             if(pdu->tbIndex == 1)
798             {
799                U16 idx1, idx2;
800                /* Adding this temporary variable for optimization */
801                RguDatReqTb *datReqTb = &dDatReq->datReqTb[0];
802              
803                tb->numLch = lchIdx = 0;
804
805                for (idx1=0; (idx1 < datReqTb->nmbLch); idx1++)
806                {
807                   tb->lchInfo[lchIdx].numPdu = pduIdx = 0;
808
809                   for(idx2=0;
810                      (idx2 < datReqTb->lchData[idx1].pdu.numPdu);
811                      idx2++)
812                   {
813                      if(pdu->schdTbSz)
814                      {
815                         if(rgMUXInsSdu(inst, &pdu->schdTbSz,
816                            datReqTb->lchData[idx1].lcId, 
817                            datReqTb->lchData[idx1].pdu.mBuf[idx2],
818                            sHdrBuf, NULLP, err) != ROK)
819                         {
820                            RGDBGERRNEW(inst,(rgPBuf(inst), "FAILED\n"));
821                            RETVALUE(RFAILED);
822                         }
823
824                         /* L2 Optimization for mUe/Tti:Increment numPdu by 1
825                          * Store pdu buffer in tb to send it to CL/PHY. Increment
826                          * numPdu by 1*/
827                         tb->lchInfo[lchIdx].mBuf[pduIdx] = datReqTb->lchData[idx1].pdu.mBuf[idx2];
828
829 #ifdef L2_OPTMZ
830                         if(datReqTb->lchData[idx1].freeBuff == FALSE)
831                         {/* Not incrementing refCnt for UM Mode. */
832                            tb->lchInfo[lchIdx].mBuf[pduIdx]->refCnt++;
833                         }
834 #endif
835 //UDAY 
836                         if(NULL != datReqTb->lchData[idx1].pdu.mBuf[idx2]->b_cont)
837                         {
838                              Buffer *tmp;
839                              tmp = datReqTb->lchData[idx1].pdu.mBuf[idx2]->b_cont;
840                              if(NULL == tmp->b_rptr)
841                              {
842                                 RLOG0(L_INFO,"11111Its Null here only ");
843                              }
844                         }
845                         else
846                         {
847                             RLOG0(L_INFO,"222222Its Null here only \n");
848                         }
849                         pduIdx++;
850                         //tb->lchInfo[tb->numLch].numPdu++;
851                         //tb->numLch++;
852
853                     }
854                   }
855                   
856                   if(pduIdx)
857                   {
858                     tb->lchInfo[lchIdx].numPdu = pduIdx;
859                     /* If Bearer is UM then MBUF to be free by MAC layer */
860                     tb->lchInfo[lchIdx].freeBuff = datReqTb->lchData[idx1].freeBuff;
861                     lchIdx++;
862                   }
863                }
864                tb->numLch = lchIdx;
865             }
866             else if(pdu->tbIndex == 2)
867             {
868                U16 idx1, idx2;
869                RguDatReqTb *datReqTb = &dDatReq->datReqTb[1];
870                tb->numLch = lchIdx = 0;
871          //      prc_trace_format_string(0x40,3,": AddSdus: numOfLch=%d numOfPdu=%d, schdSz=%d", datReqTb->nmbLch, datReqTb->lchData[0].pdu.numPdu, pdu->schdTbSz);
872               for (idx1=0; (idx1 < datReqTb->nmbLch); idx1++)
873                {
874                  tb->lchInfo[lchIdx].numPdu = pduIdx = 0;
875                  for(idx2=0;
876                      (idx2 < datReqTb->lchData[idx1].pdu.numPdu);
877                      idx2++)
878                   {
879                      if(pdu->schdTbSz)
880                      {
881                         if(rgMUXInsSdu(inst, &pdu->schdTbSz,
882                            datReqTb->lchData[idx1].lcId, 
883                            datReqTb->lchData[idx1].pdu.mBuf[idx2],
884                            sHdrBuf, NULLP, err) != ROK)
885                         {
886                            RGDBGERRNEW(inst,(rgPBuf(inst), "FAILED TB Size %d\n",
887                                     ((S16)pdu->schdTbSz)));
888                            RETVALUE(RFAILED);
889                         }
890                          /* L2 Optimization for mUe/Tti:Increment numPdu by 1
891                          * Store pdu buffer in tb to send it to CL/PHY. Increment
892                          * numPdu by 1*/
893                         tb->lchInfo[lchIdx].mBuf[pduIdx] = datReqTb->lchData[idx1].pdu.mBuf[idx2];
894 #ifdef L2_OPTMZ
895                         if(datReqTb->lchData[idx1].freeBuff == FALSE)
896                         {/* Not incrementing refCnt for UM Mode. */
897                            tb->lchInfo[lchIdx].mBuf[pduIdx]->refCnt++;
898                         }
899 #endif
900                         if(NULL != datReqTb->lchData[idx1].pdu.mBuf[idx2]->b_cont)
901                         {
902                              Buffer *tmp;
903                              tmp = datReqTb->lchData[idx1].pdu.mBuf[idx2]->b_cont;
904                              if(NULL == tmp->b_rptr)
905                              {
906                                 RLOG0(L_INFO,"2212121Its Null here only \n");
907                              }
908                         }
909                         else
910                         {
911                             RLOG0(L_INFO,"343343433ts Null here only \n");
912                         }
913                         pduIdx++;
914                        // tb->lchInfo[tb->numLch].numPdu++;
915                        // tb->numLch++;
916
917                      }
918                   }
919
920                   if(pduIdx)
921                   {
922                     tb->lchInfo[lchIdx].numPdu = pduIdx;
923                     /* If Bearer is UM then MBUF to be free by MAC layer */
924                     tb->lchInfo[lchIdx].freeBuff = datReqTb->lchData[idx1].freeBuff;
925                     lchIdx++;
926                   }
927                }
928
929                tb->numLch = lchIdx;
930            }
931          }
932          break;
933
934       case EVENT_SLOT_IND_TO_MAC:
935          break;
936       default:
937          break;
938    } /* End of switch(reqType) */
939
940    
941    if(rgMUXAddPadd(inst, &pdu->schdTbSz, sduBuf, NULLP, FALSE, err) != ROK)
942    {
943       //RGDBGERRNEW((rgPBuf, "FAILED"));
944       RETVALUE(RFAILED);
945    }
946    tb->padSize = padSize;
947
948    RETVALUE(ROK);
949 }
950
951 /**
952  * @brief Function to create MAC PDU from RLC SDUs and control elements, if any. 
953  *
954  * @details
955  *
956  *     Function : rgMUXBldPdu
957  *     -# This function shall be invoked by Downlink Harq Module as soon as a
958  *        Data request is received from RLC for a UE along with its stored 
959  *        control elements to create a MAC PDU.
960  *     -# It shall create subheaders for the control elements (timing advance
961  *        and contention resolution ID), if given, and then shall run through
962  *        all the logical channels and create subheader for each of the SDUs
963  *        given on that logical channel.
964  *     -# L2 Optimization for mUe/Tti: Avoiding muxing to reduce overhead of 
965  *           additional Mbuf allocation memory related operation.
966        -# MAC header, MAC CEs, MAC PDUs and MAC padding are stored in pre-
967             allocated mBufs. These pointers will not be freed by CL    
968  *     -# It shall invoke rgMUXPadPdu if the total length of the created 
969  *        buffer is less than the scheduled TB size.
970  *     -# At successfull operation of this function tb->macHdr, will have
971  *        complete MAC Header. tb->macCes will have MAC CEs if any. tb->
972  *        lchInfo[idx].mBuf[idx] will have MAC SDU per LCH per TB per UE 
973  *     
974  *           
975  *  @param[in]  RgBldPduInfo   *bldPdu
976  *  @param[out] RgTbInfo       *tb
977  *  @param[out] RgErrInfo      *err
978  *  @return  S16
979  *      -# ROK 
980  *      -# RFAILED 
981  **/
982 #ifdef ANSI
983 PUBLIC S16 rgMUXBldPdu
984 (
985 Inst               inst,
986 RgBldPduInfo       *pdu,
987 RgTfuDatReqTbInfo  *tb,
988 RgErrInfo          *err
989 )
990 #else
991 PUBLIC S16 rgMUXBldPdu(inst, pdu, tb, err)
992 Inst               inst;
993 RgBldPduInfo       *pdu;
994 RgTfuDatReqTbInfo  *tb;
995 RgErrInfo          *err;
996 #endif
997 {
998    Buffer         *mBuf1; /* MAC hearder */
999    Buffer         *mBuf2; /* MAC CEs */
1000    //U32            lchIdx, pduIdx;
1001
1002    TRC2(rgMUXBldPdu)
1003    
1004   /* Reseting macHdr and macCes pointers */
1005   if(tb->macHdr)
1006    SResetMBuf(tb->macHdr);
1007    if(tb->macCes)
1008    SResetMBuf(tb->macCes);
1009    
1010    mBuf1 = tb->macHdr; /* MAC hearder */
1011    mBuf2 = tb->macCes; /* MAC CEs */
1012    tb->tbSize  = pdu->schdTbSz;
1013
1014    if(rgMUXAddCes(inst, pdu, mBuf1, mBuf2, err) != ROK)
1015    {
1016       /* Reset rPtr and wPtr to the base of data buffer(db_base)*/
1017       RLOG0(L_INFO,"rgMUXBldPdu: rgMUXAddCes is Failed \n");
1018       RG_FREE_TB(tb);
1019       err->errType = RGERR_MUX_BLD_PDU;
1020       //RGDBGERRNEW((rgPBuf, "FAILED"));
1021       RETVALUE(RFAILED);
1022    }
1023    if(rgMUXAddSdus(inst, pdu, mBuf1, tb, err) != ROK)
1024    {
1025       /*TODO:MP Reset rPtr and wPtr to the base of data buffer(db_base)
1026        * Reset numLch and numPdu to zero and set MAC SDU buf to NULLP */
1027       RLOG0(L_INFO, "rgMUXBldPdu: rgMUXAddSdus is Failed \n");
1028       RG_FREE_TB(tb);
1029
1030       err->errType = RGERR_MUX_BLD_PDU;
1031       //RGDBGERRNEW((rgPBuf, "FAILED"));
1032       RETVALUE(RFAILED);
1033    }
1034 // UDAY 
1035 //      SPrntMsg(tb->macHdr, 0, 0);
1036 //   prc_trace_format_string(0x40,3,": padSize=%ld", tb->padSize);
1037
1038    tb->tbPres = TRUE;
1039    RETVALUE(ROK);
1040
1041 }  /* rgMUXBldPdu */
1042
1043 #endif /* end of L2_OPTMZ */
1044
1045 /**
1046  * @brief Function to create RAR PDU. 
1047  *
1048  * @details
1049  *
1050  *     Function : rgMUXBldRarPdu
1051  *                This function is used to build RAR PDUs and is being 
1052  *                invoked by the scheduler.
1053  *     
1054  *  @param[out]RgCellCb       *cellCb
1055  *  @param[in] RgRaRspAlloc   *bldPdu
1056  *  @param[in] Buffer         **txPdu 
1057  *  @param[out] RgErrInfo     *err
1058  *  @return    S16
1059  *      -# ROK 
1060  *      -# RFAILED 
1061  **/
1062 #ifdef ANSI
1063 PUBLIC S16 rgMUXBldRarPdu
1064 (
1065 RgCellCb        *cell,
1066 RgInfRaRntiInfo *alloc,
1067 Buffer          **txPdu,
1068 RgErrInfo       *err
1069 )
1070 #else
1071 PUBLIC S16 rgMUXBldRarPdu(cell, alloc, txPdu, err)
1072 RgCellCb        *cell;
1073 RgInfRaRntiInfo *alloc;
1074 Buffer          **txPdu;
1075 RgErrInfo       *err;
1076 #endif
1077 {
1078    Buffer      *datBuf = NULLP;
1079    S16         ret; 
1080    U8          data[RG_RAR_ELEM_LEN];
1081    U8          hdrByte;
1082    MsgLen      schdTbSz;
1083    U8          idx;
1084    Inst        inst = cell->macInst - RG_INST_START;
1085
1086    TRC2(rgMUXBldRarPdu)
1087
1088    schdTbSz = alloc->schdTbSz;
1089    /* RAR PDU Requirements */
1090    /*
1091    1. SubHeader - R/T/RAPID. //5GNR, changed E to R
1092    2. TA ( if applicable)
1093    3. Ul Grant:
1094          a. Hopping Flag - 1 Bit.
1095          b. Fixed Size RB Assignment. - 10 Bits.
1096          c. Truncated Modulation and coding scheme - 4 Bits.
1097          d. TPC command for scheduled PUSCH. - 3 Bits.
1098          e. UL Delay - 1 Bit.
1099          f. CQI Request - 1 Bit.
1100    4. Temporary Crnti.
1101    */
1102
1103    /* Initialize the error type */
1104    err->errType = RGERR_MUX_BLD_RAR_PDU;
1105   
1106    if ((ret = rgGetMsg(inst,&datBuf)) != ROK)
1107    {
1108       /* Buffer couldnt get allocated. Return a failure */
1109       err->errCause = RGERR_MUX_MEM_ALLOC_FAIL;
1110       RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "FAILED to getMsg");
1111       RETVALUE(RFAILED);
1112    }
1113
1114    if (TRUE == alloc->backOffInd.pres)
1115    {
1116       /*Set T Bit , NO E bit Required */
1117       hdrByte = 0x00;
1118       /* Add the bi */
1119       hdrByte |= (0x0F & (alloc->backOffInd.val));
1120
1121       /* Add the header */
1122       RG_PACK_RAR_SHDR(hdrByte, datBuf, ret);
1123       if(ret != ROK)
1124       {
1125          err->errCause = RGERR_MUX_BLD_BI_FAIL;
1126          RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"RGERR_MUX_BLD_BI_FAIL");
1127          RG_FREE_MSG(datBuf);
1128          RETVALUE(RFAILED);
1129       }
1130       schdTbSz--;
1131    }
1132
1133    for (idx=0; idx < (alloc->numCrnti) && 
1134          (schdTbSz >= RG_RAR_ELEM_LEN+RG_RAR_SHDR_LEN); idx++)
1135    {
1136       /* Add the tBit */
1137       hdrByte = 0x40; 
1138       /* Add the rapId */
1139       hdrByte |= (0x3F & (alloc->crntiInfo[idx].rapId));
1140
1141          /* Add the header */
1142          RG_PACK_RAR_SHDR(hdrByte, datBuf, ret);
1143          if(ret != ROK)
1144          {
1145             err->errCause = RGERR_MUX_BLD_RAPIDHDR_FAIL;
1146             RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"RGERR_MUX_BLD_RAPIDHDR_FAIL");
1147             RG_FREE_MSG(datBuf);
1148             RETVALUE(RFAILED);
1149          }
1150
1151       /* Prepare the data */
1152       data[0]  =  0x7F & ((alloc->crntiInfo[idx].ta.val) >> 4);
1153       data[1] = 0;
1154       data[2] = 0;
1155       data[3] = 0;
1156       {    
1157          rgMUXGet20bitRarGrnt(cell->bwCfg.ulTotalBw, &(alloc->crntiInfo[idx].grnt), &data[1]);
1158       }
1159       data[1] |=  ((U8)((alloc->crntiInfo[idx].ta.val) << 4));
1160       data[4]  =  (alloc->crntiInfo[idx].tmpCrnti) >> 8;
1161       data[5]  =  (U8) (alloc->crntiInfo[idx].tmpCrnti);
1162
1163       RLOG_ARG2(L_DEBUG,DBG_CELLID,cell->cellId,
1164                         "Rar,Rapid=%d, Temp CRNTI:%d", 
1165                 alloc->crntiInfo[idx].rapId,
1166                 alloc->crntiInfo[idx].tmpCrnti);
1167      MS_BUF_ADD_ALLOC_CALLER();
1168       if(SAddPstMsgMult(&data[0], RG_RAR_ELEM_LEN, datBuf) != ROK)
1169       {
1170          err->errCause = RGERR_MUX_BLD_RAPID_FAIL;
1171          RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"RGERR_MUX_BLD_RAPID_FAIL");
1172          RG_FREE_MSG(datBuf);
1173          RETVALUE(RFAILED);
1174       }
1175       schdTbSz -= RG_RAR_ELEM_LEN+RG_RAR_SHDR_LEN;
1176    }
1177
1178    if(rgMUXAddPadd(inst,&schdTbSz, datBuf, TRUE, err) != ROK)
1179    {
1180       RG_FREE_MSG(datBuf);
1181       RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"FAILED to mux add padding");
1182       RETVALUE(RFAILED);
1183    }
1184
1185    *txPdu = datBuf;
1186
1187    RETVALUE(ROK);
1188 } /* rgMUXBldRarPdu */
1189
1190 /***********************************************************
1191  *
1192  *     Func : rgMUXGet20bitRarGrnt
1193  *
1194  *     Desc : This function fills up the 20-bit grant
1195  *            for RA response.
1196  *
1197  *     Ret  : None.
1198  *
1199  *     Notes: None.
1200  *
1201  *     File : rg_mux.c
1202  *
1203  **********************************************************/
1204 #ifdef ANSI
1205 PRIVATE Void rgMUXGet20bitRarGrnt
1206 (
1207 U8             ulBw,
1208 RgInfRarUlGrnt *msg3Grnt,
1209 U8             *grnt
1210 )
1211 #else
1212 PRIVATE Void rgMUXGet20bitRarGrnt(ulBw, msg3Grnt, grnt)
1213 U8             ulBw;
1214 RgInfRarUlGrnt *msg3Grnt;
1215 U8             *grnt;
1216 #endif
1217 {
1218    U16       riv = rgMUXCalcRiv(ulBw, msg3Grnt->rbStart, msg3Grnt->numRb);
1219
1220    TRC2(rgMUXGet20bitRarGrnt);
1221
1222    grnt[2]  = msg3Grnt->cqiBit;   /* cqi bit is 0, output from sched */
1223    grnt[2] |= (msg3Grnt->delayBit << 1);
1224    grnt[2] |= (msg3Grnt->tpc << 2);
1225    grnt[2] |= (msg3Grnt->iMcsCrnt << 5);
1226
1227    grnt[1]  = (msg3Grnt->iMcsCrnt >> 3);
1228    /* Forcing right shift to insert 0 as the LSB: 
1229     * since this is assumed in the computation */
1230    grnt[1] |= (U8)((riv << 1) & 0xFE);
1231
1232    grnt[0]  = (U8)((riv >> 7) & 0x07);
1233    grnt[0] |= ((msg3Grnt->hop & 0x01) << 3);
1234
1235    RETVOID;
1236 } /* rgMUXGet20bitRarGrnt */
1237
1238 /***********************************************************
1239  *
1240  *     Func : rgMUXCalcRiv
1241  *
1242  *     Desc : This function calculates RIV.
1243  *
1244  *     Ret  : None.
1245  *
1246  *     Notes: None.
1247  *
1248  *     File : rg_mux.c
1249  *
1250  **********************************************************/
1251 #ifdef ANSI
1252 PUBLIC U16 rgMUXCalcRiv
1253 (
1254 U8           bw,
1255 U8           rbStart,
1256 U8           numRb
1257 )
1258 #else
1259 PUBLIC U16 rgMUXCalcRiv(bw, rbStart, numRb)
1260 U8           bw;
1261 U8           rbStart;
1262 U8           numRb;
1263 #endif
1264 {
1265    U8           numRbMinus1 = numRb - 1;
1266    U16          riv;
1267
1268    TRC2(rgMUXCalcRiv);
1269
1270    if (numRbMinus1 <= bw/2)
1271    {
1272       riv = bw * numRbMinus1 + rbStart;
1273    }
1274    else
1275    {
1276       riv = bw * (bw - numRbMinus1) + (bw - rbStart - 1);
1277    }
1278    RETVALUE(riv);
1279 } /* rgMUXCalcRiv */
1280
1281
1282
1283 /**********************************************************************
1284  
1285          End of file
1286 **********************************************************************/