[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-523] Statistics Response between DU APP and...
[o-du/l2.git] / src / 5gnrsch / sch_common.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:     5G NR SCH layer
22
23 Type:     C source file
24
25 Desc:     C source code for Entry point fucntions
26
27 File:     sch_common.c
28
29  **********************************************************************/
30
31 /** @file sch_common.c
32   @brief This module performs common scheduling
33  */
34 #include "common_def.h"
35 #include "tfu.h"
36 #include "lrg.h"
37
38 #include "tfu.x"
39 #include "lrg.x"
40 #include "du_log.h"
41 #include "du_app_mac_inf.h"
42 #include "mac_sch_interface.h"
43 #include "sch.h"
44 #include "sch_tmr.h"
45 #include "sch_utils.h"
46
47 /**
48  * @brief common resource allocation for SSB
49  *
50  * @details
51  *
52  *     Function : schBroadcastSsbAlloc
53  *     
54  *     This function handles common scheduling for SSB
55  *     
56  *  @param[in]  SchCellCb *cell, cell cb
57  *  @param[in]  DlBrdcstAlloc *dlBrdcstAlloc, DL brdcst allocation
58  *  @return  void
59  **/
60 uint8_t schBroadcastSsbAlloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
61 {
62    /* schedule SSB */
63    uint8_t ssbStartSymb, idx;
64    uint16_t ssbStartPrb;
65    SchDlSlotInfo *schDlSlotInfo;
66    SsbInfo ssbInfo;
67
68    if(cell == NULL)
69    {
70       DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : Cell is NULL");
71       return RFAILED;
72    }
73
74    if(dlBrdcstAlloc == NULL)
75    {
76       DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : dlBrdcstAlloc is NULL");
77       return RFAILED;
78    }
79
80    schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
81    ssbStartPrb = cell->cellCfg.ssbSubcOffset; //+Kssb
82    ssbStartSymb = cell->ssbStartSymbArr[dlBrdcstAlloc->ssbIdxSupported-1]; /*since we are supporting only 1 ssb beam */
83
84    /* Assign interface structure */
85    for(idx=0; idx<dlBrdcstAlloc->ssbIdxSupported; idx++)
86    {
87       ssbInfo.ssbIdx              = idx;
88       ssbInfo.fdAlloc.startPrb    = ssbStartPrb;
89       ssbInfo.fdAlloc.numPrb      = SCH_SSB_NUM_PRB;
90       ssbInfo.tdAlloc.startSymb   = ssbStartSymb;
91       ssbInfo.tdAlloc.numSymb     = SCH_SSB_NUM_SYMB;
92       dlBrdcstAlloc->ssbInfo[idx] = ssbInfo;
93       schDlSlotInfo->ssbInfo[idx] = ssbInfo;
94    }
95
96    if((allocatePrbDl(cell, slotTime, ssbStartSymb, SCH_SSB_NUM_SYMB, &ssbInfo.fdAlloc.startPrb, ssbInfo.fdAlloc.numPrb)) != ROK)
97    {
98        DU_LOG("\nERROR  -->  SCH: PRB allocation failed for SSB in SFN:SLOT [%d : %d]", slotTime.sfn, slotTime.slot);
99        return RFAILED;
100    }
101
102
103    schDlSlotInfo->ssbPres = true;
104    schDlSlotInfo->ssbIdxSupported = dlBrdcstAlloc->ssbIdxSupported;
105    return ROK;
106 }
107
108 /**
109  * @brief common resource allocation for SIB1
110  *
111  * @details
112  *
113  *     Function : schBroadcastSib1Alloc
114  *     
115  *     This function handles common scheduling for SIB1
116  *     
117  *  @param[in]  SchCellCb *cell, cell cb
118  *  @param[in]  DlBrdcstAlloc *dlBrdcstAlloc, DL brdcst allocation
119  *  @return  void
120  **/
121 uint8_t schBroadcastSib1Alloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
122 {
123    uint8_t dmrsStartSymbol, startSymbol, numSymbol ;
124    DmrsInfo dmrs;
125    PdschFreqAlloc freqAlloc;
126    PdschTimeAlloc timeAlloc;
127    SchDlSlotInfo *schDlSlotInfo = NULLP;
128
129    if(cell == NULL)
130    {
131       DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : Cell is NULL");
132       return RFAILED;
133    }
134
135    if(dlBrdcstAlloc == NULL)
136    {
137       DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : dlBrdcstAlloc is NULL");
138       return RFAILED;
139    }
140    
141    dlBrdcstAlloc->crnti = SI_RNTI;
142    dmrs = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.dmrs;
143    freqAlloc = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc;
144    timeAlloc = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschTimeAlloc;
145    schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
146
147    /* Find total symbols used including DMRS */
148    /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
149     * in that case only PDSCH symbols are marked as occupied */
150    dmrsStartSymbol = findDmrsStartSymbol(dmrs.dlDmrsSymbPos);   
151    if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
152    {
153       startSymbol = timeAlloc.startSymb;
154       numSymbol = timeAlloc.numSymb;
155    }
156    /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
157    else
158    {
159       startSymbol = dmrsStartSymbol;
160       numSymbol = dmrs.nrOfDmrsSymbols + timeAlloc.numSymb;
161    }
162
163    /* Allocate PRB */
164    if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol, &freqAlloc.startPrb, freqAlloc.numPrb)) != ROK)
165    {
166        DU_LOG("\nERROR  -->  SCH: PRB allocation failed for SIB1 in SFN:Slot [%d : %d]", slotTime.sfn, slotTime.slot);
167        return RFAILED;
168    }
169
170    memcpy(&dlBrdcstAlloc->sib1Alloc.bwp, &cell->sib1SchCfg.bwp, sizeof(BwpCfg)); 
171    SCH_ALLOC(dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg,sizeof(PdcchCfg));
172    if(dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg)
173    {
174       memcpy(dlBrdcstAlloc->sib1Alloc.sib1PdcchCfg, &cell->sib1SchCfg.sib1PdcchCfg, sizeof(PdcchCfg)); 
175       schDlSlotInfo->sib1Pres = true;
176    }
177    else
178    {
179       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in %s", __func__);
180       return RFAILED;
181    }
182    return ROK;
183 }
184
185 /*******************************************************************
186  *
187  * @brief Handles sending UL scheduler info to MAC 
188  *
189  * @details
190  *
191  *    Function : sendUlSchInfoToMac
192  *
193  *    Functionality:
194  *     Sends UL Sch info to MAC from SCH
195  *
196  * @params[in] 
197  * @return ROK     - success
198  *         RFAILED - failure
199  *
200  * ****************************************************************/
201 int sendUlSchInfoToMac(UlSchedInfo *ulSchedInfo, Inst inst)
202 {
203    Pst pst;
204
205    memset(&pst, 0, sizeof(Pst));
206    FILL_PST_SCH_TO_MAC(pst, inst);
207    pst.event = EVENT_UL_SCH_INFO;
208
209    return(MacMessageRouter(&pst, (void *)ulSchedInfo));
210 }
211
212 /**
213  * @brief Function to fill Pucch Format 0
214  *
215  * @details
216  *
217  *     Function : fillPucchFormat0
218  *     
219  *     Function to fill Pucch format 0
220  *     
221  *  @param[in]  SchPucchInfo pointer, SchPucchResrcInfo pointer
222  *  @return  void
223  **/
224
225 void fillPucchFormat0(SchPucchInfo *ulSchedPucch, SchPucchResrcInfo *resrcInfo)
226 {
227    if(resrcInfo->SchPucchFormat.format0)
228    {
229       ulSchedPucch->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
230       ulSchedPucch->pucchFormat  = PUCCH_FORMAT_0;
231       ulSchedPucch->initialCyclicShift =  resrcInfo->SchPucchFormat.format0->initialCyclicShift;
232       ulSchedPucch->tdAlloc.numSymb = resrcInfo->SchPucchFormat.format0->numSymbols;
233       ulSchedPucch->tdAlloc.startSymb = resrcInfo->SchPucchFormat.format0->startSymbolIdx;
234    }
235 }
236
237 /**
238  * @brief Function to fill Pucch Format 1
239  *
240  * @details
241  *
242  *     Function : fillPucchFormat1
243  *     
244  *     Function to fill Pucch format 1
245  *     
246  *  @param[in]  SchPucchInfo pointer, SchPucchResrcInfo pointer
247  *  @return  void
248  **/
249
250 void fillPucchFormat1(SchPucchInfo *ulSchedPucch, SchPucchResrcInfo *resrcInfo)
251 {
252    if(resrcInfo->SchPucchFormat.format1)
253    {
254       ulSchedPucch->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
255       ulSchedPucch->pucchFormat  = PUCCH_FORMAT_1;
256       ulSchedPucch->initialCyclicShift =  resrcInfo->SchPucchFormat.format1->initialCyclicShift;
257       ulSchedPucch->tdAlloc.numSymb = resrcInfo->SchPucchFormat.format1->numSymbols;
258       ulSchedPucch->tdAlloc.startSymb = resrcInfo->SchPucchFormat.format1->startSymbolIdx;
259       ulSchedPucch->timeDomOCC =  resrcInfo->SchPucchFormat.format1->timeDomOCC;
260   }
261 }
262
263 /**
264  * @brief Function to fill Pucch format for UL Sched Info
265  *
266  * @details
267  *
268  *     Function : fillUlSchedPucchFormat
269  *     
270  *     Function to fill Pucch format for UL Sched Info
271  *     
272  *  @param[in]  pucchFormat , SchPucchInfo pointer,
273  *  @param[in]  SchPucchFormatCfg pointer, SchPucchResrcInfo pointer
274  *  @return  void
275  **/
276
277 uint8_t fillUlSchedPucchFormat(uint8_t pucchFormat, SchPucchInfo *ulSchedPucch,\
278    SchPucchResrcInfo *resrcInfo, SchPucchFormatCfg *formatCfg)
279 {
280    uint8_t ret = ROK;
281
282    switch(pucchFormat)
283    {
284       case PUCCH_FORMAT_0:
285          {
286             if(resrcInfo)
287                fillPucchFormat0(ulSchedPucch, resrcInfo);
288             return ret;
289          }
290       case PUCCH_FORMAT_1:
291          {
292             if(resrcInfo)
293             {
294                fillPucchFormat1(ulSchedPucch, resrcInfo);
295             }
296             if(formatCfg)
297             {
298                ulSchedPucch->addDmrs = formatCfg->addDmrs;
299                ulSchedPucch->pi2BPSK = formatCfg->pi2BPSK;
300             }
301             return ret;
302          }/* To Add support for more Pucch Format */
303
304       default:
305          DU_LOG("\nERROR  --> SCH : Invalid PUCCH format[%d] in fillUlSchedPucchFormatCfg()", pucchFormat);
306          ret = RFAILED;
307          return ret;
308    }
309    return ret;
310 }
311
312 /**
313  * @brief Function to fill Pucch Dedicated Cfg for UL Sched Info
314  *
315  * @details
316  *
317  *     Function : fillUlSchedPucchDedicatedCfg
318  *     
319  *     Function to fill Pucch Dedicated Cfg for UL Sched Info
320  *     
321  *  @param[in]  pucchFormat to be filled
322  *  @param[in]  SchPucchFormatCfg pointer, SchPucchCfg pointer
323  *  @return  void
324  **/
325
326 uint8_t fillUlSchedPucchDedicatedCfg(SchCellCb *cell, SchPucchCfg *pucchDedCfg,\
327    SlotTimingInfo *slotInfo, SchPucchInfo *ulSchedPucch)
328 {
329    uint8_t ret, resrcSetIdx, resrcIdx, schedReqIdx, srPeriodicity = 0;
330    uint16_t srOffset = 0;
331    uint16_t numSlots = cell->numSlots;
332    bool isAllocated = false;
333    uint16_t pucchStartPrb;
334    ret = ROK;
335    if(pucchDedCfg->resrcSet && pucchDedCfg->resrc)
336    {
337       //Assuming one entry in the list
338       for(resrcSetIdx = 0; resrcSetIdx < pucchDedCfg->resrcSet->resrcSetToAddModListCount; resrcSetIdx++)
339       {
340          for(resrcIdx = 0; resrcIdx < pucchDedCfg->resrc->resrcToAddModListCount; resrcIdx++)
341          {
342             if(pucchDedCfg->resrcSet->resrcSetToAddModList[resrcSetIdx].resrcList[resrcSetIdx] ==\
343                   pucchDedCfg->resrc->resrcToAddModList[resrcIdx].resrcId)
344             {
345                ulSchedPucch->intraFreqHop = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].intraFreqHop;
346                ulSchedPucch->secondPrbHop = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].secondPrbHop;
347                ulSchedPucch->fdAlloc.startPrb = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].startPrb;
348                ulSchedPucch->pucchFormat = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].pucchFormat;
349                ret = fillUlSchedPucchFormat(ulSchedPucch->pucchFormat, ulSchedPucch,\
350                      &pucchDedCfg->resrc->resrcToAddModList[resrcIdx], NULLP);
351                if(ret == RFAILED)
352                   return ret;
353
354                pucchStartPrb = pucchDedCfg->resrc->resrcToAddModList[resrcIdx].startPrb;
355                ret = allocatePrbUl(cell, *slotInfo, ulSchedPucch->tdAlloc.startSymb, ulSchedPucch->tdAlloc.numSymb, &pucchStartPrb, PUCCH_NUM_PRB_FORMAT_0_1_4);
356                if(ret == ROK)
357                {
358                   isAllocated = true;
359                   break;
360                }
361             }
362          }
363          if(isAllocated)
364          break;
365       }
366    }
367
368    if(pucchDedCfg->format1)
369    {
370       ret = fillUlSchedPucchFormat(ulSchedPucch->pucchFormat, ulSchedPucch, NULLP, pucchDedCfg->format1);
371       if(ret == RFAILED)
372          return ret;
373    }
374
375    if(!isAllocated)
376    {
377       return RFAILED;
378    }
379
380    /* setting SR and UCI flag */
381    if(pucchDedCfg->schedReq)
382    {
383       for(schedReqIdx = 0; schedReqIdx < pucchDedCfg->schedReq->schedAddModListCount; schedReqIdx++)
384       {
385          srPeriodicity = pucchDedCfg->schedReq->schedAddModList[schedReqIdx].periodicity;
386          srOffset      = pucchDedCfg->schedReq->schedAddModList[schedReqIdx].offset;
387          break;
388       }
389       if(((numSlots * slotInfo->sfn + slotInfo->slot - srOffset) % srPeriodicity) == 0)
390       {
391          ulSchedPucch->srFlag  = true;
392       }
393    }
394    return ret;
395 }
396
397 /**
398  * @brief Function to fill Pucch Resource Info
399  *
400  * @details
401  *
402  *     Function : fillPucchResourceInfo
403  *     
404  *     Function to fill Pucch Resource Info
405  *     
406  *  @param[in]  SchPucchInfo *schPucchInfo, Inst inst
407  *  @return  ROK/RFAILED
408  **/
409
410 uint16_t fillPucchResourceInfo(uint8_t ueId, SchPucchInfo *schPucchInfo, Inst inst, SlotTimingInfo slotInfo)
411 {
412    uint8_t ret = ROK,  ueIdx = 0, pucchIdx = 0;
413    SchCellCb  *cell = schCb[inst].cells[inst];
414    SchPucchCfgCmn *pucchCfg = NULLP;
415    SchBwpParams *ulBwp = NULLP;
416 #ifdef NR_DRX 
417    SchUeCb *ueCb = NULLP;
418 #endif
419    uint16_t startPrb;
420
421    ueIdx = ueId -1;
422 #ifdef NR_DRX 
423    ueCb = &(cell->ueCb[ueIdx]); 
424    if(ueCb->ueDrxInfoPres)
425    {
426       if(!ueCb->drxUeCb.drxUlUeActiveStatus)
427          return RFAILED;
428    }
429 #endif
430    if(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfgPres)
431    {
432       /* fill pucch dedicated cfg */
433       ret = fillUlSchedPucchDedicatedCfg(cell,\
434        &cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg, &slotInfo, schPucchInfo);
435       if(ret == RFAILED)
436       {
437          memset(schPucchInfo, 0, sizeof(SchPucchInfo));
438          DU_LOG("\nERROR  --> SCH : Filling PUCCH dedicated cfg failed at fillPucchResourceInfo()");
439          return ret;
440       }
441    }
442    else
443    {
444       /* fill pucch common cfg */
445       /* derive pucchResourceSet from schCellCfg */
446       pucchCfg = &cell->cellCfg.ulCfgCommon.schInitialUlBwp.pucchCommon;
447       pucchIdx = pucchCfg->pucchResourceCommon;
448       ulBwp = &cell->cellCfg.ulCfgCommon.schInitialUlBwp.bwp;
449       startPrb = ulBwp->freqAlloc.startPrb + pucchResourceSet[pucchIdx][3];
450       ret = allocatePrbUl(cell, slotInfo, pucchResourceSet[pucchIdx][1], pucchResourceSet[pucchIdx][2],\
451             &startPrb, PUCCH_NUM_PRB_FORMAT_0_1_4);
452       if (ret == ROK)
453       {
454          schPucchInfo->fdAlloc.startPrb = ulBwp->freqAlloc.startPrb + pucchResourceSet[pucchIdx][3];
455          schPucchInfo->fdAlloc.numPrb = PUCCH_NUM_PRB_FORMAT_0_1_4;
456          schPucchInfo->tdAlloc.startSymb = pucchResourceSet[pucchIdx][1];
457          schPucchInfo->tdAlloc.numSymb = pucchResourceSet[pucchIdx][2];
458          schPucchInfo->pucchFormat = pucchResourceSet[pucchIdx][0];
459
460          /* set SR and UCI flag to false */
461          schPucchInfo->srFlag  = true;
462       }
463    }
464    return ROK;
465 }
466
467 /**
468  * @brief resource allocation for UL
469  *
470  * @details
471  *
472  *     Function : schUlResAlloc
473  *     
474  *     This function handles UL Resource allocation
475  *     
476  *  @param[in]  SchCellCb *cell, cellCb
477  *  @return  void
478  **/
479 uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
480 {
481    int ret = ROK;
482 #ifdef NR_DRX 
483    SchUeCb   *ueCb;
484 #endif
485    UlSchedInfo ulSchedInfo;
486    SchUlSlotInfo  *schUlSlotInfo = NULLP;
487    SlotTimingInfo ulTimingInfo;
488    memset(&ulSchedInfo, 0, sizeof(UlSchedInfo));
489
490    /* add PHY delta */
491    ADD_DELTA_TO_TIME(cell->slotInfo,ulTimingInfo,PHY_DELTA_UL+SCHED_DELTA, cell->numSlots);
492
493    ulSchedInfo.cellId = cell->cellId;
494    ulSchedInfo.slotIndInfo.cellId = ulSchedInfo.cellId;
495    ulSchedInfo.slotIndInfo.sfn = ulTimingInfo.sfn;
496    ulSchedInfo.slotIndInfo.slot = ulTimingInfo.slot;
497
498    /* Schedule resources for PRACH */
499    if(cell->firstSib1Transmitted)
500     schPrachResAlloc(cell, &ulSchedInfo, ulTimingInfo);
501
502    schUlSlotInfo = cell->schUlSlotInfo[ulTimingInfo.slot]; 
503    if(schUlSlotInfo->schPuschInfo)
504    {
505       GET_CRNTI(ulSchedInfo.crnti, schUlSlotInfo->puschUe);
506       /* Check the ue drx status if the UE is active for uplink scheduling or not  */
507 #ifdef NR_DRX 
508       ueCb = schGetUeCb(cell, ulSchedInfo.crnti);
509       if(ueCb->ueDrxInfoPres)
510       {
511          if(!ueCb->drxUeCb.drxUlUeActiveStatus)
512             return RFAILED;
513       }
514 #endif
515       ulSchedInfo.dataType |= SCH_DATATYPE_PUSCH;
516       memcpy(&ulSchedInfo.schPuschInfo, schUlSlotInfo->schPuschInfo,
517             sizeof(SchPuschInfo));
518       SCH_FREE(schUlSlotInfo->schPuschInfo, sizeof(SchPuschInfo));
519       schUlSlotInfo->schPuschInfo = NULL;
520    }
521
522    if(schUlSlotInfo->pucchPres)
523    {
524       GET_CRNTI(ulSchedInfo.crnti, schUlSlotInfo->pucchUe);
525       ret = fillPucchResourceInfo(schUlSlotInfo->pucchUe, &schUlSlotInfo->schPucchInfo, schInst, ulTimingInfo);
526       if (ret == ROK)
527       {
528          ulSchedInfo.dataType |= SCH_DATATYPE_UCI;
529          memcpy(&ulSchedInfo.schPucchInfo, &schUlSlotInfo->schPucchInfo,
530                sizeof(SchPucchInfo));
531       }
532       else
533       {
534          return RFAILED;
535       }
536       memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
537    }
538
539    /* Send msg to MAC */
540    ret = sendUlSchInfoToMac(&ulSchedInfo, schInst);
541    if(ret != ROK)
542    {
543       DU_LOG("\nERROR  -->  SCH : Sending UL Sch info from SCH to MAC failed");
544    }
545
546    /* Update UL statistics */
547    if(schCb[schInst].statistics.ulTotalPrbUsage)
548    {
549       schCb[schInst].statistics.ulTotalPrbUsage->numPrbUsedForTx += schUlSlotInfo->prbAlloc.numPrbAlloc; 
550       schCb[schInst].statistics.ulTotalPrbUsage->totalPrbAvailForTx += MAX_NUM_RB;
551    }
552
553    /* Re-initialize UL Slot */
554    schInitUlSlot(schUlSlotInfo);
555    return ret;
556 }
557
558 /*******************************************************************
559  *
560  * @brief Fills pdcch and pdsch info for msg4
561  *
562  * @details
563  *
564  *    Function : schDlRsrcAllocMsg4
565  *
566  *    Functionality:
567  *       Fills pdcch and pdsch info for msg4
568  *
569  * @params[in] SchCellCb *cell, SlotTimingInfo msg4Time
570  * @params[in] uint8_t ueId, DlMsgSchInfo *dlMsgAlloc
571  * @params[in] uint8_t pdschStartSymbol, uint8_t pdschNumSymbols
572  * @params[in] bool isRetx, SchDlHqProcCb *hqP
573  * @return ROK     - success
574  *         RFAILED - failure
575  *
576  * ****************************************************************/
577 uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo msg4Time, uint8_t ueId, DlMsgSchInfo *dlMsgAlloc,\
578                            uint8_t pdschStartSymbol, uint8_t pdschNumSymbols, bool isRetx, SchDlHqProcCb *hqP)
579 {
580    uint8_t coreset0Idx = 0;
581    uint8_t firstSymbol = 0;
582    uint8_t numSymbols = 0;
583    uint8_t mcs = DEFAULT_MCS;                         /* MCS fixed to 4 */
584    uint8_t dmrsStartSymbol = 0, startSymbol = 0, numSymbol = 0;
585    uint16_t tbSize = 0;
586    uint16_t numRbs;
587    SchBwpDlCfg *initialBwp = NULLP;
588    PdcchCfg *pdcch = NULLP;
589    PdschCfg *pdsch = NULLP;
590    BwpCfg *bwp = NULLP;
591    DlMsgSchInfo *msg4Alloc = NULLP;
592
593    if(cell == NULL)
594    {
595       DU_LOG("\nERROR  -->  SCH: schDlRsrcAllocMsg4() : Cell is NULL");
596       return RFAILED;
597    }
598
599    if(dlMsgAlloc == NULL)
600    {
601       DU_LOG("\nERROR  -->  SCH: schDlRsrcAllocMsg4() :  dlMsgAlloc is NULL");
602       return RFAILED;
603    }
604
605    msg4Alloc = dlMsgAlloc;
606    initialBwp   = &cell->cellCfg.dlCfgCommon.schInitialDlBwp;
607    SCH_ALLOC(msg4Alloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
608
609    if(!msg4Alloc->dlMsgPdcchCfg)
610    {
611       DU_LOG("\nERROR  --> SCH : Memory allocation failed in %s",__func__);
612       return RFAILED;
613    }
614    pdcch = msg4Alloc->dlMsgPdcchCfg;
615    bwp = &msg4Alloc->bwp;
616    coreset0Idx  = initialBwp->pdcchCommon.commonSearchSpace.coresetId;
617
618    fillDlMsgInfo(msg4Alloc, cell->raCb[ueId-1].tcrnti, isRetx, hqP);
619    msg4Alloc->dlMsgPduLen = cell->raCb[ueId-1].dlMsgPduLen;
620
621    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
622    numRbs     = coresetIdxTable[coreset0Idx][1];
623    numSymbols = coresetIdxTable[coreset0Idx][2];
624
625    /* calculate time domain parameters */
626    uint16_t mask = 0x2000;
627    for(firstSymbol=0; firstSymbol<MAX_SYMB_PER_SLOT; firstSymbol++)
628    {
629       if(initialBwp->pdcchCommon.commonSearchSpace.monitoringSymbol & mask)
630          break;
631       else
632          mask = mask>>1;
633    }
634
635    /* fill BWP */
636    bwp->freqAlloc.numPrb   = initialBwp->bwp.freqAlloc.numPrb;
637    bwp->freqAlloc.startPrb = initialBwp->bwp.freqAlloc.startPrb;
638    bwp->subcarrierSpacing  = initialBwp->bwp.scs;
639    bwp->cyclicPrefix       = initialBwp->bwp.cyclicPrefix;
640
641    /* fill the PDCCH PDU */
642    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
643    pdcch->coresetCfg.durationSymbols = numSymbols;
644    memcpy(pdcch->coresetCfg.freqDomainResource, \
645       cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
646
647    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
648    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
649    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
650    pdcch->coresetCfg.coreSetType = 0;
651    pdcch->coresetCfg.coreSetSize = numRbs;
652    pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
653    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
654    pdcch->numDlDci = 1;
655    pdcch->dci.rnti = cell->raCb[ueId-1].tcrnti;
656    pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
657    pdcch->dci.scramblingRnti = 0;
658    pdcch->dci.cceIndex = 4; /* considering SIB1 is sent at cce 0-1-2-3 */
659    pdcch->dci.aggregLevel = 4;
660    pdcch->dci.beamPdcchInfo.numPrgs = 1;
661    pdcch->dci.beamPdcchInfo.prgSize = 1;
662    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
663    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
664    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
665    pdcch->dci.txPdcchPower.beta_pdcch_1_0 = 0;
666    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
667    pdsch = &pdcch->dci.pdschCfg; 
668    
669    /* fill the PDSCH PDU */
670    uint8_t cwCount = 0;
671    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
672    pdsch->rnti = cell->raCb[ueId-1].tcrnti;
673    pdsch->pduIndex = 0;
674    pdsch->numCodewords = 1;
675    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
676    {
677       pdsch->codeword[cwCount].targetCodeRate = 308;
678       pdsch->codeword[cwCount].qamModOrder = 2;
679       pdsch->codeword[cwCount].mcsIndex = mcs; /* mcs configured to 4 */
680       pdsch->codeword[cwCount].mcsTable = 0; /* notqam256 */
681       if(isRetx != TRUE)
682       {
683          tbSize = schCalcTbSize(msg4Alloc->dlMsgPduLen + TX_PAYLOAD_HDR_LEN); /* MSG4 size + FAPI header size*/
684          hqP->tbInfo[cwCount].tbSzReq = tbSize;
685          pdsch->codeword[cwCount].rvIndex = 0;
686       }
687       else
688       {
689          pdsch->codeword[cwCount].rvIndex = (pdsch->codeword[cwCount].rvIndex +1) & 0x03;
690          tbSize = hqP->tbInfo[cwCount].tbSzReq;
691       }
692       pdsch->codeword[cwCount].tbSize = tbSize;
693    }
694    pdsch->dataScramblingId = cell->cellCfg.phyCellId;
695    pdsch->numLayers = 1;
696    pdsch->transmissionScheme = 0;
697    pdsch->refPoint = 0;
698    pdsch->dmrs.dlDmrsSymbPos = DL_DMRS_SYMBOL_POS; 
699    pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
700    pdsch->dmrs.dlDmrsScramblingId = cell->cellCfg.phyCellId;
701    pdsch->dmrs.scid = 0;
702    pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
703    pdsch->dmrs.dmrsPorts = 0;
704    pdsch->dmrs.mappingType      = DMRS_MAP_TYPE_A; /* Setting to Type-A */
705    pdsch->dmrs.nrOfDmrsSymbols  = NUM_DMRS_SYMBOLS;
706    pdsch->dmrs.dmrsAddPos       = DMRS_ADDITIONAL_POS;
707
708    pdsch->pdschTimeAlloc.startSymb = pdschStartSymbol; 
709    pdsch->pdschTimeAlloc.numSymb = pdschNumSymbols;
710
711    pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
712    pdsch->pdschFreqAlloc.startPrb = MAX_NUM_RB;
713    pdsch->pdschFreqAlloc.numPrb = schCalcNumPrb(tbSize, mcs, pdschNumSymbols);
714    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
715
716    /* Find total symbols occupied including DMRS */
717    dmrsStartSymbol = findDmrsStartSymbol(pdsch->dmrs.dlDmrsSymbPos);
718    /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
719     * in that case only PDSCH symbols are marked as occupied */
720    if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
721    {
722       startSymbol = pdsch->pdschTimeAlloc.startSymb;
723       numSymbol = pdsch->pdschTimeAlloc.numSymb;
724    }
725    /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
726    else
727    {
728       startSymbol = dmrsStartSymbol;
729       numSymbol = pdsch->dmrs.nrOfDmrsSymbols + pdsch->pdschTimeAlloc.numSymb;
730    }
731
732    /* Allocate the number of PRBs required for RAR PDSCH */
733    if((allocatePrbDl(cell, msg4Time, startSymbol, numSymbol,\
734       &pdsch->pdschFreqAlloc.startPrb, pdsch->pdschFreqAlloc.numPrb)) != ROK)
735    {
736       DU_LOG("\nERROR  --> SCH : Resource allocation failed for MSG4");
737       SCH_FREE(msg4Alloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
738       return RFAILED;
739    }
740
741    pdsch->beamPdschInfo.numPrgs = 1;
742    pdsch->beamPdschInfo.prgSize = 1;
743    pdsch->beamPdschInfo.digBfInterfaces = 0;
744    pdsch->beamPdschInfo.prg[0].pmIdx = 0;
745    pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
746    pdsch->txPdschPower.powerControlOffset = 0;
747    pdsch->txPdschPower.powerControlOffsetSS = 0;
748
749    return ROK;
750 }
751  
752 /*******************************************************************
753  *
754  * @brief Scheduling for Pucch Resource
755  *
756  * @details
757  *
758  *    Function : schAllocPucchResource
759  *
760  *    Functionality:
761  *       Scheduling for Pucch Resource
762  *
763  * @params[in] SchCellCb *cell, SlotTimingInfo pucchTime, crnti
764  * @params[in] SchUeCb *ueCb, bool isRetx, SchDlHqProcCb *hqP
765  * @return ROK     - success
766  *         RFAILED - failure
767  *
768  *******************************************************************/
769
770 uint16_t schAllocPucchResource(SchCellCb *cell, SlotTimingInfo pucchTime, uint16_t crnti,
771                                SchUeCb *ueCb, bool isRetx, SchDlHqProcCb *hqP)
772 {
773    uint16_t pucchSlot = 0;
774    SchUlSlotInfo  *schUlSlotInfo = NULLP;
775
776    pucchSlot = pucchTime.slot;
777    schUlSlotInfo = cell->schUlSlotInfo[pucchSlot];
778    memset(&schUlSlotInfo->schPucchInfo, 0, sizeof(SchPucchInfo));
779
780    schUlSlotInfo->pucchPres = true;
781    if(ueCb != NULLP)
782    {
783       /* set HARQ flag to true */
784       schUlSlotInfo->schPucchInfo.harqInfo.harqBitLength = 1; /* 1 bit for HARQ */
785       ADD_DELTA_TO_TIME(pucchTime, pucchTime, 3, cell->numSlots); /* SLOT_DELAY=3 */
786       cmLListAdd2Tail(&(ueCb->hqDlmap[pucchTime.slot]->hqList), &hqP->ulSlotLnk);
787    }
788    return ROK;
789 }
790
791 /*******************************************************************
792  *
793  * @brief Fills pdcch and pdsch info for dedicated DL msg
794  *
795  * @details
796  *
797  *    Function : schDlRsrcAllocDlMsg
798  *
799  *    Functionality:
800  *       Fills pdcch and pdsch info for dl msg
801  *
802  * @params[in] SchCellCb *cell, SlotTimingInfo slotTime
803  * @params[in] uint16_t crnti, uint32_t tbSize
804  * @params[in] DlMsgSchInfo *dlMsgAlloc, uint16_t startPRB
805  * @params[in] uint8_t pdschStartSymbol, uint8_t pdschNumSymbols
806  * @params[in] bool isRetx, SchDlHqProcCb *hqP
807  * @return ROK     - success
808  *         RFAILED - failure
809  *
810  * ****************************************************************/
811 uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
812                 uint32_t tbSize, DlMsgSchInfo *dlMsgAlloc, uint16_t startPRB, uint8_t pdschStartSymbol,
813                 uint8_t pdschNumSymbols, bool isRetx, SchDlHqProcCb *hqP)
814 {
815    uint8_t ueId=0;
816    uint8_t cwCount = 0;
817    PdcchCfg *pdcch = NULLP;
818    PdschCfg *pdsch = NULLP;
819    BwpCfg *bwp = NULLP;
820    SchUeCb ueCb;
821    SchControlRsrcSet coreset1;
822    SchPdschConfig pdschCfg;
823    uint8_t dmrsStartSymbol, startSymbol, numSymbol;
824
825    SCH_ALLOC(dlMsgAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
826    if(!dlMsgAlloc->dlMsgPdcchCfg)
827    {
828       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schDlRsrcAllocDlMsg");
829       return RFAILED;
830    }
831    pdcch = dlMsgAlloc->dlMsgPdcchCfg;
832    bwp = &dlMsgAlloc->bwp;
833
834    GET_UE_ID(crnti, ueId);
835    ueCb  = cell->ueCb[ueId-1];
836    coreset1 = ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdcchCfg.cRSetToAddModList[0];
837    pdschCfg = ueCb.ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg;
838
839    /* fill BWP */
840    bwp->freqAlloc.numPrb = MAX_NUM_RB;
841    bwp->freqAlloc.startPrb = 0;
842    bwp->subcarrierSpacing = cell->sib1SchCfg.bwp.subcarrierSpacing;
843    bwp->cyclicPrefix = cell->sib1SchCfg.bwp.cyclicPrefix;
844
845    /* fill the PDCCH PDU */
846    //Considering coreset1 also starts from same symbol as coreset0
847    pdcch->coresetCfg.startSymbolIndex = coresetIdxTable[0][3];
848    pdcch->coresetCfg.durationSymbols = coreset1.duration;
849    memcpy(pdcch->coresetCfg.freqDomainResource, coreset1.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
850    pdcch->coresetCfg.cceRegMappingType = coreset1.cceRegMappingType; /* non-interleaved */
851    pdcch->coresetCfg.regBundleSize = 6;   /* must be 6 for non-interleaved */
852    pdcch->coresetCfg.interleaverSize = 0; /* NA for non-interleaved */
853    pdcch->coresetCfg.coreSetType = 1; /* non PBCH coreset */
854    //Considering number of RBs in coreset1 is same as coreset0
855    pdcch->coresetCfg.coreSetSize = coresetIdxTable[0][1];
856    pdcch->coresetCfg.shiftIndex = cell->cellCfg.phyCellId;
857    pdcch->coresetCfg.precoderGranularity =  coreset1.precoderGranularity;
858    pdcch->numDlDci = 1;
859    pdcch->dci.rnti = ueCb.crnti;
860    pdcch->dci.scramblingId = cell->cellCfg.phyCellId;
861    pdcch->dci.scramblingRnti = 0;
862    pdcch->dci.cceIndex = 0; /* 0-3 for UL and 4-7 for DL */
863    pdcch->dci.aggregLevel = 4;
864    pdcch->dci.beamPdcchInfo.numPrgs = 1;
865    pdcch->dci.beamPdcchInfo.prgSize = 1;
866    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
867    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
868    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
869    pdcch->dci.txPdcchPower.beta_pdcch_1_0 = 0;
870    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
871
872    pdsch = &pdcch->dci.pdschCfg;
873    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
874    pdsch->rnti = ueCb.crnti;
875    pdsch->pduIndex = 0;
876    pdsch->numCodewords = 1;
877    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
878    {
879       pdsch->codeword[cwCount].targetCodeRate = 308;
880       pdsch->codeword[cwCount].qamModOrder = ueCb.ueCfg.dlModInfo.modOrder;
881       pdsch->codeword[cwCount].mcsIndex = ueCb.ueCfg.dlModInfo.mcsIndex;
882       pdsch->codeword[cwCount].mcsTable = ueCb.ueCfg.dlModInfo.mcsTable;
883       pdsch->codeword[cwCount].rvIndex = 0;
884
885       if (isRetx != TRUE)
886       {
887          tbSize +=TX_PAYLOAD_HDR_LEN;
888          hqP->tbInfo[cwCount].tbSzReq = tbSize;
889       }
890       pdsch->codeword[cwCount].tbSize = tbSize;
891    }
892    pdsch->dataScramblingId = cell->cellCfg.phyCellId;
893    pdsch->numLayers = 1;
894    pdsch->transmissionScheme = 0;
895    pdsch->refPoint = 0;
896    pdsch->dmrs.dlDmrsSymbPos = DL_DMRS_SYMBOL_POS; 
897    pdsch->dmrs.dmrsConfigType = 0; /* type-1 */
898    pdsch->dmrs.dlDmrsScramblingId = cell->cellCfg.phyCellId;
899    pdsch->dmrs.scid = 0;
900    pdsch->dmrs.numDmrsCdmGrpsNoData = 1;
901    pdsch->dmrs.dmrsPorts = 0;
902    pdsch->dmrs.mappingType      = DMRS_MAP_TYPE_A; /* Setting to Type-A */
903    pdsch->dmrs.nrOfDmrsSymbols  = NUM_DMRS_SYMBOLS;
904    pdsch->dmrs.dmrsAddPos       = pdschCfg.dmrsDlCfgForPdschMapTypeA.addPos;
905
906    pdsch->pdschTimeAlloc.startSymb = pdschStartSymbol; 
907    pdsch->pdschTimeAlloc.numSymb = pdschNumSymbols;
908
909    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
910    pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
911    pdsch->pdschFreqAlloc.startPrb = startPRB; /*Start PRB will be already known*/
912    pdsch->pdschFreqAlloc.numPrb = schCalcNumPrb(tbSize, ueCb.ueCfg.dlModInfo.mcsIndex, pdschNumSymbols);
913
914    /* Find total symbols occupied including DMRS */
915    dmrsStartSymbol = findDmrsStartSymbol(pdsch->dmrs.dlDmrsSymbPos);
916    /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
917     * in that case only PDSCH symbols are marked as occupied */
918    if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
919    {
920       startSymbol = pdsch->pdschTimeAlloc.startSymb;
921       numSymbol = pdsch->pdschTimeAlloc.numSymb;
922    }
923    /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
924    else
925    {
926       startSymbol = dmrsStartSymbol;
927       numSymbol = pdsch->dmrs.nrOfDmrsSymbols + pdsch->pdschTimeAlloc.numSymb;
928    }
929
930    /* Allocate the number of PRBs required for DL PDSCH */
931    if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
932       &pdsch->pdschFreqAlloc.startPrb, pdsch->pdschFreqAlloc.numPrb)) != ROK)
933    {
934       DU_LOG("\nERROR  --> SCH : allocatePrbDl() failed for DL MSG");
935       SCH_FREE(dlMsgAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
936       return RFAILED;
937    }
938
939    pdsch->beamPdschInfo.numPrgs = 1;
940    pdsch->beamPdschInfo.prgSize = 1;
941    pdsch->beamPdschInfo.digBfInterfaces = 0;
942    pdsch->beamPdschInfo.prg[0].pmIdx = 0;
943    pdsch->beamPdschInfo.prg[0].beamIdx[0] = 0;
944    pdsch->txPdschPower.powerControlOffset = 0;
945    pdsch->txPdschPower.powerControlOffsetSS = 0;
946
947    return ROK;
948 }
949
950 /*******************************************************************
951  *
952  * @brief Fills k0 and k1 information table for FDD 
953  *
954  * @details
955  *
956  *    Function : BuildK0K1TableForFdd 
957  *
958  *    Functionality:
959  *      Fills k0 and k1 information table for FDD
960  *
961  * @params[in] SchCellCb *cell,SchK0K1TimingInfoTbl *k0K1InfoTbl,bool
962  * pdschCfgCmnPres,uint8_t numTimeDomAlloc, SchPdschCfgCmnTimeDomRsrcAlloc
963  * cmnTimeDomRsrcAllocList[], SchPdschTimeDomRsrcAlloc
964  * dedTimeDomRsrcAllocList[], uint8_t ulAckListCount, uint8_t *UlAckTbl
965  * @return ROK     - success
966  *         RFAILED - failure
967  *
968  * ****************************************************************/
969 void BuildK0K1TableForFdd(SchCellCb *cell, SchK0K1TimingInfoTbl *k0K1InfoTbl, bool pdschCfgCmnPres,SchPdschCfgCmn pdschCmnCfg,\
970 SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
971 {
972    
973    uint8_t k1TmpVal =0, cfgIdx=0;
974    uint8_t slotIdx=0, k0Index=0, k1Index=0, numK0=0, numK1=0, numTimeDomAlloc=0;
975    
976    /* TODO Commented these below lines for resolving warnings. Presently these variable are not 
977     * required but this will require for harq processing */
978    // uint8_t k0TmpVal = 0; 
979    // SchPdschCfgCmnTimeDomRsrcAlloc cmnTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
980    // SchPdschTimeDomRsrcAlloc dedTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
981
982    /* Initialization the structure and storing the total slot values. */
983    memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
984    k0K1InfoTbl->tblSize = cell->numSlots;
985    
986    /* Storing time domain resource allocation list based on common or dedicated configuration. */
987    if(pdschCfgCmnPres == true)
988    {
989       numTimeDomAlloc = pdschCmnCfg.numTimeDomAlloc;
990       for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
991       {
992          /*TODO uncomment this line during harq processing */
993          //cmnTimeDomRsrcAllocList[cfgIdx] = pdschCmnCfg.timeDomRsrcAllocList[cfgIdx];
994       }
995    }
996    else
997    {
998       numTimeDomAlloc = pdschDedCfg.numTimeDomRsrcAlloc;
999       for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1000       {
1001          /*TODO uncomment this line during harq processing */
1002          //dedTimeDomRsrcAllocList[cfgIdx] = pdschDedCfg.timeDomRsrcAllociList[cfgIdx];
1003       }
1004    }
1005    
1006    /* Checking all the slots for K0 and K1 values. */
1007    for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1008    {
1009       numK0 = 0;
1010       /* Storing the values of k0 based on time domain resource
1011        * allocation list. If the value is unavailable then fill default values,
1012        * As per 38.331 PDSCH-TimeDomainResourceAllocation field descriptions. */
1013       for(k0Index = 0; ((k0Index < numTimeDomAlloc) && (k0Index < MAX_NUM_K0_IDX));  k0Index++)
1014       {
1015          /* TODO These if 0 we will remove during harq processing */
1016 #if 0
1017          if(pdschCfgCmnPres == true)
1018          {
1019             k0TmpVal = cmnTimeDomRsrcAllocList[k0Index].k0;
1020          }
1021          else
1022          {
1023             if(dedTimeDomRsrcAllocList[k0Index].k0 != NULLP)
1024             {
1025                k0TmpVal = *(dedTimeDomRsrcAllocList[k0Index].k0);
1026             }
1027             else
1028             { 
1029                k0TmpVal = DEFAULT_K0_VALUE;
1030             }
1031          }
1032 #endif         
1033          /* Checking all the Ul Alloc values. If value is less than MIN_NUM_K1_IDX
1034           * then skip else continue storing the values. */
1035          numK1 = 0;
1036          for(k1Index = 0; k1Index < ulAckListCount; k1Index++)
1037          {
1038             k1TmpVal = UlAckTbl[k1Index];
1039             if(k1TmpVal <= MIN_NUM_K1_IDX)
1040             {
1041                continue;
1042             }
1043
1044             k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.k1Indexes[numK1++] = k1Index;
1045             /* TODO Store K1 index where harq feedback will be received in harq table. */ 
1046          }
1047          if(numK1)
1048          {
1049             k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.numK1 = numK1;
1050             k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k0Index = k0Index;
1051             numK0++;
1052          }
1053       }
1054       if(numK0)
1055       {
1056          k0K1InfoTbl->k0k1TimingInfo[slotIdx].numK0 = numK0;
1057       }
1058    }
1059 }
1060
1061 /*******************************************************************
1062  *
1063  * @brief Fills k0 and k1 information table  
1064  *
1065  * @details
1066  *
1067  *    Function : BuildK0K1Table
1068  *
1069  *    Functionality:
1070  *       Fills K0 and k1 information table 
1071  *
1072  * @params[in] SchCellCb *cell,SchK0K1TimingInfoTbl *k0K1InfoTbl,bool
1073  * pdschCfgCmnPres,uint8_t numTimeDomAlloc, SchPdschCfgCmnTimeDomRsrcAlloc
1074  * cmnTimeDomRsrcAllocList[], SchPdschTimeDomRsrcAlloc
1075  * dedTimeDomRsrcAllocList[], uint8_t ulAckListCount, uint8_t *UlAckTbl
1076  * @return ROK     - success
1077  *         RFAILED - failure
1078  *
1079  * ****************************************************************/
1080 void BuildK0K1Table(SchCellCb *cell, SchK0K1TimingInfoTbl *k0K1InfoTbl, bool pdschCfgCmnPres, SchPdschCfgCmn pdschCmnCfg,\
1081 SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
1082 {
1083
1084 #ifdef NR_TDD
1085    SlotConfig  slotCfg;
1086    bool ulSlotPresent = false;
1087    uint8_t k0TmpVal = 0, k1TmpVal =0, tmpSlot=0, startSymbol=0, endSymbol=0, checkSymbol=0;
1088    uint8_t slotIdx=0, k0Index=0, k1Index=0, numK0=0, numK1=0, cfgIdx=0, numTimeDomAlloc =0, totalCfgSlot =0;
1089    SchPdschCfgCmnTimeDomRsrcAlloc cmnTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
1090    SchPdschTimeDomRsrcAlloc dedTimeDomRsrcAllocList[MAX_NUM_DL_ALLOC];
1091 #endif
1092
1093    if(cell->cellCfg.dupMode == DUPLEX_MODE_FDD)
1094    {
1095       BuildK0K1TableForFdd(cell, k0K1InfoTbl, pdschCfgCmnPres, pdschCmnCfg, pdschDedCfg, ulAckListCount, UlAckTbl);
1096    }
1097    else
1098    {
1099 #ifdef NR_TDD
1100       
1101       /* Initialization the K0K1 structure, total num of slot and calculating the slot pattern length. */
1102       memset(k0K1InfoTbl, 0, sizeof(SchK0K1TimingInfoTbl));
1103       k0K1InfoTbl->tblSize = cell->numSlots;
1104       totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbScs, cell->cellCfg.tddCfg.tddPeriod);
1105       
1106       /* Storing time domain resource allocation list based on common or 
1107        * dedicated configuration availability. */
1108       if(pdschCfgCmnPres == true)
1109       {
1110          numTimeDomAlloc = pdschCmnCfg.numTimeDomAlloc;
1111          for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1112          {
1113             cmnTimeDomRsrcAllocList[cfgIdx] = pdschCmnCfg.timeDomRsrcAllocList[cfgIdx];
1114          }
1115       }
1116       else
1117       {
1118          numTimeDomAlloc = pdschDedCfg.numTimeDomRsrcAlloc;
1119          for(cfgIdx = 0; cfgIdx<numTimeDomAlloc; cfgIdx++)
1120          {
1121             dedTimeDomRsrcAllocList[cfgIdx] = pdschDedCfg.timeDomRsrcAllociList[cfgIdx];
1122          }
1123       }
1124
1125       /* Checking all possible indexes for K0 and K1 values. */
1126       for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1127       {
1128          /* If current slot is UL or FLEXI then Skip because PDCCH is sent only in DL slots. */
1129          slotCfg = schGetSlotSymbFrmt(slotIdx%totalCfgSlot, cell->slotFrmtBitMap);
1130          if(slotCfg == UL_SLOT || slotCfg == FLEXI_SLOT)
1131          {
1132             continue;
1133          }
1134         
1135          ulSlotPresent = false;
1136          /* Storing K0 , start symbol and length symbol for further processing.
1137           * If K0 value is not available then we can fill the default values
1138           * given in spec 38.331. */
1139          numK0 = 0;
1140          for(k0Index = 0; ((k0Index < numTimeDomAlloc) && (k0Index < MAX_NUM_K0_IDX)); k0Index++)
1141          {
1142             if(pdschCfgCmnPres == true)
1143             {
1144                k0TmpVal = cmnTimeDomRsrcAllocList[k0Index].k0;
1145                startSymbol = cmnTimeDomRsrcAllocList[k0Index].startSymbol;
1146                endSymbol = startSymbol + cmnTimeDomRsrcAllocList[k0Index].lengthSymbol;
1147             }
1148             else
1149             {
1150                if(dedTimeDomRsrcAllocList[k0Index].k0 != NULLP)
1151                {
1152                   k0TmpVal =  *(dedTimeDomRsrcAllocList[k0Index].k0);
1153                }
1154                else
1155                {
1156                   k0TmpVal = DEFAULT_K0_VALUE;
1157                }
1158                startSymbol = dedTimeDomRsrcAllocList[k0Index].startSymbol;
1159                endSymbol = startSymbol + dedTimeDomRsrcAllocList[k0Index].symbolLength;
1160             }
1161             
1162             /* If current slot + k0 is UL then skip the slot
1163              * else if it is DL slot then continue the next steps
1164              * else if it is a FLEXI slot then check symbols of slot, It should not
1165              * contain any UL slot. */
1166             tmpSlot = (slotIdx+k0TmpVal) % totalCfgSlot;
1167             slotCfg = schGetSlotSymbFrmt(tmpSlot, cell->slotFrmtBitMap);
1168             if(slotCfg == UL_SLOT)
1169             {
1170                continue;
1171             }
1172             if(slotCfg == FLEXI_SLOT)
1173             {
1174                for(checkSymbol = startSymbol; checkSymbol<endSymbol; checkSymbol ++)
1175                {
1176                   slotCfg = cell->slotCfg[tmpSlot][checkSymbol];
1177                   if(slotCfg == UL_SLOT)
1178                   {
1179                      ulSlotPresent = true;
1180                      break;
1181                   }
1182                }
1183                if(ulSlotPresent == true)
1184                {
1185                   continue;
1186                }
1187             }
1188
1189              ulSlotPresent = false; //Re-initializing
1190
1191             /* If current slot + k0 + k1 is a DL slot then skip the slot
1192              * else if it is UL slot then store the information 
1193              * else if it is FLEXI slot then check the symbols, it must have
1194              * at least one UL symbol. */
1195             numK1 = 0;
1196             for(k1Index = 0; k1Index < ulAckListCount; k1Index++)
1197             {
1198                k1TmpVal = UlAckTbl[k1Index];
1199                if(k1TmpVal > MIN_NUM_K1_IDX)
1200                {
1201                   tmpSlot = (slotIdx+k0TmpVal+k1TmpVal) % totalCfgSlot;
1202                   slotCfg =  schGetSlotSymbFrmt(tmpSlot, cell->slotFrmtBitMap);
1203                   if(slotCfg == DL_SLOT) 
1204                   {
1205                      continue;
1206                   }   
1207                   if(slotCfg == FLEXI_SLOT)
1208                   {
1209                      for(checkSymbol = 0; checkSymbol< MAX_SYMB_PER_SLOT;checkSymbol++)
1210                      {
1211                         if(cell->slotCfg[tmpSlot][checkSymbol] == UL_SYMBOL)
1212                         {
1213                            ulSlotPresent = true;
1214                            break;
1215                         }
1216                      }
1217                   }
1218                   if(ulSlotPresent == true || slotCfg ==  UL_SLOT)
1219                   {
1220                      k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.k1Indexes[numK1++] = k1Index;
1221                      /* TODO Store K1 index where harq feedback will be received
1222                       * in harq table. */
1223                   }
1224                }
1225             }
1226             
1227             /* Store all the values if all condition satisfies. */
1228             if(numK1)
1229             {
1230                k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k1TimingInfo.numK1 = numK1;
1231                k0K1InfoTbl->k0k1TimingInfo[slotIdx].k0Indexes[numK0].k0Index = k0Index;
1232                numK0++;
1233             }
1234          }
1235          if(numK0)
1236          {
1237             k0K1InfoTbl->k0k1TimingInfo[slotIdx].numK0 = numK0;
1238          }
1239       }
1240 #endif
1241    }
1242 }
1243
1244 /*******************************************************************
1245 *
1246 * @brief Fills K2 information table for FDD
1247 *
1248 * @details
1249 *
1250 *    Function : BuildK2InfoTableForFdd 
1251 *
1252 *    Functionality:
1253 *       Fills K2 information table for FDD
1254 *
1255 * @params[in] SchCellCb *cell,SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[],
1256 * uint16_t puschSymTblSize,SchK2TimingInfoTbl *k2InfoTbl
1257 * @return ROK     - success
1258 *         RFAILED - failure
1259 *
1260 * ****************************************************************/
1261 void BuildK2InfoTableForFdd(SchCellCb *cell, SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[], uint16_t puschSymTblSize,\
1262 SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
1263 {
1264    uint16_t slotIdx=0, k2Index=0, k2TmpIdx=0, msg3K2TmpIdx=0;
1265
1266    /* Initialization the structure and storing the total slot values. */
1267    memset(k2InfoTbl, 0, sizeof(SchK2TimingInfoTbl));
1268    k2InfoTbl->tblSize = cell->numSlots;
1269    if(msg3K2InfoTbl)
1270       msg3K2InfoTbl->tblSize = cell->numSlots;
1271    
1272    /* Checking all possible indexes for K2. */
1273    for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1274    {
1275       /* Storing K2 values. */
1276       for(k2Index = 0; ((k2Index < puschSymTblSize) && (k2Index < MAX_NUM_K2_IDX)); k2Index++)
1277       {
1278          k2TmpIdx= k2InfoTbl->k2TimingInfo[slotIdx].numK2;
1279          k2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[k2TmpIdx] = k2Index;
1280          k2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1281
1282          /* Updating K2 values for MSG3 */
1283          if(msg3K2InfoTbl)
1284          {
1285             msg3K2TmpIdx = msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2;
1286             msg3K2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[msg3K2TmpIdx] = k2Index;
1287             msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1288          }
1289       }
1290    }
1291 }
1292
1293 /*******************************************************************
1294  *
1295  * @brief Fills K2 information table
1296  *
1297  * @details
1298  *
1299  *    Function : BuildK2InfoTable 
1300  *
1301  *    Functionality:
1302  *       Fills K2 information table
1303  *
1304  * @params[in] SchCellCb *cell,SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[],
1305  * uint16_t puschSymTblSize, SchK2TimingInfoTbl *k2InfoTbl
1306  * @return ROK     - success
1307  *         RFAILED - failure
1308  *
1309  * ****************************************************************/
1310 void BuildK2InfoTable(SchCellCb *cell, SchPuschTimeDomRsrcAlloc timeDomRsrcAllocList[], uint16_t puschSymTblSize,\
1311 SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
1312 {
1313
1314 #ifdef NR_TDD
1315    bool dlSymbolPresent = false;
1316    uint8_t slotIdx=0, k2Index=0, k2Val=0, k2TmpVal=0, msg3K2TmpVal=0, msg3Delta=0, numK2 =0, currentSymbol =0;
1317    uint8_t startSymbol =0, endSymbol =0, checkSymbol=0, totalCfgSlot=0, slotCfg=0;
1318    SlotConfig currentSlot;
1319 #endif
1320
1321    if(cell->cellCfg.dupMode == DUPLEX_MODE_FDD)
1322    {
1323       BuildK2InfoTableForFdd(cell, timeDomRsrcAllocList, puschSymTblSize, msg3K2InfoTbl, k2InfoTbl);
1324    }
1325    else
1326    {
1327 #ifdef NR_TDD
1328
1329       /* Initialization the structure and storing the total slot values. */
1330       memset(k2InfoTbl, 0, sizeof(SchK2TimingInfoTbl));
1331       k2InfoTbl->tblSize = cell->numSlots;
1332       if(msg3K2InfoTbl)
1333          msg3K2InfoTbl->tblSize = cell->numSlots;
1334       totalCfgSlot = calculateSlotPatternLength(cell->cellCfg.ssbScs, cell->cellCfg.tddCfg.tddPeriod);
1335
1336       /* Checking all possible indexes for K2. */
1337       for(slotIdx = 0; slotIdx < cell->numSlots; slotIdx++)
1338       {
1339          currentSlot = schGetSlotSymbFrmt(slotIdx % totalCfgSlot, cell->slotFrmtBitMap);
1340          
1341          /* If current slot is UL then skip because PDCCH is sent only in DL slots */
1342          if(currentSlot != UL_SLOT)
1343          {
1344             for(k2Index = 0; ((k2Index < puschSymTblSize) && (k2Index < MAX_NUM_K2_IDX)); k2Index++)
1345             {
1346                /* Storing k2, startSymbol, endSymbol information for further processing.
1347                 * If k2 is absent then fill the default values given in spec 38.331
1348                 * PUSCH-TimeDomainResourceAllocationList field descriptions */
1349                k2Val = timeDomRsrcAllocList[k2Index].k2;
1350                if(!k2Val)
1351                {
1352                   switch(cell->cellCfg.ssbScs)
1353                   {
1354                      case SCS_15KHZ:
1355                         k2Val = DEFAULT_K2_VALUE_FOR_SCS15;
1356                         break;
1357                      case SCS_30KHZ:
1358                         k2Val = DEFAULT_K2_VALUE_FOR_SCS30;
1359                         break;
1360                      case SCS_60KHZ:
1361                         k2Val = DEFAULT_K2_VALUE_FOR_SCS60;
1362                         break;
1363                      case SCS_120KHZ:
1364                         k2Val = DEFAULT_K2_VALUE_FOR_SCS120;
1365                         break;
1366                   }
1367                }
1368                
1369                /* Current slot + k2 should be either UL or FLEXI slot.
1370                 * If slot is FLEXI then check all the symbols of that slot,
1371                 * it should not contain any DL or FLEXI slot */
1372                k2TmpVal = (slotIdx + k2Val) % totalCfgSlot;
1373                slotCfg = schGetSlotSymbFrmt(k2TmpVal, cell->slotFrmtBitMap);
1374                if(slotCfg != DL_SLOT)
1375                {
1376                   if(slotCfg == FLEXI_SLOT)
1377                   {
1378                      startSymbol =  timeDomRsrcAllocList[k2Index].startSymbol;
1379                      endSymbol   =  startSymbol+ timeDomRsrcAllocList[k2Index].symbolLength;
1380                      dlSymbolPresent = false;
1381                      for(checkSymbol= startSymbol; checkSymbol<endSymbol; checkSymbol++)
1382                      {
1383                         currentSymbol = cell->slotCfg[k2TmpVal][checkSymbol];
1384                         if(currentSymbol == DL_SLOT || currentSymbol == FLEXI_SLOT)
1385                         {
1386                            dlSymbolPresent = true;
1387                            break;
1388                         }
1389                      }
1390                   }
1391                   /* Store all the values if all condition satisfies. */
1392                   if(dlSymbolPresent != true || slotCfg == UL_SLOT)
1393                   {
1394                      numK2 = k2InfoTbl->k2TimingInfo[slotIdx].numK2;
1395                      k2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[numK2] = k2Index;
1396                      k2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1397                   }
1398                }
1399
1400                if(msg3K2InfoTbl)
1401                {
1402                    msg3Delta = puschDeltaTable[cell->numerology];
1403
1404                   /* Check for K2 for MSG3 */
1405                   /* Current slot + k2 should be either UL or FLEXI slot.
1406                    * If slot is FLEXI then check all the symbols of that slot,
1407                    * it should not contain any DL or FLEXI slot */
1408                   msg3K2TmpVal = (slotIdx + k2Val + msg3Delta) % totalCfgSlot;
1409                   slotCfg = schGetSlotSymbFrmt(msg3K2TmpVal, cell->slotFrmtBitMap);
1410                   if(slotCfg != DL_SLOT)
1411                   {
1412                      if(slotCfg == FLEXI_SLOT)
1413                      {
1414                         startSymbol =  timeDomRsrcAllocList[k2Index].startSymbol;
1415                         endSymbol   =  startSymbol+ timeDomRsrcAllocList[k2Index].symbolLength;
1416                         dlSymbolPresent = false;
1417                         for(checkSymbol= startSymbol; checkSymbol<endSymbol; checkSymbol++)
1418                         {
1419                            currentSymbol = cell->slotCfg[msg3K2TmpVal][checkSymbol];
1420                            if(currentSymbol == DL_SLOT || currentSymbol == FLEXI_SLOT)
1421                            {
1422                               dlSymbolPresent = true;
1423                               break;
1424                            }
1425                         }
1426                      }
1427                      /* Store all the values if all condition satisfies. */
1428                      if(dlSymbolPresent != true || slotCfg == UL_SLOT)
1429                      {
1430                         numK2 = msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2;
1431                         msg3K2InfoTbl->k2TimingInfo[slotIdx].k2Indexes[numK2] = k2Index;
1432                         msg3K2InfoTbl->k2TimingInfo[slotIdx].numK2++;
1433                      }
1434                   }
1435                }
1436             }
1437          }
1438       }
1439 #endif
1440    }
1441 }
1442
1443 /*******************************************************************************************
1444  *
1445  * @brief Allocate the PRB using RRM policy
1446  *
1447  * @details
1448  *
1449  *    Function : prbAllocUsingRRMPolicy
1450  *
1451  *    Functionality:
1452  *      [Step1]: Traverse each Node in the LC list
1453  *      [Step2]: Check whether the LC has ZERO requirement then clean this LC
1454  *      [Step3]: Calcualte the maxPRB for this LC.
1455  *              a. For Dedicated LC, maxPRB = sum of remainingReservedPRB and
1456  *              sharedPRB
1457  *              b. For Default, just SharedPRB count
1458  *      [Step4]: If the LC is the First one to be allocated for this UE then add
1459  *      TX_PAYLODN_LEN to reqBO 
1460  *      [Step5]: Calculate the estimate PRB and estimate BO to be allocated
1461  *               based on reqBO and maxPRB left.
1462  *      [Step6]: Based on calculated PRB, Update Reserved PRB and Shared PRB counts
1463  *      [Step7]: Deduce the reqBO based on allocBO and move the LC node to last.
1464  *      [Step8]: Continue the next loop from List->head
1465  *
1466  *      [Loop Exit]:
1467  *        [Exit1]: If all the LCs are allocated in list
1468  *        [Exit2]: If PRBs are exhausted
1469  *
1470  * @params[in] I/P > lcLinkList pointer (LcInfo list)
1471  *             I/P > IsDedicatedPRB (Flag to indicate that RESERVED PRB to use 
1472  *             I/P > mcsIdx and PDSCH symbols count 
1473  *             I/P & O/P > Shared PRB , reserved PRB Count
1474  *             I/P & O/P > Total TBS size accumulated
1475  *             I/P & O/P > isTxPayloadLenAdded[For DL] : Decision flag to add the TX_PAYLOAD_HDR_LEN
1476  *             I/P & O/P > srRcvd Flag[For UL] : Decision flag to add UL_GRANT_SIZE
1477  *
1478  * @return void
1479  *
1480  * *******************************************************************************************/
1481 void prbAllocUsingRRMPolicy(CmLListCp *lcLL, bool isDedicatedPRB, uint16_t mcsIdx,uint8_t numSymbols,\
1482                   uint16_t *sharedPRB, uint16_t *reservedPRB, bool *isTxPayloadLenAdded, bool *srRcvd)
1483 {
1484    CmLList *node = NULLP;
1485    LcInfo *lcNode = NULLP;
1486    uint16_t remReservedPRB = 0, estPrb = 0, maxPRB = 0;
1487
1488    if(lcLL == NULLP)
1489    {
1490       DU_LOG("\nERROR --> SCH: LcList not present");
1491       return;
1492    }
1493    node = lcLL->first;
1494
1495    /*Only for Dedicated LcList, Valid value will be assigned to remReservedPRB
1496     * For Other LcList, remReservedPRB = 0*/
1497    if(reservedPRB != NULLP && isDedicatedPRB == TRUE)
1498    {
1499       remReservedPRB = *reservedPRB;
1500    }
1501
1502    /*[Step1]*/
1503    while(node)
1504    {
1505 #if 0
1506       /*For Debugging purpose*/
1507       printLcLL(lcLL);
1508 #endif
1509       lcNode = (LcInfo *)node->node;
1510
1511       /* [Step2]: Below condition will hit in rare case as it has been taken care during the cleaning 
1512        * process of LCID which was fully allocated. Check is just for safety purpose*/
1513       if(lcNode->reqBO == 0 && lcNode->allocBO == 0)
1514       {
1515          DU_LOG("\nERROR --> SCH: LCID:%d has no requirement, clearing this node",\
1516                lcNode->lcId);
1517          deleteNodeFromLList(lcLL, node);
1518          SCH_FREE(lcNode, sizeof(LcInfo));
1519          node = lcLL->first; 
1520          continue;
1521       }
1522
1523       /*[Exit1]: All LCs are allocated(allocBO = 0 for fully unallocated LC)*/
1524       if(lcNode->allocBO != 0)
1525       {
1526          DU_LOG("\nDEBUG  -->  SCH: All LC are allocated [SharedPRB:%d]",*sharedPRB);
1527          return;
1528       }
1529
1530       /*[Exit2]: If PRBs are exhausted*/
1531       if(isDedicatedPRB)
1532       {
1533          /*Loop Exit: All resources exhausted*/
1534          if(remReservedPRB == 0 && *sharedPRB == 0)
1535          {
1536             DU_LOG("\nDEBUG  -->  SCH: Dedicated resources exhausted for LC:%d",lcNode->lcId);
1537             return;
1538          }
1539       }
1540       else
1541       {
1542          /*Loop Exit: All resources exhausted*/
1543          if(*sharedPRB == 0)
1544          {
1545             DU_LOG("\nDEBUG  -->  SCH: Default resources exhausted for LC:%d",lcNode->lcId);
1546             return;
1547          }
1548       }
1549
1550       /*[Step3]*/
1551       maxPRB = remReservedPRB + *sharedPRB;
1552
1553       /*[Step4]*/
1554       if((isTxPayloadLenAdded != NULLP) && (*isTxPayloadLenAdded == FALSE))
1555       {
1556          DU_LOG("\nDEBUG  -->  SCH: LC:%d is the First node to be allocated which includes TX_PAYLOAD_HDR_LEN",\
1557                lcNode->lcId);
1558          *isTxPayloadLenAdded = TRUE;
1559          lcNode->allocBO = calculateEstimateTBSize((lcNode->reqBO + TX_PAYLOAD_HDR_LEN),\
1560                mcsIdx, numSymbols, maxPRB, &estPrb);
1561          lcNode->allocBO -=TX_PAYLOAD_HDR_LEN;
1562       }
1563       else if((srRcvd != NULLP) && (*srRcvd == TRUE))
1564       {
1565          DU_LOG("\nDEBUG  --> SCH: LC:%d is the First node to be allocated which includes UL_GRANT_SIZE",\
1566                lcNode->lcId);
1567          *srRcvd = FALSE;
1568          lcNode->reqBO += UL_GRANT_SIZE;
1569          lcNode->allocBO = calculateEstimateTBSize(lcNode->reqBO, mcsIdx, numSymbols, maxPRB, &estPrb);
1570       }
1571       else
1572       {
1573          /*[Step4]*/
1574          lcNode->allocBO = calculateEstimateTBSize(lcNode->reqBO,\
1575                mcsIdx, numSymbols, maxPRB, &estPrb);
1576       }
1577
1578       /*[Step6]:Re-adjust the reservedPRB pool count and *SharedPRB Count based on
1579        * estimated PRB allocated*/
1580       if((isDedicatedPRB == TRUE) && (estPrb <= remReservedPRB))
1581       {
1582          remReservedPRB = remReservedPRB - estPrb;
1583       }
1584       else   /*LC requirement need PRB share from SharedPRB*/
1585       {
1586          if(*sharedPRB <=  (estPrb - remReservedPRB))
1587          {
1588             DU_LOG("\nDEBUG  -->  SCH: SharedPRB is less");
1589             *sharedPRB = 0;
1590          }
1591          else
1592          {
1593             *sharedPRB = *sharedPRB - (estPrb - remReservedPRB);
1594          }
1595          remReservedPRB = 0;
1596       }
1597
1598       /*[Step7]*/
1599       lcNode->reqBO -= lcNode->allocBO;  /*Update the reqBO with remaining bytes unallocated*/
1600       lcNode->allocPRB = estPrb;
1601       cmLListAdd2Tail(lcLL, cmLListDelFrm(lcLL, node));
1602
1603       /*[Step8]:Next loop: First LC to be picked from the list
1604        * because Allocated Nodes are moved to the last*/
1605       node = lcLL->first; 
1606
1607    }
1608    return;
1609 }
1610
1611 /*******************************************************************************************
1612  *
1613  * @brief Check the LC List and fill the LC and GrantSize to be sent to MAC as
1614  * BO Report
1615  *
1616  * @details
1617  *
1618  *    Function : updateGrantSizeForBoRpt
1619  *
1620  *    Functionality:
1621  *             Check the LC List and fill the LC and GrantSize to be sent to MAC as
1622  *             BO Report in dlMsgAlloc Pointer
1623  *
1624  * @params[in] I/P > lcLinkList pointer (LcInfo list)
1625  *             I/P & O/P > dlMsgAlloc[for DL](Pending LC to be added in this context) 
1626  *             I/P & O/P > BsrInfo (applicable for UL)
1627  *             I/P & O/P > accumalatedBOSize
1628  * @return void
1629  *
1630  * *******************************************************************************************/
1631 void updateGrantSizeForBoRpt(CmLListCp *lcLL, DlMsgSchInfo *dlMsgAlloc,\
1632                                 BsrInfo *bsrInfo, uint32_t *accumalatedBOSize)
1633 {
1634    CmLList *node = NULLP, *next = NULLP;
1635    LcInfo *lcNode = NULLP;
1636
1637    if(lcLL == NULLP)
1638    {
1639       DU_LOG("\nERROR --> SCH: LcList not present");
1640       return;
1641    }
1642
1643    if(lcLL->count)
1644    {
1645       node = lcLL->first;
1646    }
1647    else
1648    {
1649       /*lcLL is empty*/
1650       return;
1651    }
1652
1653    /*Traverse List*/
1654    while(node)
1655    {
1656       next = node->next;
1657       lcNode = (LcInfo *)node->node;
1658       if(lcNode != NULLP)
1659       {
1660          DU_LOG("\nINFO   -->  SCH : LcID:%d, [reqBO, allocBO, allocPRB]:[%d,%d,%d]",\
1661                lcNode->lcId, lcNode->reqBO, lcNode->allocBO, lcNode->allocPRB);
1662          if(dlMsgAlloc != NULLP)
1663          {
1664
1665             /*Add this LC to dlMsgAlloc so that if this LC gets allocated, BO
1666              * report for allocation can be sent to MAC*/
1667             dlMsgAlloc->numOfTbs = 1;
1668             dlMsgAlloc->transportBlock[0].lcSchInfo[dlMsgAlloc->transportBlock[0].numLc].lcId = lcNode->lcId;
1669             dlMsgAlloc->transportBlock[0].lcSchInfo[dlMsgAlloc->transportBlock[0].numLc].schBytes = lcNode->allocBO;
1670
1671             /*Calculate the Total Payload/BO size allocated*/
1672             *accumalatedBOSize += dlMsgAlloc->transportBlock[0].lcSchInfo[dlMsgAlloc->transportBlock[0].numLc].schBytes; 
1673
1674             DU_LOG("\nINFO   -->  SCH: Added in MAC BO report: LCID:%d,reqBO:%d,Idx:%d, TotalBO Size:%d",\
1675                   lcNode->lcId,lcNode->reqBO, dlMsgAlloc->transportBlock[0].numLc, *accumalatedBOSize);
1676
1677             dlMsgAlloc->transportBlock[0].numLc++;
1678             handleLcLList(lcLL, lcNode->lcId, DELETE);
1679          }
1680          else if(bsrInfo != NULLP)
1681          {
1682             *accumalatedBOSize += lcNode->allocBO;   
1683             DU_LOG("\nINFO   --> SCH: UL : LCID:%d,reqBO:%d, TotalBO Size:%d",\
1684                   lcNode->lcId,lcNode->reqBO, *accumalatedBOSize);
1685          }
1686       }
1687       node = next;
1688    }/*End of while*/
1689    return;
1690 }
1691
1692 /*******************************************************************
1693 *
1694 * @brief fill DL message information for MSG4 and Dedicated DL Msg
1695 *
1696 * @details
1697 *
1698 *    Function : fillDlMsgInfo
1699 *
1700 *    Functionality:
1701 *       fill DL message information for MSG4 and Dedicated DL Msg
1702 *
1703 * @params[in] DlMsgInfo *dlMsgInfo,  uint16_t crnti
1704 * @params[in] bool isRetx, SchDlHqProcCb *hqP
1705 * @return void
1706 *
1707 *******************************************************************/
1708 void fillDlMsgInfo(DlMsgSchInfo *dlMsgSchInfo, uint16_t crnti, bool isRetx, SchDlHqProcCb *hqP)
1709 {
1710    hqP->tbInfo[0].isEnabled = TRUE;
1711    hqP->tbInfo[0].state = HQ_TB_WAITING;
1712    hqP->tbInfo[0].txCntr++;
1713    hqP->tbInfo[1].isEnabled = TRUE;
1714    hqP->tbInfo[1].state = HQ_TB_WAITING;
1715    hqP->tbInfo[1].txCntr++;
1716    dlMsgSchInfo->crnti = crnti;
1717    dlMsgSchInfo->transportBlock[0].ndi = hqP->tbInfo[0].ndi; /*How to handle two tb case?TBD*/
1718    dlMsgSchInfo->harqProcNum = hqP->procId;
1719    dlMsgSchInfo->dlAssignIdx = 0;
1720    dlMsgSchInfo->pucchTpc = 0;
1721    dlMsgSchInfo->pucchResInd = 0;
1722    dlMsgSchInfo->harqFeedbackInd = hqP->k1;
1723    dlMsgSchInfo->dciFormatId = 1;
1724 }
1725
1726 /*******************************************************************
1727  *
1728  * @brief sch Process pending Msg4 Req
1729  *
1730  * @details
1731  *
1732  *    Function : schProcessMsg4Req
1733  *
1734  *    Functionality:
1735  *       sch Process pending Msg4 Req
1736  *
1737  * @params[in] SchCellCb *cell, cell cb struct pointer
1738  * @params[in] SlotTimingInfo currTime, current timing info
1739  * @params[in] uint8_t ueId, ue ID
1740  * @params[in] bool isRetxMsg4, indicator to MSG4 retransmission
1741  * @params[in] SchDlHqProcCb **msg4HqProc, address of MSG4 HARQ proc pointer
1742  * @return ROK     - success
1743  *         RFAILED - failure
1744  *
1745  *******************************************************************/
1746
1747 uint8_t schProcessMsg4Req(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool isRetxMsg4, SchDlHqProcCb **msg4HqProc)
1748 {
1749    uint8_t pdschStartSymbol = 0, pdschNumSymbols = 0;
1750    SlotTimingInfo pdcchTime, pdschTime, pucchTime;
1751    DlMsgSchInfo *dciSlotAlloc = NULLP;    /* Stores info for transmission of PDCCH for Msg4 */
1752    DlMsgSchInfo *msg4SlotAlloc = NULLP;   /* Stores info for transmission of PDSCH for Msg4 */
1753
1754    if(cell == NULL)
1755    {
1756       DU_LOG("\nERROR  -->  SCH: schProcessMsg4Req() : Cell is NULL");
1757       return RFAILED;
1758    }
1759
1760    if (isRetxMsg4 == FALSE)
1761    {
1762       if (RFAILED == schDlGetAvlHqProcess(cell, &cell->ueCb[ueId - 1], msg4HqProc))
1763       {
1764          DU_LOG("\nERROR  -->  SCH: schProcessMsg4Req() : No process");
1765          return RFAILED;
1766       }
1767    }
1768
1769    if(findValidK0K1Value(cell, currTime, ueId, false, &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime,\
1770             &pucchTime, isRetxMsg4, *msg4HqProc) != true )
1771    {
1772       DU_LOG("\nERROR  -->  SCH: schProcessMsg4Req() : k0 k1 not found");
1773       return RFAILED;
1774    }
1775
1776    if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
1777    {
1778       SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgSchInfo));
1779       if(dciSlotAlloc == NULLP)
1780       {
1781          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciSlotAlloc");
1782          return RFAILED;
1783       }
1784       cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = dciSlotAlloc;
1785       memset(dciSlotAlloc, 0, sizeof(DlMsgSchInfo));
1786    }
1787    else
1788       dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1];
1789
1790    /* Fill PDCCH and PDSCH scheduling information for Msg4 */
1791    if((schDlRsrcAllocMsg4(cell, pdschTime, ueId, dciSlotAlloc, pdschStartSymbol, pdschNumSymbols, isRetxMsg4, *msg4HqProc)) != ROK)
1792    {
1793       DU_LOG("\nERROR  -->  SCH: Scheduling of Msg4 failed in slot [%d]", pdschTime.slot);
1794       if(!dciSlotAlloc->dlMsgPdschCfg)
1795       {
1796          SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1797          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
1798       }
1799       return RFAILED;
1800    }
1801
1802    /* Check if both DCI and RAR are sent in the same slot.
1803     * If not, allocate memory RAR PDSCH slot to store RAR info
1804     */
1805    if(pdcchTime.slot == pdschTime.slot)
1806    {
1807       SCH_ALLOC(dciSlotAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
1808       if(!dciSlotAlloc->dlMsgPdschCfg)
1809       {
1810          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciSlotAlloc->dlMsgPdschCfg");
1811          SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
1812          SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1813          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
1814          return RFAILED;
1815       }
1816       memcpy(dciSlotAlloc->dlMsgPdschCfg, &dciSlotAlloc->dlMsgPdcchCfg->dci.pdschCfg, sizeof(PdschCfg));
1817    }
1818    else
1819    {
1820       /* Allocate memory to schedule rarSlot to send RAR, pointer will be checked at schProcessSlotInd() */
1821       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULL)
1822       {
1823          SCH_ALLOC(msg4SlotAlloc, sizeof(DlMsgSchInfo));
1824          if(msg4SlotAlloc == NULLP)
1825          {
1826             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for msg4SlotAlloc");
1827             SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
1828             if(!dciSlotAlloc->dlMsgPdschCfg)
1829             {
1830                SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1831                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
1832             }
1833             return RFAILED;
1834          }
1835          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = msg4SlotAlloc;
1836          memset(msg4SlotAlloc, 0, sizeof(DlMsgSchInfo));
1837       }
1838       else
1839          msg4SlotAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
1840
1841       /* Copy all msg4 pdschcfg info */
1842       msg4SlotAlloc->crnti =dciSlotAlloc->crnti;
1843       msg4SlotAlloc->bwp = dciSlotAlloc->bwp;
1844       SCH_ALLOC(msg4SlotAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
1845       if(msg4SlotAlloc->dlMsgPdschCfg)
1846       {
1847          memcpy(msg4SlotAlloc->dlMsgPdschCfg, &dciSlotAlloc->dlMsgPdcchCfg->dci.pdschCfg, sizeof(PdschCfg));
1848       }
1849       else
1850       {
1851          SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));    
1852          if(dciSlotAlloc->dlMsgPdschCfg == NULLP)
1853          {
1854             SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1855             cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
1856
1857          }
1858          SCH_FREE(msg4SlotAlloc, sizeof(DlMsgSchInfo));
1859          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
1860          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for msg4SlotAlloc->dlMsgPdschCfg");
1861          return RFAILED;
1862       }
1863    }
1864
1865    /* PUCCH resource */
1866    schAllocPucchResource(cell, pucchTime, cell->raCb[ueId-1].tcrnti, &cell->ueCb[ueId-1], isRetxMsg4, *msg4HqProc);
1867
1868    cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
1869    cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
1870    cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
1871    cell->raCb[ueId-1].msg4recvd = FALSE;
1872    if(isRetxMsg4)
1873    {
1874       cell->ueCb[ueId-1].retxMsg4HqProc= NULLP;
1875    }
1876    return ROK;
1877 }
1878
1879 /*******************************************************************
1880  *
1881  * @brief sch Process pending Sr or Bsr Req
1882  *
1883  * @details
1884  *
1885  *    Function : updateBsrAndLcList
1886  *
1887  *    Functionality:
1888  *       Updating the BSRInfo in UECB and Lclist
1889  *
1890  * @params[in] SchCellCb *cell,  SlotTimingInfo currTime 
1891  * @return ROK     - success
1892  *         RFAILED - failure
1893  *
1894  *******************************************************************/
1895 void updateBsrAndLcList(CmLListCp *lcLL, BsrInfo *bsrInfo, uint8_t status)
1896 {
1897    CmLList *node = NULLP, *next = NULLP;
1898    LcInfo *lcNode = NULLP;
1899
1900    if(lcLL == NULLP)
1901    {
1902       DU_LOG("\nERROR --> SCH: LcList not present");
1903       return;
1904    }
1905
1906    if(lcLL->count)
1907    {
1908       node = lcLL->first;
1909    }
1910    else
1911    {
1912       /*lcLL is empty*/
1913       return;
1914    }
1915
1916    while(node)
1917    {
1918       next = node->next;
1919       lcNode = (LcInfo *)node->node;
1920       if(lcNode != NULLP)
1921       {
1922           /*Only when Status is OK then allocation is marked as ZERO and reqBO
1923            * is updated in UE's DB. If Failure, then allocation is added to reqBO 
1924            * and same is updated in Ue's DB inside BSR Info structure*/
1925          if(status == ROK)
1926          {
1927             lcNode->allocBO = 0;
1928          }
1929
1930          lcNode->reqBO += lcNode->allocBO;
1931          bsrInfo[lcNode->lcId].dataVol = lcNode->reqBO;
1932          if(lcNode->reqBO == 0)
1933          {
1934             handleLcLList(lcLL, lcNode->lcId, DELETE);
1935          }
1936       }
1937       node = next;
1938    }
1939 }
1940
1941 /*******************************************************************
1942  *
1943  * @brief sch Process pending Sr or Bsr Req
1944  *
1945  * @details
1946  *
1947  *    Function : schProcessSrOrBsrReq
1948  *
1949  *    Functionality:
1950  *       sch Process pending Sr or Bsr Req
1951  *
1952  * @params[in] SchCellCb *cell,  SlotTimingInfo currTime
1953  * @params[in] uint8_t ueId, Bool isRetx, SchUlHqProcCb **hqP
1954  * @return true  - success
1955  *         false - failure
1956  *
1957  *******************************************************************/
1958 bool schProcessSrOrBsrReq(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool isRetx, SchUlHqProcCb **hqP)
1959 {
1960    bool k2Found = FALSE;
1961    uint8_t startSymb = 0, symbLen = 0;
1962    uint8_t k2TblIdx = 0, k2Index = 0, k2Val = 0;
1963    SchUeCb *ueCb;
1964    SchK2TimingInfoTbl *k2InfoTbl=NULLP;
1965    SlotTimingInfo dciTime, puschTime;
1966    
1967    if(cell == NULLP)
1968    {
1969       DU_LOG("\nERROR  -->  SCH: schProcessSrOrBsrReq() : Cell is NULL");
1970       return false;
1971    }
1972
1973    ueCb = &cell->ueCb[ueId-1];
1974
1975    if(ueCb == NULLP)
1976    {
1977       DU_LOG("\nERROR  -->  SCH: schProcessSrOrBsrReq() : UE is NULL");
1978       return false;
1979    }
1980
1981    if (isRetx == FALSE)
1982    {
1983       if (schUlGetAvlHqProcess(cell, ueCb, hqP) != ROK)
1984       {
1985          return RFAILED;
1986       }
1987    }
1988
1989    /* Calculating time frame to send DCI for SR */
1990    ADD_DELTA_TO_TIME(currTime, dciTime, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1991 #ifdef NR_TDD
1992    if(schGetSlotSymbFrmt(dciTime.slot, cell->slotFrmtBitMap) == DL_SLOT)
1993 #endif
1994    {     
1995       if(ueCb->k2TblPrsnt)
1996          k2InfoTbl = &ueCb->k2InfoTbl;
1997       else
1998          k2InfoTbl =  &cell->k2InfoTbl;
1999
2000       for(k2TblIdx = 0; k2TblIdx < k2InfoTbl->k2TimingInfo[dciTime.slot].numK2; k2TblIdx++)
2001       {
2002          k2Index = k2InfoTbl->k2TimingInfo[dciTime.slot].k2Indexes[k2TblIdx];
2003
2004          if(!ueCb->k2TblPrsnt)
2005          {
2006             k2Val = cell->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].k2;
2007             startSymb = cell->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].startSymbol;
2008             symbLen = cell->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].symbolLength;
2009          }
2010          else
2011          {
2012             k2Val = ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.puschCfg.timeDomRsrcAllocList[k2Index].k2;
2013             startSymb =  ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.puschCfg.timeDomRsrcAllocList[k2Index].startSymbol;
2014             symbLen =  ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.puschCfg.timeDomRsrcAllocList[k2Index].symbolLength;
2015          }
2016          /* Check for number of Symbol of PUSCH should be same as original in case of transmisson*/
2017          /* Calculating time frame to send PUSCH for SR */
2018          ADD_DELTA_TO_TIME(dciTime, puschTime, k2Val, cell->numSlots);
2019 #ifdef NR_TDD
2020          if(schGetSlotSymbFrmt(puschTime.slot, cell->slotFrmtBitMap) == DL_SLOT)
2021             continue;
2022 #endif
2023          if(cell->schUlSlotInfo[puschTime.slot]->puschUe != 0)
2024          {
2025             continue;
2026          }
2027          k2Found = true;
2028          if(hqP)
2029          {
2030             ADD_DELTA_TO_TIME(puschTime, (*hqP)->puschTime, 0, cell->numSlots);
2031          }
2032          break;
2033       }
2034    }
2035    
2036    if(k2Found == true)
2037    {
2038       if(cell->api->SchScheduleUlLc(dciTime, puschTime, startSymb, symbLen, isRetx, hqP) != ROK)
2039          return false;
2040    }
2041    else
2042    {
2043       DU_LOG("\nDEBUG  -->  SCH : schProcessSrOrBsrReq(): K2 value is not found");
2044       return false;     
2045    }
2046    return true;
2047 }
2048
2049 /********************************************************************************
2050  *
2051  * @brief Increment the Slot by a input factor
2052  *
2053  * @details
2054  *
2055  *    Function : schIncrSlot
2056  *
2057  *    Functionality:
2058  *       Increment the slot by a input factor till num of Slots configured in a
2059  *       Radio Frame. If it exceeds, move to next sfn.
2060  *
2061  * @params[in/out] SlotTimingInfo timingInfo
2062  *        [in]     uint8_t incr [Increment factor]
2063  *        [in]     numSlotsPerRF [Number of Slots configured per RF as per
2064  *                                numerology]
2065  * @return ROK     - success
2066  *         RFAILED - failure
2067  *
2068  *******************************************************************/
2069 void schIncrSlot(SlotTimingInfo *timingInfo, uint8_t incr, uint16_t numSlotsPerRF)
2070 {
2071    timingInfo->slot += incr;
2072    if(timingInfo->slot >= numSlotsPerRF)
2073    {
2074       timingInfo->sfn += timingInfo->slot/numSlotsPerRF;
2075       timingInfo->slot %= numSlotsPerRF;
2076       if(timingInfo->sfn >  MAX_SFN)
2077       {
2078          timingInfo->sfn %= MAX_SFN;
2079       }
2080    }
2081 }
2082
2083 /*******************************************************************
2084 *
2085 * @brief   Fill PDSCH info in Page Alloc
2086 *
2087 * @details
2088 *
2089 *    Function : schFillPagePdschCfg 
2090 *
2091 *    Functionality: Fill PDSCH info in Page Alloc
2092 *
2093 * @params[in] SchCellCb *cell, PdschCfg *pagePdschCfg, SlotTimingInfo slotTime, 
2094 *             uint16_t tbsSize, uint8_t mcs, uint16_t startPrb
2095 *
2096 * @return pointer to return Value(ROK, RFAILED) 
2097 *
2098 * ****************************************************************/
2099 uint8_t schFillPagePdschCfg(SchCellCb *cell, PageDlSch *pageDlSch, SlotTimingInfo slotTime, uint16_t tbSize, uint8_t mcs, uint16_t startPrb)
2100 {
2101    uint8_t dmrsStartSymbol, startSymbol, numSymbol;
2102
2103    /* fill the PDSCH PDU */
2104
2105    pageDlSch->tbInfo.mcs = mcs;
2106    tbSize = tbSize + TX_PAYLOAD_HDR_LEN;
2107    pageDlSch->tbInfo.tbSize = tbSize;
2108    pageDlSch->dmrs.dmrsType = 0; /* type-1 */
2109    pageDlSch->dmrs.nrOfDmrsSymbols               = NUM_DMRS_SYMBOLS;
2110    pageDlSch->dmrs.dmrsAddPos                    = DMRS_ADDITIONAL_POS;
2111
2112    /* the RB numbering starts from coreset0, and PDSCH is always above SSB */
2113    pageDlSch->freqAlloc.startPrb  = startPrb;
2114    pageDlSch->freqAlloc.numPrb    = schCalcNumPrb(tbSize, mcs, NUM_PDSCH_SYMBOL);
2115    pageDlSch->vrbPrbMapping       = 0; /* non-interleaved */
2116    /* This is Intel's requirement. PDSCH should start after PDSCH DRMS symbol */
2117    pageDlSch->timeAlloc.mappingType         = DMRS_MAP_TYPE_A; /* Type-A */
2118    pageDlSch->timeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
2119    pageDlSch->timeAlloc.numSymb   = NUM_PDSCH_SYMBOL;
2120
2121    /* Find total symbols occupied including DMRS */
2122    dmrsStartSymbol = findDmrsStartSymbol(4);
2123    /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
2124     * in that case only PDSCH symbols are marked as occupied */
2125    if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
2126    {
2127       startSymbol = pageDlSch->timeAlloc.startSymb;
2128       numSymbol = pageDlSch->timeAlloc.numSymb;
2129    }
2130    /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
2131    else
2132    {
2133       startSymbol = dmrsStartSymbol;
2134       numSymbol = pageDlSch->dmrs.nrOfDmrsSymbols + pageDlSch->timeAlloc.numSymb;
2135    }
2136
2137    /* Allocate the number of PRBs required for DL PDSCH */
2138    if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
2139                &pageDlSch->freqAlloc.startPrb, pageDlSch->freqAlloc.numPrb)) != ROK)
2140    {
2141       DU_LOG("\nERROR  --> SCH : allocatePrbDl() failed for DL MSG");
2142       return RFAILED;
2143    }
2144    return ROK;
2145 }
2146
2147 /**
2148  * @brief Handles retransmission for MSG3
2149  *
2150  * @details
2151  *
2152  *     Function : schMsg3RetxSchedulingForUe
2153  *      
2154  *      This function handles retransmission for MSG3
2155  *           
2156  *  @param[in]  SchRaCb *raCb, RA cb pointer
2157  *  @return  
2158  *      -# ROK
2159  *      -# RFAILED
2160  **/
2161 uint8_t schMsg3RetxSchedulingForUe(SchRaCb *raCb)
2162 {
2163    bool      k2Found = false;
2164    uint16_t             dciSlot = 0;
2165    SlotTimingInfo       dciTime, msg3Time;
2166    SchCellCb            *cell = NULLP;
2167    SlotTimingInfo       currTime;
2168    DciInfo  *dciInfo = NULLP;
2169    cell = raCb->cell;
2170    currTime = cell->slotInfo;
2171
2172    /* Calculating time frame to send DCI for MSG3 Retx*/
2173    ADD_DELTA_TO_TIME(currTime, dciTime, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
2174 #ifdef NR_TDD
2175    /* Consider this slot for sending DCI, only if it is a DL slot */
2176    if(schGetSlotSymbFrmt(dciSlot, raCb->cell->slotFrmtBitMap) == DL_SLOT)
2177 #endif
2178    {
2179       /* If PDCCH is already scheduled on this slot, cannot schedule PDSCH for another UE here. */
2180       if(cell->schDlSlotInfo[dciSlot]->pdcchUe != 0)
2181          return false;
2182
2183       k2Found = schGetMsg3K2(cell, &raCb->msg3HqProc, dciTime.slot, &msg3Time, TRUE);
2184
2185       if (!k2Found)
2186       {
2187          return RFAILED;
2188       }
2189       SCH_ALLOC(dciInfo, sizeof(DciInfo));
2190       if(!dciInfo)
2191       {
2192          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciInfo alloc");
2193          return RFAILED;
2194       }
2195       cell->schDlSlotInfo[msg3Time.slot]->ulGrant = dciInfo;
2196       SCH_ALLOC(cell->schUlSlotInfo[msg3Time.slot]->schPuschInfo, sizeof(SchPuschInfo));
2197       memset(dciInfo,0,sizeof(DciInfo));
2198       schFillUlDciForMsg3Retx(raCb, cell->schUlSlotInfo[msg3Time.slot]->schPuschInfo, dciInfo);
2199    }   
2200    raCb->retxMsg3HqProc = NULLP;
2201    return ROK;
2202 }
2203
2204 /**
2205  * @brief Get K2 value for MSG3
2206  *
2207  * @details
2208  *
2209  *     Function : schGetMsg3K2
2210  *      
2211  *      This function gets K2 for MSG3
2212  *           
2213  *  @param[in]  SchCellCb *cell, Cell cb struc pointer
2214  *  @param[in]  SchUlHqProcCb* msg3HqProc, msg3 harq proc pointer
2215  *  @param[in]  uint16_t dlTime, DL time of scheduling
2216  *  @param[in]  SlotTimingInfo *msg3Time, MSG3 timing info
2217  *  @param[in]  bool isRetx, indicates MSG3 retransmission
2218  *  @return  
2219  *      -# true
2220  *      -# false
2221  **/
2222 bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, SlotTimingInfo *msg3Time, bool isRetx)
2223 {
2224    bool      k2Found = false;
2225    uint8_t   k2TblIdx = 0;
2226    uint8_t   k2Index = 0;
2227    uint8_t   k2 = 0;
2228    uint8_t   numK2 = 0;
2229    uint8_t   puschMu = 0;
2230    uint8_t   msg3Delta = 0, msg3MinSchTime = 0;
2231 #ifdef NR_TDD
2232    uint8_t   totalCfgSlot = 0;
2233 #endif
2234    SchK2TimingInfoTbl   *msg3K2InfoTbl=NULLP;
2235    SlotTimingInfo       currTime, msg3TempTime;
2236    currTime = cell->slotInfo;
2237    puschMu = cell->numerology;
2238
2239    if (isRetx)
2240    {
2241       if(!msg3HqProc)
2242          return false;
2243
2244       numK2 = cell->k2InfoTbl.k2TimingInfo[dlTime].numK2;
2245       msg3K2InfoTbl = &cell->msg3K2InfoTbl;
2246       msg3MinSchTime = 0;
2247       msg3Delta = 0;
2248    }
2249    else
2250    {
2251       numK2 = cell->msg3K2InfoTbl.k2TimingInfo[dlTime].numK2;
2252       msg3K2InfoTbl = &cell->k2InfoTbl;
2253       msg3MinSchTime = minMsg3SchTime[cell->numerology];
2254       msg3Delta = puschDeltaTable[puschMu];
2255    }
2256
2257    for(k2TblIdx = 0; k2TblIdx < numK2; k2TblIdx++)
2258    {
2259       k2Index = msg3K2InfoTbl->k2TimingInfo[dlTime].k2Indexes[k2TblIdx];
2260
2261       k2 = cell->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].k2;
2262       if (isRetx)
2263       {
2264          if ((msg3HqProc->strtSymbl != cell->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].startSymbol) ||
2265             (msg3HqProc->numSymbl != cell->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList[k2Index].symbolLength))
2266          {
2267             continue;
2268          }
2269       }
2270       /* Delta is added to the slot allocation for msg3 based on 38.214 section 6.1.2.1 */
2271       k2 = k2 + msg3Delta;
2272       if(k2 >= msg3MinSchTime)
2273       {
2274          ADD_DELTA_TO_TIME(currTime, msg3TempTime, k2, cell->numSlots);
2275 #ifdef NR_TDD
2276          if(schGetSlotSymbFrmt(msg3TempTime.slot % totalCfgSlot, cell->slotFrmtBitMap) == DL_SLOT)
2277             continue;
2278 #endif
2279          /* If PUSCH is already scheduled on this slot, another PUSCH
2280           * pdu cannot be scheduled here */
2281          if(cell->schUlSlotInfo[msg3TempTime.slot]->puschUe != 0)
2282             continue;
2283          k2Found = true;
2284          break;
2285       }
2286    }
2287    if (k2Found == true)
2288    {
2289       msg3Time->slot = msg3TempTime.slot;
2290       msg3Time->sfn = msg3TempTime.sfn;
2291       msg3Time->slot = msg3TempTime.slot;
2292    }
2293    return k2Found;
2294 }
2295
2296 /**********************************************************************
2297   End of file
2298  **********************************************************************/
2299