[Epic-ID: ODUHIGH-488][Task-ID: ODUHIGH-501] WG8 Alignment | Ue reset req and rsp
[o-du/l2.git] / src / 5gnrsch / sch.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:     sch.c
22   
23      Type:     C source file
24   
25      Desc:     C source code for scheduler fucntions
26   
27      File:     sch.c
28   
29 **********************************************************************/
30
31 /** @file sch.c
32 @brief This file implements the schedulers main access to MAC layer code.
33 */
34 #include "common_def.h" 
35 #include "du_app_mac_inf.h"
36 #include "lrg.h"
37 #include "tfu.h"
38 #include "du_log.h"
39 #include "rgr.h"
40 #include "rg_sch_inf.h"
41 #include "rg_sch.h"
42
43 #include "tfu.x"           /* TFU types */
44 #include "lrg.x"           /* layer management typedefs for MAC */
45 #include "rgr.x"           /* layer management typedefs for MAC */
46 #include "rg_sch_inf.x"         /* typedefs for Scheduler */
47 #include "mac_sch_interface.h"
48 #include "sch.h"
49 #include "sch_utils.h"
50 #include "sch_fcfs.h"
51 #include "sch_slice_based.h"
52
53 /**
54  * @brief Task Initiation function. 
55  *
56  * @details
57  *
58  *     Function : schActvInit
59  *     
60  *     This function is supplied as one of parameters during MAC's 
61  *     task registration. MAC will invoke this function once, after
62  *     it creates and attaches this TAPA Task to a system task.
63  *     
64  *  @param[in]  Ent Entity, the entity ID of this task.     
65  *  @param[in]  Inst Inst, the instance ID of this task.
66  *  @param[in]  Region Region, the region ID registered for memory 
67  *              usage of this task.
68  *  @param[in]  Reason Reason.
69  *  @return  int
70  *      -# ROK
71  **/
72 uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason)
73 {
74    Inst inst = (instId  - SCH_INST_START);
75
76    /* Initialize the MAC TskInit structure to zero */
77    memset ((uint8_t *)&schCb[inst], 0, sizeof(schCb));
78
79    /* Initialize the MAC TskInit with received values */
80    schCb[inst].schInit.ent = entity;
81    schCb[inst].schInit.inst = inst;
82    schCb[inst].schInit.region = region;
83    schCb[inst].schInit.pool = 0;
84    schCb[inst].schInit.reason = reason;
85    schCb[inst].schInit.cfgDone = FALSE;
86    schCb[inst].schInit.acnt = FALSE;
87    schCb[inst].schInit.usta = FALSE;
88    schCb[inst].schInit.trc = FALSE;
89    schCb[inst].schInit.procId = ODU_GET_PROCID();
90
91    return ROK;
92 } /* schActvInit */
93
94 /**
95  * @brief Scheduler All Apis initialized. 
96  *
97  * @details
98  *
99  *     Function : schAllApisInit
100  *     
101  *     This function initializes all Scheduler APIs/functionality for each kind
102  *     of scheduler type. 
103  *     
104  *  @param[in]  Inst inst, the Scheduler instance 
105  *  @return  void
106  **/
107 void schAllApisInit(Inst inst)
108 {
109     schFcfsAllApisInit(&schCb[inst].allApis[SCH_FCFS]);  
110     schSliceBasedAllApisInit(&schCb[inst].allApis[SCH_SLICE_BASED]);
111 }
112
113 /**
114  * @brief Scheduler instance Configuration Handler. 
115  *
116  * @details
117  *
118  *     Function : SchInstCfg
119  *     
120  *     This function in called by SchProcGenCfgReq(). It handles the
121  *     general configurations of the scheduler instance. Returns
122  *     reason for success/failure of this function.
123  *     
124  *  @param[in]  RgCfg *cfg, the Configuaration information 
125  *  @return  uint16_t
126  *      -# LCM_REASON_NOT_APPL 
127  *      -# LCM_REASON_INVALID_MSGTYPE
128  *      -# LCM_REASON_MEM_NOAVAIL
129  **/
130 uint8_t SchInstCfg(RgCfg *cfg, Inst  dInst)
131 {
132    uint16_t ret = LCM_REASON_NOT_APPL;
133    Inst     inst = (dInst - SCH_INST_START);
134
135    DU_LOG("\nDEBUG  -->  SCH : Entered SchInstCfg()");
136    /* Check if Instance Configuration is done already */
137    if (schCb[inst].schInit.cfgDone == TRUE)
138    {
139       return LCM_REASON_INVALID_MSGTYPE;
140    }
141    /* Update the Pst structure for LM interface */
142    memcpy(&schCb[inst].schInit.lmPst, &cfg->s.schInstCfg.genCfg.lmPst, sizeof(Pst));
143
144    schCb[inst].schInit.inst = inst;
145    schCb[inst].schInit.lmPst.srcProcId = schCb[inst].schInit.procId;
146    schCb[inst].schInit.lmPst.srcEnt = schCb[inst].schInit.ent;
147    schCb[inst].schInit.lmPst.srcInst = schCb[inst].schInit.inst +
148       SCH_INST_START;
149    schCb[inst].schInit.lmPst.event = EVTNONE;
150
151    schCb[inst].schInit.region = cfg->s.schInstCfg.genCfg.mem.region;
152    schCb[inst].schInit.pool = cfg->s.schInstCfg.genCfg.mem.pool;
153    schCb[inst].genCfg.tmrRes = cfg->s.schInstCfg.genCfg.tmrRes;
154 #ifdef LTE_ADV
155    schCb[inst].genCfg.forceCntrlSrbBoOnPCel =  cfg->s.schInstCfg.genCfg.forceCntrlSrbBoOnPCel;
156    schCb[inst].genCfg.isSCellActDeactAlgoEnable =  cfg->s.schInstCfg.genCfg.isSCellActDeactAlgoEnable;
157 #endif
158    schCb[inst].genCfg.startCellId    = cfg->s.schInstCfg.genCfg.startCellId;
159
160    /* Initialzie the timer queue */   
161    memset(&schCb[inst].tmrTq, 0, sizeof(CmTqType) * SCH_TQ_SIZE);
162    /* Initialize the timer control point */
163    memset(&schCb[inst].tmrTqCp, 0, sizeof(CmTqCp));
164    schCb[inst].tmrTqCp.tmrLen = RGSCH_TQ_SIZE;
165
166    /* SS_MT_TMR needs to be enabled as schActvTmr needs instance information */
167    /* Timer Registration request to system services */
168    if (ODU_REG_TMR_MT(schCb[inst].schInit.ent, dInst, (int)schCb[inst].genCfg.tmrRes, schActvTmr) != ROK)
169    {
170       DU_LOG("\nERROR  -->  SCH : SchInstCfg(): Failed to "
171             "register timer.");
172       return (LCM_REASON_MEM_NOAVAIL);
173    }   
174               
175    /* Set Config done in TskInit */
176    schCb[inst].schInit.cfgDone = TRUE;
177    DU_LOG("\nINFO   -->  SCH : Scheduler gen config done");
178    
179    schAllApisInit(inst);
180    return ret;
181 }
182
183 /**
184  * @brief Layer Manager Configuration request handler. 
185  *
186  * @details
187  *
188  *     Function : SchProcGenCfgReq
189  *     
190  *     This function handles the configuration
191  *     request received at scheduler instance from the Layer Manager.
192  *     -# Based on the cfg->hdr.elmId.elmnt value it invokes one of the
193  *        functions rgHdlGenCfg() or rgHdlSapCfg().
194  *     -# Invokes RgMiLrgSchCfgCfm() to send back the confirmation to the LM.
195  *     
196  *  @param[in]  Pst *pst, the post structure     
197  *  @param[in]  RgMngmt *cfg, the configuration parameter's structure
198  *  @return  S16
199  *      -# ROK
200  **/
201 uint8_t SchProcGenCfgReq(Pst *pst, RgMngmt *cfg)
202 {
203    uint8_t   ret = LCM_PRIM_OK;
204    uint16_t  reason = LCM_REASON_NOT_APPL;
205    RgMngmt   cfm;
206    Pst       cfmPst;
207
208    if(pst->dstInst < SCH_INST_START)
209    {
210       DU_LOG("\nERROR  -->  SCH : Invalid inst ID");
211       DU_LOG("\nERROR  -->  SCH : SchProcGenCfgReq(): "
212             "pst->dstInst=%d SCH_INST_START=%d", pst->dstInst,SCH_INST_START); 
213       return ROK;
214    }
215    DU_LOG("\nINFO   -->  SCH : Received scheduler gen config");
216    /* Fill the post structure for sending the confirmation */
217    memset(&cfmPst, 0 , sizeof(Pst));
218    SchFillCfmPst(pst, &cfmPst, cfg);
219
220    memset(&cfm, 0, sizeof(RgMngmt));
221
222 #ifdef LMINT3
223    cfm.hdr.transId =
224       cfg->hdr.transId;
225 #endif
226
227    cfm.hdr.elmId.elmnt = cfg->hdr.elmId.elmnt;
228    switch(cfg->hdr.elmId.elmnt)
229    {
230       case STSCHINST:
231          reason = SchInstCfg(&cfg->t.cfg,pst->dstInst );
232          break;
233       default:
234          ret = LCM_PRIM_NOK;
235          reason = LCM_REASON_INVALID_ELMNT;
236          DU_LOG("\nERROR  -->  SCH : Invalid Elmnt=%d", cfg->hdr.elmId.elmnt);
237          break;
238    }
239
240    if (reason != LCM_REASON_NOT_APPL)
241    {
242       ret = LCM_PRIM_NOK;
243    }
244
245    cfm.cfm.status = ret;
246    cfm.cfm.reason = reason;
247
248    SchSendCfgCfm(&cfmPst, &cfm);
249    /*   SCH_FREE(pst->region, pst->pool, (Data *)cfg, sizeof(RgMngmt)); */
250
251    return ROK;
252 }/*-- SchProcGenCfgReq --*/
253
254 #ifdef NR_TDD
255 /**
256  *@brief Returns TDD periodicity in micro seconds
257  *
258  * @details
259  * 
260  * Function : schGetPeriodicityInMsec 
261  * 
262  * This API retunrs TDD periodicity in micro seconds
263  * 
264  * @param[in] DlUlTxPeriodicity 
265  * @return  periodicityInMsec
266  * **/
267
268 uint16_t schGetPeriodicityInMsec(DlUlTxPeriodicity tddPeriod)
269 {
270    uint16_t  periodicityInMsec = 0;
271    switch(tddPeriod)
272    {
273       case TX_PRDCTY_MS_0P5:
274       {
275          periodicityInMsec = 500;
276          break;
277       }
278       case TX_PRDCTY_MS_0P625:
279       {
280          periodicityInMsec = 625;
281          break;
282       }
283       case TX_PRDCTY_MS_1:
284       {
285          periodicityInMsec = 1000;
286          break;
287       }
288       case TX_PRDCTY_MS_1P25:
289       {
290          periodicityInMsec = 1250;
291          break;
292       }
293       case TX_PRDCTY_MS_2:
294       {
295          periodicityInMsec = 2000;
296          break;
297       }
298       case TX_PRDCTY_MS_2P5:
299       {
300          periodicityInMsec = 2500;
301          break;
302       }
303       case TX_PRDCTY_MS_5:
304       {
305          periodicityInMsec = 5000;
306          break;
307       }
308       case TX_PRDCTY_MS_10:
309       {
310          periodicityInMsec = 10000;
311          break;
312       }
313       default:
314       {
315          DU_LOG("\nERROR  -->  SCH : Invalid DlUlTxPeriodicity:%d", tddPeriod);
316       }
317    }
318
319    return periodicityInMsec;
320 }
321
322 /**
323  *@brief Fills the slotCfg from CellCfg
324  *
325  * @details
326  * 
327  * Function : schFillSlotConfig 
328  * 
329  * This API Fills the slotCfg from CellCfg
330  * 
331  * @param[in] SchCellCb *cell, TDDCfg tddCfg
332  * @return  void
333  * **/
334 void schFillSlotConfig(SchCellCb *cell, TDDCfg tddCfg)
335 {
336    uint8_t slotIdx = 0, symbolIdx = 0;
337
338    for(slotIdx =0 ;slotIdx < MAX_TDD_PERIODICITY_SLOTS; slotIdx++) 
339    {
340       for(symbolIdx = 0; symbolIdx < MAX_SYMB_PER_SLOT; symbolIdx++)
341       {
342          /*Fill Full-DL Slots as well as DL symbols ini 1st Flexi Slo*/
343          if(slotIdx < tddCfg.nrOfDlSlots || \
344                (slotIdx == tddCfg.nrOfDlSlots && symbolIdx < tddCfg.nrOfDlSymbols)) 
345          {
346               cell->slotCfg[slotIdx][symbolIdx] = DL_SYMBOL; 
347          }
348
349          /*Fill Full-FLEXI SLOT and as well as Flexi Symbols in 1 slot preceding FULL-UL slot*/ 
350          else if(slotIdx < (MAX_TDD_PERIODICITY_SLOTS - tddCfg.nrOfUlSlots -1) ||  \
351                (slotIdx == (MAX_TDD_PERIODICITY_SLOTS - tddCfg.nrOfUlSlots -1) && \
352                 symbolIdx < (MAX_SYMB_PER_SLOT - tddCfg.nrOfUlSymbols)))
353          {
354               cell->slotCfg[slotIdx][symbolIdx] = FLEXI_SYMBOL; 
355          }
356          /*Fill Partial UL symbols and Full-UL slot*/
357          else
358          {
359               cell->slotCfg[slotIdx][symbolIdx] = UL_SYMBOL; 
360          }
361       }
362    }
363 }
364
365 /**
366  * @brief init TDD slot config 
367  *
368  * @details
369  *
370  *     Function : schInitTddSlotCfg 
371  *      
372  *      This API is invoked after receiving schCellCfg
373  *           
374  *  @param[in]  schCellCb *cell
375  *  @param[in]  SchCellCfg *schCellCfg
376  *  @return  void
377  **/
378 void schInitTddSlotCfg(SchCellCb *cell, SchCellCfg *schCellCfg)
379 {
380    uint16_t periodicityInMicroSec = 0;
381    int8_t slotIdx, symbIdx;
382
383    periodicityInMicroSec = schGetPeriodicityInMsec(schCellCfg->tddCfg.tddPeriod);
384    cell->numSlotsInPeriodicity = (periodicityInMicroSec * pow(2, schCellCfg->numerology))/1000;
385    cell->slotFrmtBitMap = 0;
386    schFillSlotConfig(cell, schCellCfg->tddCfg);
387    for(slotIdx = cell->numSlotsInPeriodicity-1; slotIdx >= 0; slotIdx--)
388    {
389       symbIdx = 0;
390       /* If the first and last symbol are the same, the entire slot is the same type */
391       if((cell->slotCfg[slotIdx][symbIdx] == cell->slotCfg[slotIdx][MAX_SYMB_PER_SLOT-1]) &&
392               cell->slotCfg[slotIdx][symbIdx] != FLEXI_SYMBOL)
393       {
394          switch(cell->slotCfg[slotIdx][symbIdx])
395          {
396             case DL_SLOT:
397             {
398                /*BitMap to be set to 00 */
399                cell->slotFrmtBitMap = (cell->slotFrmtBitMap<<2);
400                break;
401             }
402             case UL_SLOT:
403             {
404                /*BitMap to be set to 01 */
405                cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (UL_SLOT));
406                break;
407             }
408             default:
409                DU_LOG("\nERROR  -->  SCH : Invalid slot Config in schInitTddSlotCfg");
410            }
411          continue;
412       }
413       /* slot config is flexible. First set slotBitMap to 10 */
414       cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (FLEXI_SLOT));
415    }
416 }
417 #endif
418
419 /**
420  * @brief Fill SSB start symbol
421  *
422  * @details
423  *
424  *     Function : fillSsbStartSymb 
425  *      
426  *      This API stores SSB start index per beam
427  *           
428  *  @param[in]  SchCellCb     *cellCb
429  *  @return  int
430  *      -# ROK 
431  *      -# RFAILED 
432  **/
433 void fillSsbStartSymb(SchCellCb *cellCb)
434 {
435    uint8_t cnt, scs, symbIdx, ssbStartSymbArr[SCH_MAX_SSB_BEAM];
436
437    scs = cellCb->cellCfg.scsCommon;
438
439    memset(ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
440    symbIdx = 0;
441    /* Determine value of "n" based on Section 4.1 of 3GPP TS 38.213 */
442    switch(scs)
443    {
444       case SCS_15KHZ:
445          {
446             if(cellCb->cellCfg.ssbFrequency <= 300000)
447                cnt = 2;/* n = 0, 1 */
448             else
449                cnt = 4; /* n = 0, 1, 2, 3 */
450             for(uint8_t idx=0; idx<cnt; idx++)
451             {
452                /* start symbol determined using {2, 8} + 14n */
453                ssbStartSymbArr[symbIdx++] = 2 +  MAX_SYMB_PER_SLOT*idx;
454                ssbStartSymbArr[symbIdx++] = 8 +  MAX_SYMB_PER_SLOT*idx;
455             }
456          }
457          break;
458       case SCS_30KHZ:
459          {
460             if(cellCb->cellCfg.ssbFrequency <= 300000)
461                cnt = 1;/* n = 0 */
462             else
463                cnt = 2; /* n = 0, 1 */
464             for(uint8_t idx=0; idx<cnt; idx++)
465             {
466                /* start symbol determined using {4, 8, 16, 20} + 28n */
467                ssbStartSymbArr[symbIdx++] = 4 +  MAX_SYMB_PER_SLOT*idx;
468                ssbStartSymbArr[symbIdx++] = 8 +  MAX_SYMB_PER_SLOT*idx;
469                ssbStartSymbArr[symbIdx++] = 16 +  MAX_SYMB_PER_SLOT*idx;
470                ssbStartSymbArr[symbIdx++] = 20 +  MAX_SYMB_PER_SLOT*idx;
471             }
472          }
473          break;
474       default:
475          DU_LOG("\nERROR  -->  SCH : SCS %d is currently not supported", scs);
476    }
477    memset(cellCb->ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
478    memcpy(cellCb->ssbStartSymbArr, ssbStartSymbArr, SCH_MAX_SSB_BEAM);
479 }
480
481
482 /**
483  * @brief init cellCb based on cellCfg
484  *
485  * @details
486  *
487  *     Function : schInitCellCb 
488  *      
489  *      This API is invoked after receiving schCellCfg
490  *           
491  *  @param[in]  schCellCb *cell
492  *  @param[in]  SchCellCfg *schCellCfg
493  *  @return  int
494  *      -# ROK 
495  *      -# RFAILED 
496  **/
497 uint8_t schInitCellCb(Inst inst, SchCellCfg *schCellCfg)
498 {
499    SchCellCb *cell= NULLP;
500    SCH_ALLOC(cell, sizeof(SchCellCb));
501    if(!cell)
502    {
503       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
504       return RFAILED;
505    }
506
507    cell->cellId = schCellCfg->cellId; 
508    cell->instIdx = inst;
509    switch(schCellCfg->numerology)
510    {
511       case SCH_NUMEROLOGY_0:
512          {
513             cell->numSlots = SCH_MU0_NUM_SLOTS;
514          }
515          break;
516       case SCH_NUMEROLOGY_1:
517          {
518             cell->numSlots = SCH_MU1_NUM_SLOTS;
519          }
520          break;
521       case SCH_NUMEROLOGY_2:
522          {
523             cell->numSlots = SCH_MU2_NUM_SLOTS;
524          }
525          break;
526       case SCH_NUMEROLOGY_3:
527          {
528             cell->numSlots = SCH_MU3_NUM_SLOTS;
529          }
530          break;
531       case SCH_NUMEROLOGY_4:
532          {
533             cell->numSlots = SCH_MU4_NUM_SLOTS;
534          }
535          break;
536       default:
537          DU_LOG("\nERROR  -->  SCH : Numerology %d not supported", schCellCfg->numerology);
538    }
539 #ifdef NR_TDD
540    schInitTddSlotCfg(cell, schCellCfg);   
541 #endif
542
543    SCH_ALLOC(cell->schDlSlotInfo, cell->numSlots * sizeof(SchDlSlotInfo*));
544    if(!cell->schDlSlotInfo)
545    {
546       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb for schDlSlotInfo");
547       return RFAILED;
548    }
549
550    SCH_ALLOC(cell->schUlSlotInfo, cell->numSlots * sizeof(SchUlSlotInfo*));
551    if(!cell->schUlSlotInfo)
552    {
553       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb for schUlSlotInfo");
554       return RFAILED;
555    }
556
557    for(uint8_t idx=0; idx<cell->numSlots; idx++)
558    {
559       SchDlSlotInfo *schDlSlotInfo;
560       SchUlSlotInfo *schUlSlotInfo;
561
562       /* DL Alloc */
563       SCH_ALLOC(schDlSlotInfo, sizeof(SchDlSlotInfo));
564       if(!schDlSlotInfo)
565       {
566          DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
567          return RFAILED;
568       }
569
570       /* UL Alloc */
571       SCH_ALLOC(schUlSlotInfo, sizeof(SchUlSlotInfo));
572       if(!schUlSlotInfo)
573       {
574          DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
575          return RFAILED;
576       }
577
578       schInitDlSlot(schDlSlotInfo);
579       schInitUlSlot(schUlSlotInfo);
580
581       cell->schDlSlotInfo[idx] = schDlSlotInfo;
582       cell->schUlSlotInfo[idx] = schUlSlotInfo;
583
584    }
585    cell->firstSsbTransmitted = false;
586    cell->firstSib1Transmitted = false;
587    fillSsbStartSymb(cell);
588
589 #ifdef NR_DRX
590    memset(cell->drxCb, 0, MAX_DRX_SIZE*sizeof(SchDrxCb));
591 #endif   
592    schCb[inst].cells[inst] = cell;
593
594    DU_LOG("\nINFO  -->  SCH : Cell init completed for cellId:%d", cell->cellId);
595
596    return ROK;   
597 }
598
599 /**
600  * @brief Fill SIB1 configuration
601  *
602  * @details
603  *
604  *     Function : fillSchSib1Cfg
605  *
606  *     Fill SIB1 configuration
607  *
608  *  @param[in]  uint8_t bandwidth : total available bandwidth
609  *              uint8_t numSlots : total slots per SFN
610  *              SchSib1Cfg *sib1SchCfg : cfg to be filled
611  *              uint16_t pci : physical cell Id
612  *              uint8_t offsetPointA : offset
613  *  @return  void
614  **/
615 uint8_t fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots,SchPdcchConfigSib1 *pdcchCfgSib1,\
616                SchSib1Cfg *sib1SchCfg, uint16_t pci, uint8_t offsetPointA, uint16_t sib1PduLen)
617 {
618    uint8_t coreset0Idx = 0;
619    uint8_t searchSpace0Idx = 0;
620    //uint8_t ssbMuxPattern = 0;
621    uint8_t numRbs = 0;
622    uint8_t numSymbols = 0;
623    uint8_t offset = 0;
624    uint8_t oValue = 0;
625    //uint8_t numSearchSpacePerSlot = 0;
626    uint8_t mValue = 0;
627    uint8_t firstSymbol = 0; /* need to calculate using formula mentioned in 38.213 */
628    uint8_t slotIndex = 0;
629    uint8_t FreqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
630    uint16_t tbSize = 0;
631    uint8_t ssbIdx = 0;
632    PdcchCfg *pdcch;
633    PdschCfg *pdsch;
634    BwpCfg *bwp;
635
636    pdcch = &(sib1SchCfg->sib1PdcchCfg);
637    bwp = &(sib1SchCfg->bwp);
638
639    coreset0Idx     = pdcchCfgSib1->coresetZeroIndex;
640    searchSpace0Idx = pdcchCfgSib1->searchSpaceZeroIndex;
641
642    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
643    //ssbMuxPattern = coresetIdxTable[coreset0Idx][0];
644    numRbs        = coresetIdxTable[coreset0Idx][1];
645    numSymbols    = coresetIdxTable[coreset0Idx][2];
646    offset        = coresetIdxTable[coreset0Idx][3];
647
648    /* derive the search space params from table 13-11 spec 38.213 */
649    oValue                = searchSpaceIdxTable[searchSpace0Idx][0];
650    //numSearchSpacePerSlot = searchSpaceIdxTable[searchSpace0Idx][1];
651    mValue                = searchSpaceIdxTable[searchSpace0Idx][2];
652    firstSymbol           = searchSpaceIdxTable[searchSpace0Idx][3];
653
654    /* calculate the n0, need to add the formulae, as of now the value is 0 
655     * Need to add the even and odd values of i during configuration 
656     * [(O . 2^u + i . M )  ] mod numSlotsPerSubframe 
657     * assuming u = 0, i = 0, numSlotsPerSubframe = 10
658     * Also, from this configuration, coreset0 is only on even subframe */
659    slotIndex = (int)((oValue*pow(2, mu)) + floor(ssbIdx*mValue))%numSlots;
660    sib1SchCfg->n0 = slotIndex;
661
662    /* fill BWP */
663    switch(bandwidth)
664    {
665       case BANDWIDTH_20MHZ:
666          {
667             bwp->freqAlloc.numPrb = TOTAL_PRB_20MHZ_MU0;
668          }
669          break;
670       case BANDWIDTH_100MHZ:
671          {
672             bwp->freqAlloc.numPrb = TOTAL_PRB_100MHZ_MU1;
673          }
674          break;
675       default:
676          DU_LOG("\nERROR  -->  SCH : Bandwidth %d not supported", bandwidth);
677
678    }
679    bwp->freqAlloc.startPrb = 0;
680    bwp->subcarrierSpacing  = 0;         /* 15Khz */
681    bwp->cyclicPrefix       = 0;              /* normal */
682
683    /* fill the PDCCH PDU */
684    pdcch->coresetCfg.coreSetSize = numRbs;
685    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
686    pdcch->coresetCfg.durationSymbols = numSymbols;
687    
688    /* Fill Bitmap for PRBs in coreset */
689    fillCoresetFeqDomAllocMap(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
690    covertFreqDomRsrcMapToIAPIFormat(FreqDomainResource, pdcch->coresetCfg.freqDomainResource);
691
692    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
693    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
694    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
695    pdcch->coresetCfg.coreSetType = 0;
696    pdcch->coresetCfg.shiftIndex = pci;
697    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
698    pdcch->numDlDci = 1;
699    pdcch->dci.rnti = SI_RNTI;
700    pdcch->dci.scramblingId = pci;
701    pdcch->dci.scramblingRnti = 0;
702    pdcch->dci.cceIndex = 0;
703    pdcch->dci.aggregLevel = 4;
704    pdcch->dci.beamPdcchInfo.numPrgs = 1;
705    pdcch->dci.beamPdcchInfo.prgSize = 1;
706    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
707    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
708    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
709    pdcch->dci.txPdcchPower.beta_pdcch_1_0= 0;
710    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
711    /* Storing pdschCfg pointer here. Required to access pdsch config while
712       fillig up pdcch pdu */
713    pdsch = &pdcch->dci.pdschCfg; 
714
715    /* fill the PDSCH PDU */
716    uint8_t cwCount = 0;
717    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
718    pdsch->rnti = 0xFFFF; /* SI-RNTI */
719    pdsch->pduIndex = 0;
720    pdsch->numCodewords = 1;
721    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
722    {
723       pdsch->codeword[cwCount].targetCodeRate = 308;
724       pdsch->codeword[cwCount].qamModOrder = 2;
725       pdsch->codeword[cwCount].mcsIndex = DEFAULT_MCS;
726       pdsch->codeword[cwCount].mcsTable = 0; /* notqam256 */
727       pdsch->codeword[cwCount].rvIndex = 0;
728       tbSize = schCalcTbSize(sib1PduLen + TX_PAYLOAD_HDR_LEN);
729       pdsch->codeword[cwCount].tbSize = tbSize;
730    }
731    pdsch->dataScramblingId                   = pci;
732    pdsch->numLayers                          = 1;
733    pdsch->transmissionScheme                 = 0;
734    pdsch->refPoint                           = 0;
735    pdsch->dmrs.dlDmrsSymbPos                 = DL_DMRS_SYMBOL_POS; 
736    pdsch->dmrs.dmrsConfigType                = 0; /* type-1 */
737    pdsch->dmrs.dlDmrsScramblingId            = pci;
738    pdsch->dmrs.scid                          = 0;
739    pdsch->dmrs.numDmrsCdmGrpsNoData          = 1;
740    pdsch->dmrs.dmrsPorts                     = 0x0001;
741    pdsch->dmrs.mappingType                   = DMRS_MAP_TYPE_A; /* Type-A */
742    pdsch->dmrs.nrOfDmrsSymbols               = NUM_DMRS_SYMBOLS;
743    pdsch->dmrs.dmrsAddPos                    = DMRS_ADDITIONAL_POS;
744
745    pdsch->pdschFreqAlloc.resourceAllocType   = 1; /* RAT type-1 RIV format */
746    /* the RB numbering starts from coreset0, and PDSCH is always above SSB */
747    pdsch->pdschFreqAlloc.startPrb  = offsetPointA + SCH_SSB_NUM_PRB;
748    pdsch->pdschFreqAlloc.numPrb    = schCalcNumPrb(tbSize, DEFAULT_MCS, NUM_PDSCH_SYMBOL);
749    pdsch->pdschFreqAlloc.vrbPrbMapping       = 0; /* non-interleaved */
750    pdsch->pdschTimeAlloc.rowIndex            = 1;
751    /* This is Intel's requirement. PDSCH should start after PDSCH DRMS symbol */
752    pdsch->pdschTimeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
753    pdsch->pdschTimeAlloc.numSymb   = NUM_PDSCH_SYMBOL;
754    pdsch->beamPdschInfo.numPrgs              = 1;
755    pdsch->beamPdschInfo.prgSize              = 1;
756    pdsch->beamPdschInfo.digBfInterfaces      = 0;
757    pdsch->beamPdschInfo.prg[0].pmIdx         = 0;
758    pdsch->beamPdschInfo.prg[0].beamIdx[0]    = 0;
759    pdsch->txPdschPower.powerControlOffset    = 0;
760    pdsch->txPdschPower.powerControlOffsetSS  = 0;
761
762    return ROK;
763 }
764
765 /**
766  * @brief cell config from MAC to SCH.
767  *
768  * @details
769  *
770  *     Function : macSchCellCfgReq
771  *      
772  *      This API is invoked by MAC to send cell config to SCH
773  *           
774  *  @param[in]  Pst            *pst
775  *  @param[in]  SchCellCfg     *schCellCfg
776  *  @return  int
777  *      -# ROK 
778  *      -# RFAILED 
779  **/
780 uint8_t SchProcCellCfgReq(Pst *pst, SchCellCfg *schCellCfg)
781 {
782    uint8_t ret = ROK;
783    SchCellCb *cellCb;
784    SchCellCfgCfm schCellCfgCfm;
785    Pst rspPst;
786    Inst inst = pst->dstInst - SCH_INST_START; 
787    uint8_t coreset0Idx = 0;
788    uint8_t numRbs = 0;
789    uint8_t offset = 0;
790    uint8_t freqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
791    SchPdschConfig pdschCfg;
792
793    schInitCellCb(inst, schCellCfg);
794    cellCb = schCb[inst].cells[inst]; //cells is of MAX_CELLS, why inst
795    cellCb->macInst = pst->srcInst;
796
797    /* derive the SIB1 config parameters */
798    ret = fillSchSib1Cfg(schCellCfg->numerology, schCellCfg->dlBandwidth, cellCb->numSlots,
799          &(schCellCfg->pdcchCfgSib1), &(cellCb->sib1SchCfg), schCellCfg->phyCellId,
800          schCellCfg->dlCfgCommon.schFreqInfoDlSib.offsetToPointA, schCellCfg->sib1PduLen);
801    
802    if(ret != ROK)
803    {
804       DU_LOG("\nERROR --> SCH : Failed to fill sib1 configuration");
805       return RFAILED;
806    }
807    memcpy(&cellCb->cellCfg, schCellCfg, sizeof(SchCellCfg));
808    schProcPagingCfg(cellCb);
809
810    /* Fill coreset frequencyDomainResource bitmap */
811    coreset0Idx = cellCb->cellCfg.dlCfgCommon.schInitialDlBwp.pdcchCommon.commonSearchSpace.coresetId;
812    numRbs = coresetIdxTable[coreset0Idx][1];
813    offset = coresetIdxTable[coreset0Idx][3];
814    fillCoresetFeqDomAllocMap(((cellCb->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA - offset)/6), \
815                                   (numRbs/6), freqDomainResource);
816    covertFreqDomRsrcMapToIAPIFormat(freqDomainResource, \
817       cellCb->cellCfg.dlCfgCommon.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc);
818
819    /* Fill K0 - K1 table for common cfg*/ 
820    BuildK0K1Table(cellCb, &cellCb->k0K1InfoTbl, true, cellCb->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon,
821                    pdschCfg, DEFAULT_UL_ACK_LIST_COUNT, defaultUlAckTbl);
822    
823    BuildK2InfoTable(cellCb, cellCb->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.timeDomRsrcAllocList,\
824    cellCb->cellCfg.ulCfgCommon.schInitialUlBwp.puschCommon.numTimeDomRsrcAlloc, &cellCb->msg3K2InfoTbl, \
825    &cellCb->k2InfoTbl);
826    
827    /*As per Spec 38.211, Sec 6.3.3.2; RootSeq Len(Lra) where Lra=839 or Lra=139,
828     *depending on the PRACH preamble format as given by Tables 6.3.3.1-1 and 6.3.3.1-2.*/
829    if(prachCfgIdxTable[cellCb->cellCfg.ulCfgCommon.schInitialUlBwp.schRachCfg.prachCfgGeneric.prachCfgIdx][0] <= 3)
830    {
831       cellCb->cellCfg.ulCfgCommon.schInitialUlBwp.schRachCfg.rootSeqLen = ROOT_SEQ_LEN_1;
832    }
833    else
834    {
835       cellCb->cellCfg.ulCfgCommon.schInitialUlBwp.schRachCfg.rootSeqLen = ROOT_SEQ_LEN_2;
836    }
837    /* Initializing global variables */
838    cellCb->actvUeBitMap = 0;
839    cellCb->boIndBitMap = 0;
840
841    cellCb->schHqCfg.maxDlDataHqTx = SCH_MAX_NUM_DL_HQ_TX;
842    cellCb->schHqCfg.maxMsg4HqTx = SCH_MAX_NUM_MSG4_TX;
843    cellCb->schHqCfg.maxUlDataHqTx = SCH_MAX_NUM_UL_HQ_TX;
844    cellCb->maxMsg3Tx = SCH_MAX_NUM_MSG3_TX;
845
846    cellCb->schAlgoType = SCH_FCFS;
847    cellCb->api = &schCb[inst].allApis[cellCb->schAlgoType]; /* For FCFS */
848    cellCb->api->SchCellCfgReq(cellCb);
849    
850    /* Fill and send Cell config confirm */
851    memset(&rspPst, 0, sizeof(Pst));
852    FILL_PST_SCH_TO_MAC(rspPst, pst->dstInst);
853    rspPst.event = EVENT_SCH_CELL_CFG_CFM;
854
855    schCellCfgCfm.cellId = schCellCfg->cellId; 
856    schCellCfgCfm.rsp = RSP_OK;
857
858    ret = MacMessageRouter(&rspPst, (void *)&schCellCfgCfm);
859    return ret;
860
861 }
862
863 /*******************************************************************
864  *
865  * @brief Fill and send Cell delete response to MAC
866  *
867  * @details
868  *
869  *    Function :  SchSendCellDeleteRspToMac
870  *
871  *    Functionality: Fill and send Cell delete response to MAC
872  *
873  * @params[in] SchCellDelete  *ueDelete, Inst inst, SchMacRsp result
874  * @return ROK     - success
875  *         RFAILED - failure
876  *
877  * ****************************************************************/
878 uint8_t SchSendCellDeleteRspToMac(SchCellDeleteReq  *ueDelete, Inst inst, SchMacRsp result)
879 {
880    Pst rspPst;
881    uint8_t ret=0;
882    
883    SchCellDeleteRsp  delRsp;
884
885    DU_LOG("\nINFO   --> SCH : Filling Cell Delete response");
886    memset(&delRsp, 0, sizeof(SchCellDeleteRsp));
887    delRsp.cellId = ueDelete->cellId;
888    delRsp.rsp = result;
889
890    /* Filling response post */
891    memset(&rspPst, 0, sizeof(Pst));
892    FILL_PST_SCH_TO_MAC(rspPst, inst);
893    rspPst.event = EVENT_CELL_DELETE_RSP_TO_MAC;
894    ret = MacMessageRouter(&rspPst, (void *)&delRsp);
895    if(ret == RFAILED)
896    {
897       DU_LOG("\nERROR  -->  SCH : SchSendCellDeleteRspToMac(): failed to send the Cell Delete response");
898       return ret;
899    }
900    return ret;
901 }
902
903 /*******************************************************************
904  *
905  * @brief Function for cellCb Deletion 
906  *
907  * @details
908  *
909  *    Function : deleteSchCellCb 
910  *
911  *    Functionality: Function for cellCb Deletion 
912  *
913  * @params[in] SchCellDelete  *cellDelete
914  * @return ROK     - success
915  *         RFAILED - failure
916  *
917  * ****************************************************************/
918 void deleteSchCellCb(SchCellCb *cellCb)
919 {
920    uint8_t sliceIdx=0, slotIdx=0, plmnIdx = 0;
921    CmLListCp *list=NULL;
922    CmLList *node=NULL, *next=NULL;
923    SchPageInfo *tempNode = NULLP;
924
925    if(cellCb->schDlSlotInfo)
926    {
927       for(slotIdx=0; slotIdx<cellCb->numSlots; slotIdx++)
928       {
929          list = &cellCb->schDlSlotInfo[slotIdx]->prbAlloc.freePrbBlockList;
930          node = list->first;
931          while(node)
932          {
933             next = node->next;
934             SCH_FREE(node->node, sizeof(FreePrbBlock));
935             deleteNodeFromLList(list, node);
936             node = next;
937          }
938          SCH_FREE(cellCb->schDlSlotInfo[slotIdx], sizeof(SchDlSlotInfo));
939       }
940       SCH_FREE(cellCb->schDlSlotInfo, cellCb->numSlots *sizeof(SchDlSlotInfo*));
941    }
942
943    if(cellCb->schUlSlotInfo)
944    {
945       for(slotIdx=0; slotIdx<cellCb->numSlots; slotIdx++)
946       {
947          list = &cellCb->schUlSlotInfo[slotIdx]->prbAlloc.freePrbBlockList;
948          node = list->first;
949          while(node)
950          {
951             next = node->next;
952             SCH_FREE(node->node, sizeof(FreePrbBlock));
953             deleteNodeFromLList(list, node);
954             node = next;
955          }
956          SCH_FREE(cellCb->schUlSlotInfo[slotIdx], sizeof(SchUlSlotInfo));  
957       }
958       SCH_FREE(cellCb->schUlSlotInfo,  cellCb->numSlots * sizeof(SchUlSlotInfo*));
959    }
960
961    for(plmnIdx = 0; plmnIdx < MAX_PLMN; plmnIdx++)
962    {
963       if(cellCb->cellCfg.plmnInfoList[plmnIdx].snssai)
964       {
965          for(sliceIdx=0; sliceIdx<cellCb->cellCfg.plmnInfoList[plmnIdx].numSliceSupport; sliceIdx++)
966          {
967             SCH_FREE(cellCb->cellCfg.plmnInfoList[plmnIdx].snssai[sliceIdx], sizeof(Snssai));
968          }
969          SCH_FREE(cellCb->cellCfg.plmnInfoList[plmnIdx].snssai, cellCb->cellCfg.plmnInfoList[plmnIdx].numSliceSupport*sizeof(Snssai*));
970       }
971    }
972
973    for(uint16_t idx =0; idx<MAX_SFN; idx++)
974    {
975       list = &cellCb->pageCb.pageIndInfoRecord[idx];
976       node = list->first;
977       while(node)
978       {
979          next = node->next;
980          if(node->node)
981          {
982             tempNode = (SchPageInfo*)(node->node);
983             SCH_FREE(tempNode->pagePdu, tempNode->msgLen);
984             SCH_FREE(node->node,  sizeof(SchPageInfo));
985          }
986          deleteNodeFromLList(list, node);
987          node = next;
988       }
989    }
990
991    cellCb->api->SchCellDeleteReq(cellCb);
992
993    memset(cellCb, 0, sizeof(SchCellCb));
994 }
995
996 /*******************************************************************
997  *
998  * @brief Function for cell Delete request from MAC to SCH
999  *
1000  * @details
1001  *
1002  *    Function : SchProcCellDeleteReq
1003  *
1004  *    Functionality: Function for cell Delete request from MAC to SCH
1005  *
1006  * @params[in] Pst *pst, SchCellDelete  *cellDelete
1007  * @return ROK     - success
1008  *         RFAILED - failure
1009  *
1010  * ****************************************************************/
1011 uint8_t SchProcCellDeleteReq(Pst *pst, SchCellDeleteReq  *cellDelete)
1012 {
1013    uint8_t   cellIdx=0, ret = RFAILED;
1014    Inst      inst = pst->dstInst - SCH_INST_START;
1015    SchMacRsp result= RSP_OK;
1016    
1017    if(!cellDelete)
1018    {
1019       DU_LOG("\nERROR  -->  SCH : SchProcCellDeleteReq(): Ue Delete request failed");
1020    }
1021    else
1022    {
1023       GET_CELL_IDX(cellDelete->cellId, cellIdx);
1024       if(schCb[inst].cells[cellIdx] == NULLP)
1025       { 
1026          DU_LOG("\nERROR  -->  SCH : SchProcCellDeleteReq(): cell Id[%d] is not available", cellDelete->cellId);
1027          result = RSP_NOK;
1028       }
1029       else
1030       {
1031          if(schCb[inst].cells[cellIdx]->cellId == cellDelete->cellId)
1032          {
1033             deleteSchCellCb(schCb[inst].cells[cellIdx]);
1034             result = RSP_OK;
1035             ret = ROK;
1036             SCH_FREE(schCb[inst].cells[cellIdx], sizeof(SchCellCb));
1037             DU_LOG("\nINFO   -->  SCH : Sending Cell Delete response to MAC");
1038          }
1039          else
1040          {
1041             DU_LOG("\nERROR  -->  SCH : SchProcCellDeleteReq(): cell Id[%d] is not available",cellDelete->cellId);
1042             result = RSP_NOK;
1043          }
1044       }
1045
1046       if(SchSendCellDeleteRspToMac(cellDelete, inst, result)!=ROK)
1047       {
1048          DU_LOG("\nERROR  -->  SCH : SchProcCellDeleteReq(): failed to send Cell Delete response");
1049          ret =  RFAILED;
1050       }
1051    }
1052    return ret;   
1053 }
1054
1055 /*******************************************************************
1056  *
1057  * @brief Processes DL RLC BO info from MAC
1058  *
1059  * @details
1060  *
1061  *    Function : SchProcDlRlcBoInfo
1062  *
1063  *    Functionality:
1064  *       Processes DL RLC BO info from MAC
1065  *
1066  * @params[in] 
1067  * @return ROK     - success
1068  *         RFAILED - failure
1069  *
1070  * ****************************************************************/
1071 uint8_t SchProcDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
1072 {
1073    uint8_t  lcId = 0;
1074    uint16_t ueId = 0;
1075    bool isLcIdValid = false;
1076    SchUeCb *ueCb = NULLP;
1077    SchCellCb *cell = NULLP;
1078    Inst  inst = pst->dstInst-SCH_INST_START;   
1079
1080    DU_LOG("\nDEBUG  -->  SCH : Received RLC BO Status indication LCId [%d] BO [%d]", dlBoInfo->lcId, dlBoInfo->dataVolume);
1081    cell = schCb[inst].cells[inst];
1082
1083    if(cell == NULLP)
1084    {
1085       DU_LOG("\nERROR  -->  SCH : SchProcDlRlcBoInfo(): Cell does not exists");
1086       return RFAILED;
1087    }
1088
1089    GET_UE_ID(dlBoInfo->crnti, ueId);
1090    ueCb = &cell->ueCb[ueId-1];
1091    if(ueCb->ueCfg.dataTransmissionAction == STOP_DATA_TRANSMISSION)
1092    {
1093       DU_LOG("INFO  --> SCH : DL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId);
1094       return ROK;
1095    }
1096    
1097    lcId  = dlBoInfo->lcId;
1098    CHECK_LCID(lcId, isLcIdValid);
1099    if(isLcIdValid == FALSE)
1100    {
1101       DU_LOG("ERROR --> SCH: LCID:%d is not valid", lcId);
1102       return RFAILED;
1103    }
1104
1105    /*Expected when theres a case of Retransmission Failure or Resetablishment
1106     *By Zero BO, the RLC is informing that previous data can be cleared out
1107     *Thus clearing out the LC from the Lc priority list*/
1108    if(dlBoInfo->dataVolume == 0)
1109    {
1110       /* TODO : Check the LC is Dedicated or default and accordingly LCList
1111        * will be used*/
1112       return ROK;
1113    }
1114
1115    if(lcId == SRB0_LCID)
1116    {
1117       cell->raCb[ueId -1].msg4recvd = true;
1118       cell->raCb[ueId -1].dlMsgPduLen = dlBoInfo->dataVolume;      
1119    }
1120    else
1121    {
1122       /* TODO : These part of changes will be corrected during DL scheduling as
1123        * per K0 - K1 -K2 */
1124       SET_ONE_BIT(ueId, cell->boIndBitMap);
1125       if(ueCb->dlInfo.dlLcCtxt[lcId].lcId == lcId)
1126       {
1127          ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
1128       }
1129       else
1130       {
1131          DU_LOG("ERROR --> SCH: LCID:%d is not configured in SCH Cb",lcId);
1132          return RFAILED;
1133       }
1134    }
1135    /* Adding UE Id to list of pending UEs to be scheduled */
1136    cell->api->SchDlRlcBoInfo(cell, ueId);
1137    return ROK;
1138 }
1139
1140 /*******************************************************************
1141  *
1142  * @brief Processes BSR indiation from MAC
1143  *
1144  * @details
1145  *
1146  *    Function : SchProcBsr
1147  *
1148  *    Functionality:
1149  *       Processes DL BSR from MAC
1150  *
1151  * @params[in]    Pst pst
1152  *                UlBufferStatusRptInd bsrInd
1153  * @return ROK     - success
1154  *         RFAILED - failure
1155  *
1156  * ****************************************************************/
1157 uint8_t SchProcBsr(Pst *pst, UlBufferStatusRptInd *bsrInd)
1158 {
1159    Inst           schInst       = pst->dstInst-SCH_INST_START;
1160    SchCellCb      *cellCb       = NULLP;
1161    SchUeCb        *ueCb         = NULLP;
1162    uint8_t        lcgIdx = 0;
1163
1164    DU_LOG("\nDEBUG  -->  SCH : Received BSR");
1165    if(bsrInd == NULLP)
1166    {
1167       DU_LOG("\nERROR  -->  SCH : BSR Ind is empty");
1168       return RFAILED;
1169    }
1170    cellCb = schCb[schInst].cells[schInst];
1171    if(cellCb == NULLP)
1172    {
1173       DU_LOG("\nERROR  -->  SCH : CellCb is empty");
1174       return RFAILED;
1175    }
1176    ueCb = schGetUeCb(cellCb, bsrInd->crnti);
1177
1178    if(ueCb == NULLP)
1179    {
1180       DU_LOG("\nERROR  -->  SCH : UeCB is empty");
1181       return RFAILED;
1182    }
1183
1184    if(ueCb->ueCfg.dataTransmissionAction == STOP_DATA_TRANSMISSION)
1185    {
1186       DU_LOG("\nINFO --> SCH: UL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId);
1187       return ROK;
1188    }
1189    
1190    ueCb->bsrRcvd = true;
1191    /* store dataVolume per lcg in uecb */
1192    for(lcgIdx = 0; lcgIdx < bsrInd->numLcg; lcgIdx++)
1193    {
1194       ueCb->bsrInfo[bsrInd->dataVolInfo[lcgIdx].lcgId].priority = 1; //TODO: determining LCG priority?
1195       ueCb->bsrInfo[bsrInd->dataVolInfo[lcgIdx].lcgId].dataVol = bsrInd->dataVolInfo[lcgIdx].dataVol;
1196    }
1197    
1198    /* Adding UE Id to list of pending UEs to be scheduled */
1199    cellCb->api->SchBsr(cellCb, ueCb->ueId);
1200    return ROK;
1201 }
1202
1203 /*******************************************************************
1204  *
1205  * @brief Processes SR UCI indication from MAC 
1206  *
1207  * @details
1208  *
1209  *    Function : SchProcSrUciInd
1210  *
1211  *    Functionality:
1212  *      Processes SR UCI indication from MAC
1213  *
1214  * @params[in] Post structure
1215  *             UCI Indication
1216  * @return ROK     - success
1217  *         RFAILED - failure
1218  *
1219  * ****************************************************************/
1220 uint8_t SchProcSrUciInd(Pst *pst, SrUciIndInfo *uciInd)
1221 {
1222    Inst  inst = pst->dstInst-SCH_INST_START;
1223
1224    SchUeCb   *ueCb; 
1225    SchCellCb *cellCb = schCb[inst].cells[inst];
1226
1227    DU_LOG("\nDEBUG  -->  SCH : Received SR");
1228
1229    ueCb = schGetUeCb(cellCb, uciInd->crnti);
1230    
1231    if(ueCb->state == SCH_UE_STATE_INACTIVE)
1232    {
1233       DU_LOG("\nERROR  -->  SCH : Crnti %d is inactive", uciInd->crnti);
1234       return ROK;  
1235    }
1236    if(ueCb->ueCfg.dataTransmissionAction == STOP_DATA_TRANSMISSION)
1237    {
1238       DU_LOG("\nINFO --> SCH: UL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId);
1239       return ROK;
1240    }
1241    if(uciInd->numSrBits)
1242    {
1243       ueCb->srRcvd = true;      
1244       /* Adding UE Id to list of pending UEs to be scheduled */
1245       cellCb->api->SchSrUciInd(cellCb, ueCb->ueId);
1246    }
1247    return ROK;
1248 }
1249
1250 /*******************************************************************
1251  *
1252  * @brief Processes DL HARQ indication from MAC 
1253  *
1254  * @details
1255  *
1256  *    Function : SchProcDlHarqInd
1257  *
1258  *    Functionality:
1259  *      Processes DL HARQ indication from MAC
1260  *
1261  * @params[in] Post structure
1262  *             DL HARQ Indication
1263  * @return ROK     - success
1264  *         RFAILED - failure
1265  *
1266  * ****************************************************************/
1267 uint8_t SchProcDlHarqInd(Pst *pst, DlHarqInd *dlHarqInd)
1268 {
1269    Inst  inst = pst->dstInst-SCH_INST_START;
1270    SchUeCb   *ueCb;
1271    SchCellCb *cellCb = schCb[inst].cells[inst];
1272
1273    DU_LOG("\nDEBUG  -->  SCH : Received HARQ");
1274
1275    ueCb = schGetUeCb(cellCb, dlHarqInd->crnti);
1276
1277    if(ueCb->state == SCH_UE_STATE_INACTIVE)
1278    {
1279       DU_LOG("\nERROR  -->  SCH : Crnti %d is inactive", dlHarqInd->crnti);
1280       return ROK;
1281    }
1282
1283    schUpdateHarqFdbk(ueCb, dlHarqInd->numHarq, dlHarqInd->harqPayload, &dlHarqInd->slotInd);
1284
1285    return ROK;
1286 }
1287
1288 /*******************************************************************
1289  *
1290  * @brief Allocates requested PRBs for DL
1291  *
1292  * @details
1293  *
1294  *    Function : allocatePrbDl
1295  *
1296  *    Functionality:
1297  *      Allocates requested PRBs in DL
1298  *      Keeps track of allocated PRB (using bitmap) and remaining PRBs
1299  *
1300  * @params[in] prbAlloc table
1301  *             Start symbol
1302  *             Number of symbols
1303  *             Start PRB
1304  *             Number of PRBs
1305  *
1306  * @return ROK     - success
1307  *         RFAILED - failure
1308  *
1309  * ****************************************************************/
1310 uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \
1311    uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
1312 {
1313    uint8_t        symbol = 0;
1314    uint16_t       broadcastPrbStart=0, broadcastPrbEnd=0;
1315    FreePrbBlock   *freePrbBlock = NULLP;
1316    CmLList        *freePrbNode = NULLP;
1317    PduTxOccsaion  ssbOccasion=0, sib1Occasion=0;
1318    SchDlSlotInfo  *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
1319    SchPrbAlloc    *prbAlloc = &schDlSlotInfo->prbAlloc;
1320
1321    /* If startPrb is set to MAX_NUM_RB, it means startPrb is not known currently.
1322     * Search for an appropriate location in PRB grid and allocate requested resources */
1323    if(*startPrb == MAX_NUM_RB)
1324    {
1325       /* Check if SSB/SIB1 is also scheduled in this slot  */
1326       ssbOccasion = schCheckSsbOcc(cell, slotTime);
1327       sib1Occasion = schCheckSib1Occ(cell, slotTime);
1328
1329       if(ssbOccasion && sib1Occasion)
1330       {
1331          broadcastPrbStart = cell->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA; 
1332          broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1;
1333       }
1334       else if(ssbOccasion)
1335       {
1336          broadcastPrbStart = cell->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA;
1337          broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB -1;
1338       }
1339       else if(sib1Occasion)
1340       {
1341          broadcastPrbStart = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.startPrb;
1342          broadcastPrbEnd = broadcastPrbStart + cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1;
1343       }
1344
1345       /* Iterate through all free PRB blocks */
1346       freePrbNode = prbAlloc->freePrbBlockList.first; 
1347       while(freePrbNode)
1348       {
1349          freePrbBlock = (FreePrbBlock *)freePrbNode->node; 
1350
1351          /* If broadcast message is scheduled in this slot, then check if its PRBs belong to the current free block.
1352           * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
1353          if((ssbOccasion || sib1Occasion) && 
1354             ((broadcastPrbStart >= freePrbBlock->startPrb) && (broadcastPrbStart <= freePrbBlock->endPrb)) && \
1355             ((broadcastPrbEnd >= freePrbBlock->startPrb) && (broadcastPrbEnd <= freePrbBlock->endPrb)))
1356          {
1357             /* Implmentation is done such that highest-numbered free-RB is allocated first */ 
1358             if((freePrbBlock->endPrb > broadcastPrbEnd) && ((freePrbBlock->endPrb - broadcastPrbEnd) >= numPrb))
1359             {
1360                /* If sufficient free PRBs are available above bradcast message then,
1361                 * endPrb = freePrbBlock->endPrb
1362                 * startPrb = endPrb - numPrb +1;
1363                 */
1364                *startPrb = freePrbBlock->endPrb - numPrb +1;
1365                break;
1366             }
1367             else if((broadcastPrbStart > freePrbBlock->startPrb) && ((broadcastPrbStart - freePrbBlock->startPrb) >= numPrb))
1368             {
1369                /* If free PRBs are available below broadcast message then,
1370                 * endPrb = broadcastPrbStart - 1
1371                 * startPrb = endPrb - numPrb +1
1372                 */
1373                *startPrb = broadcastPrbStart - numPrb; 
1374                break;
1375             }
1376             else
1377             {
1378                freePrbNode = freePrbNode->next;
1379                continue;
1380             }
1381          }
1382          else
1383          {
1384             /* Check if requested number of blocks can be allocated from the current block */ 
1385             if (freePrbBlock->numFreePrb < numPrb)
1386             {
1387                freePrbNode = freePrbNode->next;
1388                continue;
1389             }
1390             *startPrb = freePrbBlock->endPrb - numPrb +1;
1391             break;  
1392          }
1393       }
1394
1395       /* If no free block can be used to allocated request number of RBs */
1396       if(*startPrb == MAX_NUM_RB)
1397          return RFAILED;
1398    }
1399
1400    /* If startPrb is known already, check if requested PRBs are available for allocation */
1401    else
1402    {
1403       freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
1404       if(!freePrbNode)
1405       {
1406          DU_LOG("\nERROR  -->  SCH: Requested DL PRB unavailable");
1407          return RFAILED;
1408       }
1409    }
1410
1411    /* Update bitmap to allocate PRBs */
1412    for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
1413    {
1414       if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
1415       {
1416          DU_LOG("\nERROR  -->  SCH: fillPrbBitmap() failed for symbol [%d] in DL", symbol);
1417          return RFAILED;
1418       }
1419    }
1420
1421    /* Update the remaining number for free PRBs */
1422    removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
1423
1424    return ROK;
1425 }
1426
1427 /*******************************************************************
1428  *
1429  * @brief Allocates requested PRBs for UL
1430  *
1431  * @details
1432  *
1433  *    Function : allocatePrbUl
1434  *
1435  *    Functionality:
1436  *      Allocates requested PRBs in UL
1437  *      Keeps track of allocated PRB (using bitmap) and remaining PRBs
1438  *
1439  * @params[in] prbAlloc table
1440  *             Start symbol
1441  *             Number of symbols
1442  *             Start PRB
1443  *             Number of PRBs
1444  *
1445  * @return ROK     - success
1446  *         RFAILED - failure
1447  *
1448  * ****************************************************************/
1449 uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \
1450    uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
1451 {
1452    uint8_t        symbol = 0;
1453    uint16_t       prachStartPrb, prachNumPrb, prachEndPrb;
1454    bool           isPrachOccasion;
1455    FreePrbBlock   *freePrbBlock = NULLP;
1456    CmLList        *freePrbNode = NULLP;
1457    SchPrbAlloc    *prbAlloc = NULLP;
1458
1459    if(cell == NULLP)
1460    {
1461       DU_LOG("\nERROR  --> SCH : allocatePrbUl(): Received cellCb is null");
1462       return RFAILED;
1463    }
1464    
1465    prbAlloc =   &cell->schUlSlotInfo[slotTime.slot]->prbAlloc;
1466    /* If startPrb is set to MAX_NUM_RB, it means startPrb is not known currently.
1467     * Search for an appropriate location in PRB grid and allocate requested resources */
1468    if(*startPrb == MAX_NUM_RB)
1469    {
1470       /* Check if PRACH is also scheduled in this slot */
1471       isPrachOccasion = schCheckPrachOcc(cell, slotTime);
1472       if(isPrachOccasion)
1473       {
1474          prachStartPrb =  cell->cellCfg.ulCfgCommon.schInitialUlBwp.schRachCfg.prachCfgGeneric.msg1FreqStart;
1475          prachNumPrb = schCalcPrachNumRb(cell);
1476          prachEndPrb = prachStartPrb + prachNumPrb -1;
1477       }
1478
1479       /* Iterate through all free PRB blocks */
1480       freePrbNode = prbAlloc->freePrbBlockList.first; 
1481       while(freePrbNode)
1482       {
1483          freePrbBlock = (FreePrbBlock *)freePrbNode->node; 
1484
1485          /* If PRACH is scheduled in this slot, then check if its PRBs belong to the current free block.
1486           * PRBs required for PRACH cannot be allocated to any other message */
1487          if((isPrachOccasion) &&
1488             ((prachStartPrb >= freePrbBlock->startPrb) && (prachStartPrb <= freePrbBlock->endPrb)) &&
1489             ((prachEndPrb >= freePrbBlock->startPrb) && (prachEndPrb <= freePrbBlock->endPrb)))
1490          {
1491             /* Implmentation is done such that highest-numbered free-RB is allocated first */ 
1492             if((freePrbBlock->endPrb > prachEndPrb) && ((freePrbBlock->endPrb - prachEndPrb) >= numPrb))
1493             {
1494                /* If sufficient free PRBs are available above PRACH message then,
1495                 * endPrb = freePrbBlock->endPrb
1496                 * startPrb = endPrb - numPrb +1;
1497                 */
1498                *startPrb = freePrbBlock->endPrb - numPrb +1;
1499                break;
1500             }
1501             else if((prachStartPrb > freePrbBlock->startPrb) && ((prachStartPrb - freePrbBlock->startPrb) >= numPrb))
1502             {
1503                /* If free PRBs are available below PRACH message then,
1504                 * endPrb = prachStartPrb - 1
1505                 * startPrb = endPrb - numPrb +1
1506                 */
1507                *startPrb = prachStartPrb - numPrb; 
1508                break;
1509             }
1510             else
1511             {
1512                freePrbNode = freePrbNode->next;
1513                continue;
1514             } 
1515          }
1516          else
1517          {
1518             /* Check if requested number of PRBs can be allocated from currect block */
1519             if(freePrbBlock->numFreePrb < numPrb)
1520             {
1521                freePrbNode = freePrbNode->next;
1522                continue;
1523             }
1524             *startPrb = freePrbBlock->endPrb - numPrb +1;
1525             break;
1526          }
1527       }
1528
1529       /* If no free block can be used to allocated requested number of RBs */
1530       if(*startPrb == MAX_NUM_RB)
1531          return RFAILED;
1532    }
1533    else
1534    {
1535       /* If startPrb is known already, check if requested PRBs are available for allocation */
1536       freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
1537       if(!freePrbNode)
1538       {
1539          DU_LOG("\nERROR  -->  SCH: Requested UL PRB unavailable");
1540          return RFAILED;
1541       }
1542    }
1543
1544    /* Update bitmap to allocate PRBs */
1545    for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
1546    {
1547       if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
1548       {
1549          DU_LOG("\nERROR  -->  SCH: fillPrbBitmap() failed for symbol [%d] in UL", symbol);
1550          return RFAILED;
1551       }
1552    }
1553
1554    /* Update the remaining number for free PRBs */
1555    removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
1556
1557    return ROK;
1558 }
1559
1560 /*******************************************************************************
1561  *
1562  * @brief Try to find Best Free Block with Max Num PRB 
1563  *
1564  * @details
1565  *
1566  *    Function : searchLargestFreeBlock
1567  *
1568  *    Functionality:
1569  *     Finds the FreeBlock with MaxNum of FREE PRB considering SSB/SIB1 ocassions.
1570  *
1571  * @params[in] I/P > prbAlloc table (FreeBlock list)
1572  *             I/P > Slot timing Info
1573  *             O/P > Start PRB
1574  *             I/P > Direction (UL/DL)
1575  *       
1576  *
1577  * @return Max Number of Free PRB 
1578  *         If 0, then no Suitable Free Block
1579  *
1580  * ********************************************************************************/
1581
1582 uint16_t searchLargestFreeBlock(SchCellCb *cell, SlotTimingInfo slotTime,uint16_t *startPrb, Direction dir)
1583 {
1584    uint16_t       reservedPrbStart=0, reservedPrbEnd=0, maxFreePRB = 0;
1585    FreePrbBlock   *freePrbBlock = NULLP;
1586    CmLList        *freePrbNode = NULLP;
1587    SchPrbAlloc    *prbAlloc = NULLP;
1588    bool           checkOccasion = FALSE;
1589
1590    *startPrb = 0; /*Initialize the StartPRB to zero*/
1591
1592    /*Based on Direction, Reserved Messsages will differi.e.
1593     * DL >> SSB and SIB1 ocassions wheres for UL, PRACH ocassions to be checked
1594     * and reserved before allocation for dedicated DL/UL msg*/
1595    if(dir == DIR_DL)
1596    {
1597       SchDlSlotInfo  *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
1598       PduTxOccsaion  ssbOccasion=0, sib1Occasion=0;
1599
1600       prbAlloc = &schDlSlotInfo->prbAlloc;
1601
1602       ssbOccasion = schCheckSsbOcc(cell, slotTime);
1603       sib1Occasion = schCheckSib1Occ(cell, slotTime);
1604
1605       checkOccasion = TRUE;
1606       if(ssbOccasion && sib1Occasion)
1607       {
1608          reservedPrbStart = cell->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA; 
1609          reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB + \
1610                           cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1;
1611       }
1612       else if(ssbOccasion)
1613       {
1614          reservedPrbStart = cell->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA;
1615          reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB -1;
1616       }
1617       else if(sib1Occasion)
1618       {
1619          reservedPrbStart = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.startPrb;
1620          reservedPrbEnd = reservedPrbStart + cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1;
1621       }
1622       else
1623       {
1624          checkOccasion = FALSE;  
1625       }
1626    }
1627    else if(dir == DIR_UL)
1628    {
1629       prbAlloc = &cell->schUlSlotInfo[slotTime.slot]->prbAlloc;
1630
1631       /* Check if PRACH is also scheduled in this slot */
1632       checkOccasion = schCheckPrachOcc(cell, slotTime);
1633       if(checkOccasion)
1634       {
1635          reservedPrbStart =  cell->cellCfg.ulCfgCommon.schInitialUlBwp.schRachCfg.prachCfgGeneric.msg1FreqStart;
1636          reservedPrbEnd = reservedPrbStart + (schCalcPrachNumRb(cell)) -1;
1637       }
1638    }
1639    else
1640    {
1641       DU_LOG("\nERROR --> SCH: Invalid Direction!");
1642       return (maxFreePRB);
1643    }
1644
1645    freePrbNode = prbAlloc->freePrbBlockList.first; 
1646    while(freePrbNode)
1647    {
1648       freePrbBlock = (FreePrbBlock *)freePrbNode->node;
1649
1650       /*For block with same numFreeBlocks, choose the one with HighestPRB range
1651        *Since FreeBLockList are arranged in Descending order of PRB range thus Skipping this block*/
1652       if(maxFreePRB >= freePrbBlock->numFreePrb) 
1653       {
1654          //skip this block
1655          freePrbNode = freePrbNode->next;
1656          continue;
1657       }
1658
1659       /* If Broadcast/Prach message is scheduled in this slot, then check if its PRBs belong to the current free block.
1660        * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
1661       if(checkOccasion && 
1662             ((reservedPrbStart >= freePrbBlock->startPrb) && (reservedPrbStart <= freePrbBlock->endPrb)) && \
1663             ((reservedPrbEnd >= freePrbBlock->startPrb) && (reservedPrbEnd <= freePrbBlock->endPrb)))
1664       {
1665
1666          /* Implmentation is done such that highest-numbered free-RB is Checked first
1667             and freePRB in this block is greater than Max till now */
1668          if((freePrbBlock->endPrb > reservedPrbEnd) && ((freePrbBlock->endPrb - reservedPrbEnd) > maxFreePRB))
1669          {
1670             /* If sufficient free PRBs are available above reserved message*/
1671             *startPrb = reservedPrbEnd + 1;
1672             maxFreePRB = (freePrbBlock->endPrb - reservedPrbEnd);                
1673          }
1674          /*Also check the other freeBlock (i.e. Above the reserved message) for MAX FREE PRB*/
1675          if((reservedPrbStart > freePrbBlock->startPrb) && ((reservedPrbStart - freePrbBlock->startPrb) > maxFreePRB))
1676          {
1677             /* If free PRBs are available below reserved message*/
1678             *startPrb = freePrbBlock->startPrb;
1679             maxFreePRB = (reservedPrbStart - freePrbBlock->startPrb);
1680          }
1681       }
1682       else  //Best Block
1683       {
1684          if(maxFreePRB < freePrbBlock->numFreePrb)
1685          {
1686             *startPrb = freePrbBlock->startPrb;
1687             maxFreePRB = freePrbBlock->numFreePrb;
1688          }
1689
1690       }
1691       freePrbNode = freePrbNode->next;
1692    }  
1693    return(maxFreePRB);
1694 }
1695
1696 /*******************************************************************************
1697  *
1698  * @brief This function is used to send Slice Cfg rsp to MAC
1699  *
1700  * @details
1701  *
1702  *    Function : SchSendSliceCfgRspToMac
1703  *
1704  *    Functionality:
1705  *     function is used to send Slice Cfg rsp to MAC
1706  *
1707  * @params[in] Pst *pst, SchSliceCfgRsp sliceCfgRsp
1708  *
1709  * @return- void
1710  *
1711  * ********************************************************************************/
1712 void SchSendSliceCfgRspToMac(Inst inst, SchSliceCfgRsp sliceCfgRsp)
1713 {
1714    Pst rspPst;
1715    
1716    memset(&rspPst, 0, sizeof(Pst));
1717    FILL_PST_SCH_TO_MAC(rspPst, inst);
1718    rspPst.event = EVENT_SLICE_CFG_RSP_TO_MAC;
1719    
1720    MacMessageRouter(&rspPst, (void *)&sliceCfgRsp);
1721
1722 }
1723
1724 /*******************************************************************************
1725  *
1726  * @brief This function is used to store or modify the slice configuration Sch DB
1727  *
1728  * @details
1729  *
1730  *    Function : addOrModifySliceCfgInSchDb 
1731  *
1732  *    Functionality:
1733  *     function is used to store or modify the slice configuration Sch DB
1734  *
1735  * @params[in] SchSliceCfg *storeSliceCfg, SchSliceCfgReq *cfgReq,
1736  * SchSliceCfgRsp cfgRsp, uint8_t count
1737  *
1738  * @return
1739  *        ROK - Success
1740  *        RFAILED - Failure
1741  *
1742  * ********************************************************************************/
1743 uint8_t addSliceCfgInSchDb(CmLListCp *sliceCfgInDb, SchRrmPolicyOfSlice *cfgReq)
1744 {
1745    SchRrmPolicyOfSlice *sliceToStore;
1746
1747    SCH_ALLOC(sliceToStore, sizeof(SchRrmPolicyOfSlice));
1748    if(sliceToStore)
1749    {
1750       memcpy(&sliceToStore->snssai, &cfgReq->snssai, sizeof(Snssai));  
1751       memcpy(&sliceToStore->rrmPolicyRatioInfo, &cfgReq->rrmPolicyRatioInfo, sizeof(SchRrmPolicyRatio));  
1752       addNodeToLList(sliceCfgInDb, sliceToStore, NULL);
1753    }
1754    else
1755    {
1756       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in addOrModifySliceCfgInSchDb");
1757       return RFAILED;
1758    }
1759    return ROK;
1760 }
1761
1762 /*******************************************************************************
1763  *
1764  * @brief fill slice configuration response
1765  *
1766  * @details
1767  *
1768  *    Function : fillSliceCfgRsp
1769  *
1770  *    Functionality:
1771  *     fill slice configuration response
1772  *
1773  * @params[in] SchCellCb, SchSliceCfgReq, SchSliceCfgRsp,uint8_t  count
1774  *
1775  * @return
1776  *        ROK - Success
1777  *        RFAILED - Failure
1778  *
1779  * ********************************************************************************/
1780 uint8_t fillSliceCfgRsp(Inst inst, CmLListCp *storedSliceCfg, SchCellCb *cellCb, SchSliceCfgReq *schSliceCfgReq)
1781 {
1782    SchMacRsp sliceFound;
1783    uint8_t cfgIdx = 0, sliceIdx = 0, plmnIdx = 0, ret =ROK;
1784    SchSliceCfgRsp schSliceCfgRsp;
1785
1786    for(cfgIdx = 0; cfgIdx<schSliceCfgReq->numOfConfiguredSlice; cfgIdx++)
1787    {
1788       sliceFound = RSP_NOK;
1789       /* Here comparing the slice cfg request with the slice stored in cellCfg */
1790       for(plmnIdx = 0; plmnIdx < MAX_PLMN; plmnIdx++)
1791       {
1792          for(sliceIdx = 0; sliceIdx<cellCb->cellCfg.plmnInfoList[plmnIdx].numSliceSupport; sliceIdx++)
1793          {
1794             /* If we find the SliceCfgReq's SNSSAI in CellCb's SNSSAI DB, we mark this slice as configured and add it to Sch's DB. */ 
1795             if(!memcmp(&schSliceCfgReq->listOfSlices[cfgIdx]->snssai, cellCb->cellCfg.plmnInfoList[plmnIdx].snssai[sliceIdx], sizeof(Snssai)))
1796             {
1797                if(addSliceCfgInSchDb(storedSliceCfg, schSliceCfgReq->listOfSlices[cfgIdx]) == ROK)
1798                {
1799                   sliceFound = RSP_OK;
1800                   schSliceCfgRsp.cause = SUCCESSFUL;
1801                }
1802                else
1803                {
1804                   DU_LOG("\nERROR  --> SCH : Failed to store slice configuration in SchDb");
1805                   schSliceCfgRsp.cause = RESOURCE_UNAVAILABLE;
1806                   ret = RFAILED;
1807                }
1808                plmnIdx = MAX_PLMN;
1809                break;
1810             }
1811          }
1812       }
1813       
1814       if((sliceFound == RSP_NOK) && (schSliceCfgRsp.cause != RESOURCE_UNAVAILABLE))
1815          schSliceCfgRsp.cause = SLICE_NOT_FOUND;
1816       
1817       schSliceCfgRsp.snssai = schSliceCfgReq->listOfSlices[cfgIdx]->snssai;
1818       schSliceCfgRsp.rsp    = sliceFound;
1819       SchSendSliceCfgRspToMac(inst, schSliceCfgRsp);
1820    }
1821    return ret;
1822 }
1823
1824 /*******************************************************************************
1825  *
1826  * @brief This function is used to free the slice cfg and re cfg request pointer
1827  *
1828  * @details
1829  *
1830  *    Function : freeSchSliceCfgReq 
1831  *
1832  *    Functionality:
1833  *     function is used to free the slice cfg and re cfg request pointer
1834  *
1835  * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1836  *
1837  * @return
1838  *        ROK - Success
1839  *        RFAILED - Failure
1840  * ********************************************************************************/
1841 void freeSchSliceCfgReq(SchSliceCfgReq *sliceCfgReq)
1842 {
1843    uint8_t cfgIdx = 0;
1844    
1845    if(sliceCfgReq)
1846    {
1847       if(sliceCfgReq->numOfConfiguredSlice)
1848       {
1849          for(cfgIdx = 0; cfgIdx<sliceCfgReq->numOfConfiguredSlice; cfgIdx++)
1850          {
1851             if(sliceCfgReq->listOfSlices[cfgIdx])
1852             {
1853                SCH_FREE(sliceCfgReq->listOfSlices[cfgIdx], sizeof(SchRrmPolicyOfSlice));
1854             }
1855          }
1856          SCH_FREE(sliceCfgReq->listOfSlices, sliceCfgReq->numOfConfiguredSlice * sizeof(SchRrmPolicyOfSlice*));
1857       }
1858       SCH_FREE(sliceCfgReq, sizeof(SchSliceCfgReq));
1859    }
1860 }
1861 /*******************************************************************************
1862  *
1863  * @brief This function is used to store the slice configuration Sch DB
1864  *
1865  * @details
1866  *
1867  *    Function : SchProcSliceCfgReq 
1868  *
1869  *    Functionality:
1870  *     function is used to store the slice configuration Sch DB
1871  *
1872  * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1873  *
1874  * @return
1875  *        ROK - Success
1876  *        RFAILED - Failure
1877  *
1878  * ********************************************************************************/
1879 uint8_t SchProcSliceCfgReq(Pst *pst, SchSliceCfgReq *schSliceCfgReq)
1880 {
1881    uint8_t ret = ROK;
1882    Inst   inst = pst->dstInst - SCH_INST_START;
1883
1884    DU_LOG("\nINFO  -->  SCH : Received Slice Cfg request from MAC");
1885    if(schSliceCfgReq)
1886    {
1887       if(schSliceCfgReq->listOfSlices)
1888       {
1889          /* filling the slice configuration response of each slice */
1890          if(fillSliceCfgRsp(inst, &schCb[inst].sliceCfg, schCb[inst].cells[0], schSliceCfgReq) != ROK)
1891          {
1892             DU_LOG("\nERROR  -->  SCH : Failed to fill the slice cfg rsp");
1893             ret = RFAILED;
1894          }
1895          freeSchSliceCfgReq(schSliceCfgReq);
1896       }
1897    }
1898    else
1899    {
1900       DU_LOG("\nERROR  -->  SCH : Received SchSliceCfgReq is NULL");
1901       ret = RFAILED;
1902    }
1903    return ret;
1904 }
1905
1906 /*******************************************************************************
1907  *
1908  * @brief This function is used to send Slice re Cfg rsp to MAC
1909  *
1910  * @details
1911  *
1912  *    Function : SchSendSliceRecfgRspToMac
1913  *
1914  *    Functionality:
1915  *     function is used to send Slice re Cfg rsp to MAC
1916  *
1917  * @params[in] Pst *pst, SchSliceRecfgRsp schSliceRecfgRsp
1918  *
1919  * @return- void
1920  *
1921  * ********************************************************************************/
1922 void SchSendSliceRecfgRspToMac(Inst inst, SchSliceRecfgRsp schSliceRecfgRsp)
1923 {
1924    Pst rspPst;
1925    
1926    memset(&rspPst, 0, sizeof(Pst));
1927    FILL_PST_SCH_TO_MAC(rspPst, inst);
1928    rspPst.event = EVENT_SLICE_RECFG_RSP_TO_MAC;
1929    
1930    MacMessageRouter(&rspPst, (void *)&schSliceRecfgRsp);
1931 }
1932
1933 /*******************************************************************************
1934  *
1935  * @brief fill slice configuration response
1936  *
1937  * @details
1938  *
1939  *    Function : fillSliceRecfgRsp
1940  *
1941  *    Functionality: fill slice reconfiguration response
1942  *
1943  * @params[in] SchCellCb, SchSliceCfgReq, SchSliceCfgRsp,uint8_t  count
1944  *
1945  * @return
1946  *        ROK - Success
1947  *        RFAILED - Failure
1948  *
1949  * ********************************************************************************/
1950
1951 uint8_t fillSliceRecfgRsp(Inst inst, CmLListCp *storedSliceCfg, SchSliceRecfgReq *schSliceRecfgReq)
1952 {
1953    SchMacRsp sliceFound;
1954    uint8_t cfgIdx = 0;
1955    SchRrmPolicyOfSlice *rrmPolicyOfSlices;
1956    SchSliceRecfgRsp schSliceRecfgRsp;
1957
1958    for(cfgIdx = 0; cfgIdx<schSliceRecfgReq->numOfConfiguredSlice; cfgIdx++)
1959    {
1960       sliceFound = RSP_NOK;
1961       /* Here comparing the slice recfg request with the StoredSliceCfg */
1962       CmLList *sliceCfg = storedSliceCfg->first;
1963
1964       while(sliceCfg)
1965       {
1966          rrmPolicyOfSlices = (SchRrmPolicyOfSlice*)sliceCfg->node;
1967          
1968          if(rrmPolicyOfSlices && (memcmp(&schSliceRecfgReq->listOfSlices[cfgIdx]->snssai, &(rrmPolicyOfSlices->snssai), sizeof(Snssai)) == 0))
1969          {
1970             memcpy(&rrmPolicyOfSlices->rrmPolicyRatioInfo, &schSliceRecfgReq->listOfSlices[cfgIdx]->rrmPolicyRatioInfo, sizeof(SchRrmPolicyRatio));
1971             sliceFound = RSP_OK;
1972             break;
1973          }
1974          sliceCfg = sliceCfg->next;
1975       }
1976
1977       schSliceRecfgRsp.snssai = schSliceRecfgReq->listOfSlices[cfgIdx]->snssai;
1978       schSliceRecfgRsp.rsp    = sliceFound;
1979       if(schSliceRecfgRsp.rsp == RSP_OK)
1980          schSliceRecfgRsp.cause = SUCCESSFUL;
1981       else
1982          schSliceRecfgRsp.cause = SLICE_NOT_FOUND;
1983       SchSendSliceRecfgRspToMac(inst, schSliceRecfgRsp);
1984    }
1985    return ROK;
1986 }
1987 /*******************************************************************************
1988  *
1989  * @brief This function is used to store the slice reconfiguration Sch DB
1990  *
1991  * @details
1992  *
1993  *    Function : SchProcSliceRecfgReq 
1994  *
1995  *    Functionality:
1996  *     function is used to store the slice re configuration Sch DB
1997  *
1998  * @params[in] Pst *pst, SchSliceRecfgReq *schSliceRecfgReq
1999  *
2000  * @return
2001  *        ROK - Success
2002  *        RFAILED - Failure
2003  *
2004  * ********************************************************************************/
2005 uint8_t SchProcSliceRecfgReq(Pst *pst, SchSliceRecfgReq *schSliceRecfgReq)
2006 {
2007    uint8_t ret = ROK;
2008    Inst   inst = pst->dstInst - SCH_INST_START;
2009
2010    DU_LOG("\nINFO  -->  SCH : Received Slice ReCfg request from MAC");
2011    if(schSliceRecfgReq)
2012    {
2013       if(schSliceRecfgReq->listOfSlices)
2014       {
2015          /* filling the slice configuration response of each slice */
2016          if(fillSliceRecfgRsp(inst, &schCb[inst].sliceCfg, schSliceRecfgReq) != ROK)
2017          {
2018             DU_LOG("\nERROR  -->  SCH : Failed to fill sch slice cfg response");
2019             ret = RFAILED;
2020          }
2021          freeSchSliceCfgReq(schSliceRecfgReq);
2022       }
2023    }
2024    else
2025    {
2026       DU_LOG("\nERROR  -->  SCH : Received SchSliceRecfgReq is NULL");
2027
2028    }
2029    return ret;
2030 }
2031
2032 /****************************************************************************
2033  *
2034  * @brief Stores the Paging Configuration from DU APP in CellCb 
2035  *
2036  * @details
2037  *
2038  *    Function : schProcPagingParam
2039  *
2040  *    Functionality:
2041  *          Process the Paging Configuration when FirstPDCCHMonitoring for
2042  *          Paging Ocassion is not present.
2043  *
2044  *          As per 38.304 Sec 7.1,
2045  *          "When firstPDCCH-MonitoringOccasionOfPO is present, the
2046  *          starting PDCCH monitoring occasion number of (i_s + 1)th PO is the
2047  *          (i_s + 1)th value of the firstPDCCHMonitoringOccasionOfPO
2048  *          parameter; otherwise, it is equal to i_s * S."
2049  *          "S = number of actual transmitted SSBs determined according 
2050  *              to ssb-PositionsInBurst in SIB1"
2051  *
2052  * @params[in] SchCellCb *cell 
2053  *       
2054  * @return void 
2055  *        
2056  *************************************************************************/
2057 void schProcPagingCfg(SchCellCb *cell)
2058 {
2059    SchPcchCfg *pageCfgRcvd = NULL;
2060    uint8_t i_sIdx = 0;
2061
2062    pageCfgRcvd = &(cell->cellCfg.dlCfgCommon.schPcchCfg);
2063
2064    if(pageCfgRcvd->poPresent == TRUE)
2065    {
2066       /*Fetching first Pdcch Monitoring Occasion for SFN (i_s + 1)th*/
2067       for(i_sIdx = 0; i_sIdx < pageCfgRcvd->numPO; i_sIdx++)
2068       {
2069          cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pageCfgRcvd->pagingOcc[i_sIdx] / MAX_SYMB_PER_SLOT ;
2070          if ((pageCfgRcvd->pagingOcc[i_sIdx] % MAX_SYMB_PER_SLOT) != 0 )
2071          {
2072             cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot++;
2073          }
2074
2075          cell->pageCb.pagMonOcc[i_sIdx].frameOffset = 0;
2076
2077       }
2078    }
2079    else
2080    {
2081       schCfgPdcchMonOccOfPO(cell);                  
2082    }
2083 }
2084
2085 /****************************************************************************
2086  *
2087  * @brief Calculate PO if not present in Configuration 
2088  *
2089  * @details
2090  *
2091  *    Function : schCfgPdcchMonOccOfPO
2092  *
2093  *    Functionality: In this function, PO are calculated i_s * S because
2094  *    FirstPDCCHMonitoring_ForPO is not present.
2095  *
2096  * @params[in] SchCellCb *cellCb
2097  *       
2098  * @return void 
2099  *        
2100  *************************************************************************/
2101 void schCfgPdcchMonOccOfPO(SchCellCb *cell)
2102 {
2103    uint8_t         cnt = 0, incr = 1, i_sIdx = 0, frameOffSet = 0;
2104    uint8_t         nsValue = cell->cellCfg.dlCfgCommon.schPcchCfg.numPO;
2105    uint8_t         totalNumSsb = countSetBits(cell->cellCfg.ssbPosInBurst[0]);
2106    SlotTimingInfo  tmpTimingInfo, pdcchTime; 
2107
2108    /*Starting with First Sfn and slot*/
2109    tmpTimingInfo.sfn = 0;
2110    tmpTimingInfo.slot = 0;
2111
2112    pdcchTime = tmpTimingInfo;
2113
2114    while(i_sIdx < nsValue)
2115    {
2116       /*Increment frame Offset if PO falls on next SFN*/
2117       if(pdcchTime.sfn != tmpTimingInfo.sfn)
2118       {
2119          frameOffSet++;
2120       }
2121       pdcchTime = tmpTimingInfo;
2122       schIncrSlot(&(tmpTimingInfo), incr, cell->numSlots);
2123
2124       if (i_sIdx == 0)
2125       {
2126          cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pdcchTime.slot;
2127          cell->pageCb.pagMonOcc[i_sIdx].frameOffset = frameOffSet;
2128          i_sIdx++;
2129       }
2130       else
2131       {
2132          cnt++;
2133          if((cnt == totalNumSsb) && (i_sIdx < MAX_PO_PER_PF)) 
2134          {
2135             cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pdcchTime.slot;
2136             cell->pageCb.pagMonOcc[i_sIdx].frameOffset = frameOffSet;
2137             cnt = 0;
2138             i_sIdx++;
2139          }
2140       }
2141    }
2142 }
2143
2144 /****************************************************************************
2145  *
2146  * @brief Storing the paging information in SCH database 
2147  *
2148  * @details
2149  *
2150  *    Function : schAddPagingIndtoList
2151  *
2152  *    Functionality: Storing the paging information in SCH database
2153  *
2154  * @params[in] CmLListCp *storedPageList, CmLList *pageIndInfo
2155  *       
2156  * @return ROK - sucess
2157  *         RFAILED - failure
2158  *        
2159  *************************************************************************/
2160 uint8_t schAddPagingIndtoList(CmLListCp *storedPageList,void * pageIndInfo)
2161 {
2162    CmLList  *firstNodeOfList = NULLP;
2163    CmLList  *currentNodeInfo = NULLP;
2164    SchPageInfo *tempNode = NULLP, *recvdNode = NULLP;
2165    
2166    recvdNode = (SchPageInfo*) pageIndInfo;
2167    CM_LLIST_FIRST_NODE(storedPageList,firstNodeOfList);
2168    
2169    SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
2170    if(!currentNodeInfo)
2171    {  
2172       DU_LOG("\nERROR  --> SCH : schAddPagingIndtoList() : Memory allocation failed");
2173       return RFAILED;
2174    }
2175    
2176    currentNodeInfo->node = (PTR)pageIndInfo;
2177    while(firstNodeOfList)
2178    {
2179       tempNode = (SchPageInfo*)(firstNodeOfList->node);
2180       if ((recvdNode->pageTxTime.slot < tempNode->pageTxTime.slot))
2181       {
2182          cmLListInsCrnt(storedPageList, currentNodeInfo);
2183          break;
2184       }
2185       else if ((recvdNode->pageTxTime.slot == tempNode->pageTxTime.slot))
2186       {
2187          DU_LOG("\nERROR  --> SCH : schAddPagingIndtoList() : Slot[%d] is already present in the list", recvdNode->pageTxTime.slot);
2188          return RFAILED;
2189       }
2190       else
2191       {
2192          CM_LLIST_NEXT_NODE(storedPageList, firstNodeOfList);
2193       }
2194    } 
2195    
2196    if(!firstNodeOfList)
2197    {
2198       cmLListAdd2Tail(storedPageList, currentNodeInfo);
2199    }
2200    DU_LOG("\nDEBUG   -->  SCH : Paging information is stored successfully for PF:%d, Slot:%d",\
2201               recvdNode->pageTxTime.sfn, recvdNode->pageTxTime.slot);
2202    return ROK;
2203 }
2204
2205 /****************************************************************************
2206  *
2207  * @brief Process paging indication at  SCH recevied form MAC 
2208  *
2209  * @details
2210  *
2211  *    Function : SchProcPagingInd
2212  *
2213  *    Functionality: Process paging indication at SCH recevied form MAC 
2214  *
2215  * @params[in] Pst *pst,  SchPageInd *pageInd 
2216  *       
2217  * @return void 
2218  *        
2219  *************************************************************************/
2220 uint8_t SchProcPagingInd(Pst *pst,  SchPageInd *pageInd)
2221 {
2222    uint8_t ret = RFAILED;
2223    uint16_t cellIdx = 0;
2224    Inst  inst = pst->dstInst - SCH_INST_START;
2225    SchCellCb *cellCb = NULLP;
2226    SchPageInfo *pageInfo = NULLP;
2227
2228    if(pageInd)
2229    {
2230       DU_LOG("\nDEBUG   -->  SCH : Received paging indication from MAC for cellId[%d]",\
2231                   pageInd->cellId);
2232
2233       /* Fetch Cell CB */
2234       for(cellIdx = 0; cellIdx < MAX_NUM_CELL; cellIdx++)
2235       {
2236          if((schCb[inst].cells[cellIdx]) && (schCb[inst].cells[cellIdx]->cellId == pageInd->cellId))
2237          {
2238             cellCb = schCb[inst].cells[cellIdx];
2239             break;
2240          }
2241       }
2242       if(cellCb)
2243       {
2244          if(pageInd->i_s > cellCb->cellCfg.dlCfgCommon.schPcchCfg.numPO)
2245          {
2246             DU_LOG("\nERROR --> SCH : SchProcPagingInd(): i_s should not be greater than number of paging occasion");
2247          }
2248          else
2249          {
2250             SCH_ALLOC(pageInfo, sizeof(SchPageInfo));
2251             if(pageInfo)
2252             {
2253                pageInfo->pf = pageInd->pf; 
2254                pageInfo->i_s = pageInd->i_s;
2255                pageInfo->pageTxTime.cellId = pageInd->cellId;
2256                pageInfo->pageTxTime.sfn = (pageInd->pf +  cellCb->pageCb.pagMonOcc[pageInd->i_s].frameOffset) % MAX_SFN;
2257                pageInfo->pageTxTime.slot = cellCb->pageCb.pagMonOcc[pageInd->i_s].pagingOccSlot;
2258                pageInfo->mcs = DEFAULT_MCS;
2259                pageInfo->msgLen =  pageInd->pduLen;
2260                SCH_ALLOC(pageInfo->pagePdu, pageInfo->msgLen);
2261                if(!pageInfo->pagePdu)
2262                {
2263                   DU_LOG("\nERROR  --> SCH : SchProcPagingInd(): Failed to allocate memory");
2264                }
2265                else
2266                {
2267                   memcpy(pageInfo->pagePdu, pageInd->pagePdu, pageInfo->msgLen);
2268                   ret = schAddPagingIndtoList(&cellCb->pageCb.pageIndInfoRecord[pageInfo->pageTxTime.sfn], pageInfo);
2269                   if(ret != ROK)
2270                   {
2271                      DU_LOG("\nERROR  --> SCH : SchProcPagingInd(): Failed to store paging record");
2272                   }
2273                }
2274             }
2275             else
2276             {
2277                DU_LOG("\nERROR  --> SCH : SchProcPagingInd(): Failed to allocate memory");
2278             }
2279          }
2280       }
2281       else
2282       {
2283          DU_LOG("\nERROR  -->  SCH : Cell ID [%d] not found", pageInd->cellId);
2284       }
2285       SCH_FREE(pageInd->pagePdu, pageInd->pduLen);
2286       SCH_FREE(pageInd, sizeof(SchPageInd));
2287    }
2288    else
2289    {
2290       DU_LOG("\nERROR  --> SCH : SchProcPagingInd(): Received null pointer");
2291    }
2292    return ret;
2293 }
2294
2295 \f
2296 /***********************************************************
2297  *
2298  *     Func : SchFillCfmPst 
2299  *        
2300  *
2301  *     Desc : Fills the Confirmation Post Structure cfmPst using the reqPst 
2302  *            and the cfm->hdr.response.
2303  *            
2304  *
2305  *     Ret  : Void
2306  *
2307  *     Notes: 
2308  *
2309  *     File : rg_sch_lmm.c 
2310  *
2311  **********************************************************/
2312 Void SchFillCfmPst
2313 (
2314 Pst           *reqPst,
2315 Pst           *cfmPst,
2316 RgMngmt       *cfm
2317 )
2318 {
2319    Inst inst;
2320
2321    inst = (reqPst->dstInst - SCH_INST_START);
2322
2323    cfmPst->srcEnt    = ENTMAC;
2324    cfmPst->srcInst   = (Inst) 1;
2325    cfmPst->srcProcId = schCb[inst].schInit.procId;
2326    cfmPst->dstEnt    = ENTMAC;
2327    cfmPst->dstInst   = (Inst) 0;
2328    cfmPst->dstProcId = reqPst->srcProcId;
2329
2330    cfmPst->selector  = cfm->hdr.response.selector;
2331    cfmPst->region    = cfm->hdr.response.mem.region;
2332    cfmPst->pool      = cfm->hdr.response.mem.pool;
2333
2334    return;
2335 }
2336
2337 /*******************************************************************
2338  *
2339  * @brief Processes DL CQI ind from MAC
2340  *
2341  * @details
2342  *
2343  *    Function : SchProcDlCqiInd
2344  *
2345  *    Functionality:
2346  *       Processes DL CQI ind from MAC
2347  *
2348  * @params[in] 
2349  * @return ROK     - success
2350  *         RFAILED - failure
2351  *
2352  * ****************************************************************/
2353 uint8_t SchProcDlCqiInd(Pst *pst, SchDlCqiInd *dlCqiInd)
2354 {
2355    uint8_t  ret = ROK;
2356    uint16_t ueId = 0, cellIdx = 0;
2357    SchUeCb *ueCb = NULLP;
2358    SchCellCb *cell = NULLP;
2359    Inst  inst = pst->dstInst-SCH_INST_START;   
2360
2361    if(!dlCqiInd)
2362    {
2363       DU_LOG("\nERROR  -->  SCH : SchProcDlCqiInd(): CQI Ind is empty");
2364       ret = RFAILED;
2365    }
2366    else
2367    {
2368       GET_CELL_IDX(dlCqiInd->cellId, cellIdx);
2369       cell = schCb[inst].cells[cellIdx];
2370       if(cell == NULLP)
2371       { 
2372          DU_LOG("\nERROR  -->  SCH : SchProcDlCqiInd(): cell Id[%d] not found", dlCqiInd->cellId);
2373          ret = RFAILED;
2374       }
2375       else
2376       {
2377          if(cell->cellId == dlCqiInd->cellId)
2378          {
2379             GET_UE_ID(dlCqiInd->crnti, ueId);
2380             ueCb = &cell->ueCb[ueId-1];
2381             if(ueCb->crnti != dlCqiInd->crnti)
2382             {
2383                DU_LOG("\nERROR  -->  SCH : SchProcDlCqiInd(): UeCb for received crnti[%d] not found", dlCqiInd->crnti);
2384                ret = RFAILED;
2385             }
2386             else
2387             {
2388                /*TODO: complete the processing of DL CQI Ind*/ 
2389             }
2390          }
2391          else
2392          {
2393             DU_LOG("\nERROR  -->  SCH : SchProcDlCqiInd(): Received cell Id[%d] from MAC is not matching with CellID[%d] in SCH Cb",\
2394                     dlCqiInd->cellId, cell->cellId);
2395             ret = RFAILED;
2396          }
2397       }
2398    }
2399    return ret;
2400 }
2401
2402 /*******************************************************************
2403  *
2404  * @brief Processes UL CQI ind from MAC
2405  *
2406  * @details
2407  *
2408  *    Function : SchProcUlCqiInd
2409  *
2410  *    Functionality:
2411  *       Processes UL CQI ind from MAC
2412  *
2413  * @params[in] 
2414  * @return ROK     - success
2415  *         RFAILED - failure
2416  *
2417  * ****************************************************************/
2418 uint8_t SchProcUlCqiInd(Pst *pst, SchUlCqiInd *ulCqiInd)
2419 {
2420    uint8_t  ret = ROK;
2421    uint16_t ueId = 0, cellIdx = 0;
2422    SchUeCb *ueCb = NULLP;
2423    SchCellCb *cell = NULLP;
2424    Inst  inst = pst->dstInst-SCH_INST_START;   
2425
2426    if(!ulCqiInd)
2427    {
2428       DU_LOG("\nERROR  -->  SCH : SchProcUlCqiInd(): CQI Ind is empty");
2429       ret = RFAILED;
2430    }
2431    else
2432    {
2433       GET_CELL_IDX(ulCqiInd->cellId, cellIdx);
2434       cell = schCb[inst].cells[cellIdx];
2435       if(cell == NULLP)
2436       { 
2437          DU_LOG("\nERROR  -->  SCH : SchProcUlCqiInd(): cell Id[%d] not found", ulCqiInd->cellId);
2438          ret = RFAILED;
2439       }
2440       else
2441       {
2442          if(cell->cellId == ulCqiInd->cellId)
2443          {
2444             GET_UE_ID(ulCqiInd->crnti, ueId);
2445             ueCb = &cell->ueCb[ueId-1];
2446             if(ueCb->crnti != ulCqiInd->crnti)
2447             {
2448                DU_LOG("\nERROR  -->  SCH : SchProcUlCqiInd(): UeCb for received crnti[%d] not found",ulCqiInd->crnti);
2449                ret = RFAILED;
2450             }
2451             else
2452             {
2453                /*TODO: complete the processing of UL CQI Ind*/ 
2454             }
2455          }
2456          else
2457          {
2458             DU_LOG("\nERROR  -->  SCH : SchProcUlCqiInd(): Received cell Id[%d] from MAC is not matching with CellId[%d] in SCH Cb",\
2459                     ulCqiInd->cellId, cell->cellId);
2460             ret = RFAILED;
2461          }
2462       }
2463    }
2464    return ret;
2465 }
2466
2467 /*******************************************************************
2468  *
2469  * @brief Processes PHR ind from MAC
2470  *
2471  * @details
2472  *
2473  *    Function : SchProcPhrInd
2474  *
2475  *    Functionality:
2476  *       Processes PHR ind from MAC
2477  *
2478  * @params[in] 
2479  * @return ROK     - success
2480  *         RFAILED - failure
2481  *
2482  * ****************************************************************/
2483 uint8_t SchProcPhrInd(Pst *pst, SchPwrHeadroomInd *schPhrInd)
2484 {
2485    uint8_t  ret = ROK;
2486    uint16_t ueId = 0, cellIdx = 0;
2487    SchUeCb *ueCb = NULLP;
2488    SchCellCb *cell = NULLP;
2489    Inst  inst = pst->dstInst-SCH_INST_START;   
2490
2491    if(!schPhrInd)
2492    {
2493       DU_LOG("\nERROR  -->  SCH : SchProcPhrInd(): PHR is empty");
2494       ret = RFAILED;
2495    }
2496    else
2497    {
2498       GET_CELL_IDX(schPhrInd->cellId, cellIdx);
2499       cell = schCb[inst].cells[cellIdx];
2500       if(cell == NULLP)
2501       { 
2502          DU_LOG("\nERROR  -->  SCH : schProcPhrInd(): cell Id[%d] is not found", schPhrInd->cellId);
2503          ret = RFAILED;
2504       }
2505       else
2506       {
2507          if(cell->cellId == schPhrInd->cellId)
2508          {
2509             GET_UE_ID(schPhrInd->crnti, ueId);
2510             ueCb = &cell->ueCb[ueId-1];
2511             if(ueCb->crnti != schPhrInd->crnti)
2512             {
2513                DU_LOG("\nERROR  -->  SCH : SchProcPhrInd(): UeCb for received crnti[%d] not found",schPhrInd->crnti);
2514                ret = RFAILED;
2515             }
2516             else
2517             {
2518                /*TODO: complete the processing of PHR Ind*/ 
2519             }
2520          }
2521          else
2522          {
2523             DU_LOG("\nERROR  -->  SCH : SchProcPhrInd(): Mismatch between Received cell Id[%d] from MAC and CellID[%d] in SCH CB ",\
2524                     schPhrInd->cellId, cell->cellId);
2525             ret = RFAILED;
2526          }
2527       }
2528    }
2529    return ret;
2530 }
2531
2532 /**********************************************************************
2533   End of file
2534  **********************************************************************/