Merge "Fixes in current code for Multi-UE support [Issue-ID: ODUHIGH-354]"
[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
51 SchCb schCb[SCH_MAX_INST];
52 void SchFillCfmPst(Pst *reqPst,Pst *cfmPst,RgMngmt *cfm);
53
54 /* local defines */
55 SchCellCfgCfmFunc SchCellCfgCfmOpts[] = 
56 {
57    packSchCellCfgCfm,     /* LC */
58    MacProcSchCellCfgCfm,  /* TC */
59    packSchCellCfgCfm      /* LWLC */
60 };
61
62
63 /**
64  * @brief Task Initiation function. 
65  *
66  * @details
67  *
68  *     Function : schActvInit
69  *     
70  *     This function is supplied as one of parameters during MAC's 
71  *     task registration. MAC will invoke this function once, after
72  *     it creates and attaches this TAPA Task to a system task.
73  *     
74  *  @param[in]  Ent Entity, the entity ID of this task.     
75  *  @param[in]  Inst Inst, the instance ID of this task.
76  *  @param[in]  Region Region, the region ID registered for memory 
77  *              usage of this task.
78  *  @param[in]  Reason Reason.
79  *  @return  int
80  *      -# ROK
81  **/
82 uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason)
83 {
84    Inst inst = (instId  - SCH_INST_START);
85
86    /* Initialize the MAC TskInit structure to zero */
87    memset ((uint8_t *)&schCb[inst], 0, sizeof(schCb));
88
89    /* Initialize the MAC TskInit with received values */
90    schCb[inst].schInit.ent = entity;
91    schCb[inst].schInit.inst = inst;
92    schCb[inst].schInit.region = region;
93    schCb[inst].schInit.pool = 0;
94    schCb[inst].schInit.reason = reason;
95    schCb[inst].schInit.cfgDone = FALSE;
96    schCb[inst].schInit.acnt = FALSE;
97    schCb[inst].schInit.usta = FALSE;
98    schCb[inst].schInit.trc = FALSE;
99    schCb[inst].schInit.procId = ODU_GET_PROCID();
100
101    return ROK;
102 } /* schActvInit */
103
104 /**
105  * @brief Scheduler instance Configuration Handler. 
106  *
107  * @details
108  *
109  *     Function : SchInstCfg
110  *     
111  *     This function in called by SchProcGenCfgReq(). It handles the
112  *     general configurations of the scheduler instance. Returns
113  *     reason for success/failure of this function.
114  *     
115  *  @param[in]  RgCfg *cfg, the Configuaration information 
116  *  @return  uint16_t
117  *      -# LCM_REASON_NOT_APPL 
118  *      -# LCM_REASON_INVALID_MSGTYPE
119  *      -# LCM_REASON_MEM_NOAVAIL
120  **/
121 uint8_t SchInstCfg(RgCfg *cfg, Inst  dInst)
122 {
123    uint16_t ret = LCM_REASON_NOT_APPL;
124    Inst     inst = (dInst - SCH_INST_START);
125
126    DU_LOG("\nDEBUG  -->  SCH : Entered SchInstCfg()");
127    /* Check if Instance Configuration is done already */
128    if (schCb[inst].schInit.cfgDone == TRUE)
129    {
130       return LCM_REASON_INVALID_MSGTYPE;
131    }
132    /* Update the Pst structure for LM interface */
133    memcpy(&schCb[inst].schInit.lmPst,
134          &cfg->s.schInstCfg.genCfg.lmPst,
135          sizeof(Pst));
136
137    schCb[inst].schInit.inst = inst;
138    schCb[inst].schInit.lmPst.srcProcId = schCb[inst].schInit.procId;
139    schCb[inst].schInit.lmPst.srcEnt = schCb[inst].schInit.ent;
140    schCb[inst].schInit.lmPst.srcInst = schCb[inst].schInit.inst +
141       SCH_INST_START;
142    schCb[inst].schInit.lmPst.event = EVTNONE;
143
144    schCb[inst].schInit.region = cfg->s.schInstCfg.genCfg.mem.region;
145    schCb[inst].schInit.pool = cfg->s.schInstCfg.genCfg.mem.pool;
146    schCb[inst].genCfg.tmrRes = cfg->s.schInstCfg.genCfg.tmrRes;
147 #ifdef LTE_ADV
148    schCb[inst].genCfg.forceCntrlSrbBoOnPCel =  cfg->s.schInstCfg.genCfg.forceCntrlSrbBoOnPCel;
149    schCb[inst].genCfg.isSCellActDeactAlgoEnable =  cfg->s.schInstCfg.genCfg.isSCellActDeactAlgoEnable;
150 #endif
151    schCb[inst].genCfg.startCellId    = cfg->s.schInstCfg.genCfg.startCellId;
152
153    /* Initialzie the timer queue */   
154    memset(&schCb[inst].tmrTq, 0, sizeof(CmTqType) * SCH_TQ_SIZE);
155    /* Initialize the timer control point */
156    memset(&schCb[inst].tmrTqCp, 0, sizeof(CmTqCp));
157    schCb[inst].tmrTqCp.tmrLen = RGSCH_TQ_SIZE;
158
159    /* SS_MT_TMR needs to be enabled as schActvTmr needs instance information */
160    /* Timer Registration request to system services */
161    if (ODU_REG_TMR_MT(schCb[inst].schInit.ent, dInst,
162             (int)schCb[inst].genCfg.tmrRes, schActvTmr) != ROK)
163    {
164       DU_LOG("\nERROR  -->  SCH : SchInstCfg(): Failed to "
165             "register timer.");
166       return (LCM_REASON_MEM_NOAVAIL);
167    }   
168               
169    /* Set Config done in TskInit */
170    schCb[inst].schInit.cfgDone = TRUE;
171    DU_LOG("\nINFO  -->  SCH : Scheduler gen config done");
172
173    return ret;
174 }
175
176 /**
177  * @brief Layer Manager Configuration request handler. 
178  *
179  * @details
180  *
181  *     Function : SchProcGenCfgReq
182  *     
183  *     This function handles the configuration
184  *     request received at scheduler instance from the Layer Manager.
185  *     -# Based on the cfg->hdr.elmId.elmnt value it invokes one of the
186  *        functions rgHdlGenCfg() or rgHdlSapCfg().
187  *     -# Invokes RgMiLrgSchCfgCfm() to send back the confirmation to the LM.
188  *     
189  *  @param[in]  Pst *pst, the post structure     
190  *  @param[in]  RgMngmt *cfg, the configuration parameter's structure
191  *  @return  S16
192  *      -# ROK
193  **/
194 uint8_t SchProcGenCfgReq(Pst *pst, RgMngmt *cfg)
195 {
196    uint8_t   ret = LCM_PRIM_OK;
197    uint16_t  reason = LCM_REASON_NOT_APPL;
198    RgMngmt   cfm;
199    Pst       cfmPst;
200
201 #ifdef CALL_FLOW_DEBUG_LOG
202    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : GENERAL_CFG_REQ\n");
203 #endif
204
205    if(pst->dstInst < SCH_INST_START)
206    {
207       DU_LOG("\nERROR  -->  SCH : Invalid inst ID");
208       DU_LOG("\nERROR  -->  SCH : SchProcGenCfgReq(): "
209             "pst->dstInst=%d SCH_INST_START=%d", pst->dstInst,SCH_INST_START); 
210       return ROK;
211    }
212    DU_LOG("\nINFO -->  SCH : Received scheduler gen config");
213    /* Fill the post structure for sending the confirmation */
214    memset(&cfmPst, 0 , sizeof(Pst));
215    SchFillCfmPst(pst, &cfmPst, cfg);
216
217    memset(&cfm, 0, sizeof(RgMngmt));
218
219 #ifdef LMINT3
220    cfm.hdr.transId =
221       cfg->hdr.transId;
222 #endif
223
224    cfm.hdr.elmId.elmnt = cfg->hdr.elmId.elmnt;
225    switch(cfg->hdr.elmId.elmnt)
226    {
227       case STSCHINST:
228          reason = SchInstCfg(&cfg->t.cfg,pst->dstInst );
229          break;
230       default:
231          ret = LCM_PRIM_NOK;
232          reason = LCM_REASON_INVALID_ELMNT;
233          DU_LOG("\nERROR  -->  SCH : Invalid Elmnt=%d", cfg->hdr.elmId.elmnt);
234          break;
235    }
236
237    if (reason != LCM_REASON_NOT_APPL)
238    {
239       ret = LCM_PRIM_NOK;
240    }
241
242    cfm.cfm.status = ret;
243    cfm.cfm.reason = reason;
244
245    SchSendCfgCfm(&cfmPst, &cfm);
246    /*   SCH_FREE(pst->region, pst->pool, (Data *)cfg, sizeof(RgMngmt)); */
247
248    return ROK;
249 }/*-- SchProcGenCfgReq --*/
250
251 /**
252  * @brief slot indication from MAC to SCH.
253  *
254  * @details
255  *
256  *     Function : MacSchSlotInd 
257  *      
258  *      This API is invoked by PHY to indicate slot indication to Scheduler for
259  *      a cell.
260  *           
261  *  @param[in]  Pst            *pst
262  *  @param[in]  SlotIndInfo    *slotInd
263  *  @return  S16
264  *      -# ROK 
265  *      -# RFAILED 
266  **/
267 uint8_t MacSchSlotInd(Pst *pst, SlotIndInfo *slotInd)
268 {
269    Inst  inst = pst->dstInst-SCH_INST_START;
270
271 #ifdef CALL_FLOW_DEBUG_LOG
272    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SLOT_IND_TO_SCH\n");
273 #endif
274
275    schProcessSlotInd(slotInd, inst);
276
277    return ROK;
278 }  /* MacSchSlotInd */
279
280 /*******************************************************************
281  *
282  * @brief Processes Rach indication from MAC 
283  *
284  * @details
285  *
286  *    Function : MacSchRachInd
287  *
288  *    Functionality:
289  *      Processes Rach indication from MAC
290  *
291  * @params[in] 
292  * @return ROK     - success
293  *         RFAILED - failure
294  *
295  * ****************************************************************/
296 uint8_t MacSchRachInd(Pst *pst, RachIndInfo *rachInd)
297 {
298    Inst  inst = pst->dstInst-SCH_INST_START;
299
300 #ifdef CALL_FLOW_DEBUG_LOG
301    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_RACH_IND_TO_SCH\n");
302 #endif
303
304    DU_LOG("\nINFO  -->  SCH : Received Rach indication");
305    schProcessRachInd(rachInd, inst);
306    return ROK;
307 }
308
309 /*******************************************************************
310  *
311  * @brief Processes CRC indication from MAC 
312  *
313  * @details
314  *
315  *    Function : MacSchCrcInd
316  *
317  *    Functionality:
318  *      Processes CRC indication from MAC
319  *
320  * @params[in] Post structure
321  *             Crc Indication
322  * @return ROK     - success
323  *         RFAILED - failure
324  *
325  * ****************************************************************/
326 uint8_t MacSchCrcInd(Pst *pst, CrcIndInfo *crcInd)
327 {
328 #ifdef CALL_FLOW_DEBUG_LOG
329    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_CRC_IND_TO_SCH\n");
330 #endif
331
332    switch(crcInd->crcInd[0])
333    {
334       case CRC_FAILED:
335          DU_LOG("\nDEBUG  -->  SCH : Received CRC indication. CRC Status [FAILURE]");
336          break;
337       case CRC_PASSED:
338          DU_LOG("\nDEBUG  -->  SCH : Received CRC indication. CRC Status [PASS]");
339          break;
340       default:
341          DU_LOG("\nDEBUG  -->  SCH : Invalid CRC state %d", crcInd->crcInd[0]);
342          return RFAILED;
343    }
344    return ROK;
345 }
346
347 #ifdef NR_TDD
348 /**
349  *@brief Returns TDD periodicity in micro seconds
350  *
351  * @details
352  * 
353  * Function : schGetPeriodicityInMsec 
354  * 
355  * This API retunrs TDD periodicity in micro seconds
356  * 
357  * @param[in] DlUlTxPeriodicity 
358  * @return  periodicityInMsec
359  * **/
360
361 uint16_t schGetPeriodicityInMsec(DlUlTxPeriodicity tddPeriod)
362 {
363    uint16_t  periodicityInMsec = 0;
364    switch(tddPeriod)
365    {
366       case TX_PRDCTY_MS_0P5:
367       {
368          periodicityInMsec = 500;
369          break;
370       }
371       case TX_PRDCTY_MS_0P625:
372       {
373          periodicityInMsec = 625;
374          break;
375       }
376       case TX_PRDCTY_MS_1:
377       {
378          periodicityInMsec = 1000;
379          break;
380       }
381       case TX_PRDCTY_MS_1P25:
382       {
383          periodicityInMsec = 1250;
384          break;
385       }
386       case TX_PRDCTY_MS_2:
387       {
388          periodicityInMsec = 2000;
389          break;
390       }
391       case TX_PRDCTY_MS_2P5:
392       {
393          periodicityInMsec = 2500;
394          break;
395       }
396       case TX_PRDCTY_MS_5:
397       {
398          periodicityInMsec = 5000;
399          break;
400       }
401       case TX_PRDCTY_MS_10:
402       {
403          periodicityInMsec = 10000;
404          break;
405       }
406       default:
407       {
408          DU_LOG("\nERROR  -->  SCH : Invalid DlUlTxPeriodicity:%d", tddPeriod);
409       }
410    }
411
412    return periodicityInMsec;
413 }
414
415
416 /**
417  * @brief init TDD slot config 
418  *
419  * @details
420  *
421  *     Function : schInitTddSlotCfg 
422  *      
423  *      This API is invoked after receiving schCellCfg
424  *           
425  *  @param[in]  schCellCb *cell
426  *  @param[in]  SchCellCfg *schCellCfg
427  *  @return  void
428  **/
429 void schInitTddSlotCfg(SchCellCb *cell, SchCellCfg *schCellCfg)
430 {
431    uint16_t periodicityInMicroSec = 0;
432    int8_t slotIdx, symbIdx;
433
434    periodicityInMicroSec = schGetPeriodicityInMsec(schCellCfg->tddCfg.tddPeriod);
435    cell->numSlotsInPeriodicity = (periodicityInMicroSec * pow(2, schCellCfg->numerology))/1000;
436    cell->slotFrmtBitMap = 0;
437    cell->symbFrmtBitMap = 0;
438    for(slotIdx = cell->numSlotsInPeriodicity-1; slotIdx >= 0; slotIdx--)
439    {
440       symbIdx = 0;
441       /* If the first and last symbol are the same, the entire slot is the same type */
442       if((schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx] == schCellCfg->tddCfg.slotCfg[slotIdx][MAX_SYMB_PER_SLOT-1]) &&
443               schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx] != FLEXI_SLOT)
444       {
445          switch(schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx])
446          {
447             case DL_SLOT:
448             {
449                /*BitMap to be set to 00 */
450                cell->slotFrmtBitMap = (cell->slotFrmtBitMap<<2);
451                break;
452             }
453             case UL_SLOT:
454             {
455                /*BitMap to be set to 01 */
456                cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (UL_SLOT));
457                break;
458             }
459             default:
460                DU_LOG("\nERROR  -->  SCH : Invalid slot Config in schInitTddSlotCfg");
461            }
462          continue;
463       }
464       /* slot config is flexible. First set slotBitMap to 10 */
465       cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (FLEXI_SLOT));
466
467       /* Now set symbol bitmap */ 
468       for(symbIdx = MAX_SYMB_PER_SLOT-1; symbIdx >= 0; symbIdx--)
469       {
470          switch(schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx])
471          {
472             case DL_SLOT:
473             {
474                /*symbol BitMap to be set to 00 */
475                cell->symbFrmtBitMap = (cell->symbFrmtBitMap<<2);
476                break;
477             }
478             case UL_SLOT:
479             {
480                /*symbol BitMap to be set to 01 */
481                cell->symbFrmtBitMap = ((cell->symbFrmtBitMap<<2) | (UL_SLOT));
482                break;
483             }
484             case FLEXI_SLOT:
485             {
486                /*symbol BitMap to be set to 10 */
487                cell->symbFrmtBitMap = ((cell->symbFrmtBitMap<<2) | (FLEXI_SLOT));
488                break;
489             }
490             default:
491                DU_LOG("\nERROR  -->  SCH : Invalid slot Config in schInitTddSlotCfg");
492          }
493       }
494    }
495 }
496 #endif
497
498 /**
499  * @brief Fill SSB start symbol
500  *
501  * @details
502  *
503  *     Function : fillSsbStartSymb 
504  *      
505  *      This API stores SSB start index per beam
506  *           
507  *  @param[in]  SchCellCb     *cellCb
508  *  @return  int
509  *      -# ROK 
510  *      -# RFAILED 
511  **/
512 void fillSsbStartSymb(SchCellCb *cellCb)
513 {
514    uint8_t cnt, scs, symbIdx, ssbStartSymbArr[SCH_MAX_SSB_BEAM];
515
516    scs = cellCb->cellCfg.ssbSchCfg.scsCommon;
517
518    memset(ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
519    symbIdx = 0;
520    /* Determine value of "n" based on Section 4.1 of 3GPP TS 38.213 */
521    switch(scs)
522    {
523       case SCS_15KHZ:
524          {
525             if(cellCb->cellCfg.dlFreq <= 300000)
526                cnt = 2;/* n = 0, 1 */
527             else
528                cnt = 4; /* n = 0, 1, 2, 3 */
529             for(uint8_t idx=0; idx<cnt; idx++)
530             {
531                /* start symbol determined using {2, 8} + 14n */
532                ssbStartSymbArr[symbIdx++] = 2 + SCH_SYMBOL_PER_SLOT*idx;
533                ssbStartSymbArr[symbIdx++] = 8 + SCH_SYMBOL_PER_SLOT*idx;
534             }
535          }
536          break;
537       case SCS_30KHZ:
538          {
539             if(cellCb->cellCfg.dlFreq <= 300000)
540                cnt = 1;/* n = 0 */
541             else
542                cnt = 2; /* n = 0, 1 */
543             for(uint8_t idx=0; idx<cnt; idx++)
544             {
545                /* start symbol determined using {4, 8, 16, 20} + 28n */
546                ssbStartSymbArr[symbIdx++] = 4 + SCH_SYMBOL_PER_SLOT*idx;
547                ssbStartSymbArr[symbIdx++] = 8 + SCH_SYMBOL_PER_SLOT*idx;
548                ssbStartSymbArr[symbIdx++] = 16 + SCH_SYMBOL_PER_SLOT*idx;
549                ssbStartSymbArr[symbIdx++] = 20 + SCH_SYMBOL_PER_SLOT*idx;
550             }
551          }
552          break;
553       default:
554          DU_LOG("\nERROR  -->  SCH : SCS %d is currently not supported", scs);
555    }
556    memset(cellCb->ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
557    memcpy(cellCb->ssbStartSymbArr, ssbStartSymbArr, SCH_MAX_SSB_BEAM);
558
559 }
560
561
562 /**
563  * @brief init cellCb based on cellCfg
564  *
565  * @details
566  *
567  *     Function : schInitCellCb 
568  *      
569  *      This API is invoked after receiving schCellCfg
570  *           
571  *  @param[in]  schCellCb *cell
572  *  @param[in]  SchCellCfg *schCellCfg
573  *  @return  int
574  *      -# ROK 
575  *      -# RFAILED 
576  **/
577 uint8_t schInitCellCb(Inst inst, SchCellCfg *schCellCfg)
578 {
579    SchCellCb *cell= NULLP;
580    SCH_ALLOC(cell, sizeof(SchCellCb));
581    if(!cell)
582    {
583       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
584       return RFAILED;
585    }
586
587    cell->cellId = schCellCfg->cellId; 
588    cell->instIdx = inst;
589    switch(schCellCfg->numerology)
590    {
591       case SCH_NUMEROLOGY_0:
592          {
593             cell->numSlots = SCH_MU0_NUM_SLOTS;
594          }
595          break;
596       case SCH_NUMEROLOGY_1:
597          {
598             cell->numSlots = SCH_MU1_NUM_SLOTS;
599          }
600          break;
601       case SCH_NUMEROLOGY_2:
602          {
603             cell->numSlots = SCH_MU2_NUM_SLOTS;
604          }
605          break;
606       case SCH_NUMEROLOGY_3:
607          {
608             cell->numSlots = SCH_MU3_NUM_SLOTS;
609          }
610          break;
611       case SCH_NUMEROLOGY_4:
612          {
613             cell->numSlots = SCH_MU4_NUM_SLOTS;
614          }
615          break;
616       default:
617          DU_LOG("\nERROR  -->  SCH : Numerology %d not supported", schCellCfg->numerology);
618    }
619 #ifdef NR_TDD
620    schInitTddSlotCfg(cell, schCellCfg);   
621 #endif
622
623    SCH_ALLOC(cell->schDlSlotInfo, cell->numSlots * sizeof(SchDlSlotInfo*));
624    if(!cell->schDlSlotInfo)
625    {
626       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb for schDlSlotInfo");
627       return RFAILED;
628    }
629
630    SCH_ALLOC(cell->schUlSlotInfo, cell->numSlots * sizeof(SchUlSlotInfo*));
631    if(!cell->schUlSlotInfo)
632    {
633       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb for schUlSlotInfo");
634       return RFAILED;
635    }
636
637    for(uint8_t idx=0; idx<cell->numSlots; idx++)
638    {
639       SchDlSlotInfo *schDlSlotInfo;
640       SchUlSlotInfo *schUlSlotInfo;
641
642       /* DL Alloc */
643       SCH_ALLOC(schDlSlotInfo, sizeof(SchDlSlotInfo));
644       if(!schDlSlotInfo)
645       {
646          DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
647          return RFAILED;
648       }
649
650       /* UL Alloc */
651       SCH_ALLOC(schUlSlotInfo, sizeof(SchUlSlotInfo));
652       if(!schUlSlotInfo)
653       {
654          DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
655          return RFAILED;
656       }
657
658       schInitDlSlot(schDlSlotInfo);
659       schInitUlSlot(schUlSlotInfo);
660
661       cell->schDlSlotInfo[idx] = schDlSlotInfo;
662       cell->schUlSlotInfo[idx] = schUlSlotInfo;
663
664    }
665    cell->firstSsbTransmitted = false;
666    cell->firstSib1Transmitted = false;
667    fillSsbStartSymb(cell);
668    schCb[inst].cells[inst] = cell;
669
670    DU_LOG("\nINFO  -->  SCH : Cell init completed for cellId:%d", cell->cellId);
671
672    return ROK;   
673 }
674
675 /**
676  * @brief Fill SIB1 configuration
677  *
678  * @details
679  *
680  *     Function : fillSchSib1Cfg
681  *
682  *     Fill SIB1 configuration
683  *
684  *  @param[in]  uint8_t bandwidth : total available bandwidth
685  *              uint8_t numSlots : total slots per SFN
686  *              SchSib1Cfg *sib1SchCfg : cfg to be filled
687  *              uint16_t pci : physical cell Id
688  *              uint8_t offsetPointA : offset
689  *  @return  void
690  **/
691 void fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots, SchSib1Cfg *sib1SchCfg, uint16_t pci, uint8_t offsetPointA)
692 {
693    uint8_t coreset0Idx = 0;
694    uint8_t searchSpace0Idx = 0;
695    //uint8_t ssbMuxPattern = 0;
696    uint8_t numRbs = 0;
697    uint8_t numSymbols = 0;
698    uint8_t offset = 0;
699    uint8_t oValue = 0;
700    //uint8_t numSearchSpacePerSlot = 0;
701    uint8_t mValue = 0;
702    uint8_t firstSymbol = 0; /* need to calculate using formula mentioned in 38.213 */
703    uint8_t slotIndex = 0;
704    /* TODO : This should be filled through freqDomRscAllocType0() */
705    uint8_t FreqDomainResource[6] = {15, 0, 0, 0, 0, 0};
706    uint16_t tbSize = 0;
707    uint8_t numPdschSymbols = 11; /* considering pdsch region from symbols 3 to 13 */
708    uint8_t ssbIdx = 0;
709
710    PdcchCfg *pdcch = &(sib1SchCfg->sib1PdcchCfg);
711    PdschCfg *pdsch = &(sib1SchCfg->sib1PdschCfg);
712    BwpCfg *bwp = &(sib1SchCfg->bwp);
713
714    coreset0Idx     = sib1SchCfg->coresetZeroIndex;
715    searchSpace0Idx = sib1SchCfg->searchSpaceZeroIndex;
716
717    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
718    //ssbMuxPattern = coresetIdxTable[coreset0Idx][0];
719    numRbs        = coresetIdxTable[coreset0Idx][1];
720    numSymbols    = coresetIdxTable[coreset0Idx][2];
721    offset        = coresetIdxTable[coreset0Idx][3];
722
723    /* derive the search space params from table 13-11 spec 38.213 */
724    oValue                = searchSpaceIdxTable[searchSpace0Idx][0];
725    //numSearchSpacePerSlot = searchSpaceIdxTable[searchSpace0Idx][1];
726    mValue                = searchSpaceIdxTable[searchSpace0Idx][2];
727    firstSymbol           = searchSpaceIdxTable[searchSpace0Idx][3];
728
729    /* calculate the n0, need to add the formulae, as of now the value is 0 
730     * Need to add the even and odd values of i during configuration 
731     * [(O . 2^u + i . M )  ] mod numSlotsPerSubframe 
732     * assuming u = 0, i = 0, numSlotsPerSubframe = 10
733     * Also, from this configuration, coreset0 is only on even subframe */
734    slotIndex = (int)((oValue*pow(2, mu)) + floor(ssbIdx*mValue))%numSlots;
735    sib1SchCfg->n0 = slotIndex;
736
737    /* calculate the PRBs */
738    //freqDomRscAllocType0(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
739
740    /* fill BWP */
741    switch(bandwidth)
742    {
743       case BANDWIDTH_20MHZ:
744          {
745             bwp->freqAlloc.numPrb = TOTAL_PRB_20MHZ_MU0;
746          }
747          break;
748       case BANDWIDTH_100MHZ:
749          {
750             bwp->freqAlloc.numPrb = TOTAL_PRB_100MHZ_MU1;
751          }
752          break;
753       default:
754          DU_LOG("\nERROR  -->  SCH : Bandwidth %d not supported", bandwidth);
755
756    }
757    bwp->freqAlloc.startPrb = 0;
758    bwp->subcarrierSpacing  = 0;         /* 15Khz */
759    bwp->cyclicPrefix       = 0;              /* normal */
760
761    /* fill the PDCCH PDU */
762    pdcch->coresetCfg.coreSetSize = numRbs;
763    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
764    pdcch->coresetCfg.durationSymbols = numSymbols;
765    memcpy(pdcch->coresetCfg.freqDomainResource,FreqDomainResource,6);
766    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
767    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
768    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
769    pdcch->coresetCfg.coreSetType = 0;
770    pdcch->coresetCfg.shiftIndex = pci;
771    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
772    pdcch->numDlDci = 1;
773    pdcch->dci.rnti = SI_RNTI;
774    pdcch->dci.scramblingId = pci;
775    pdcch->dci.scramblingRnti = 0;
776    pdcch->dci.cceIndex = 0;
777    pdcch->dci.aggregLevel = 4;
778    pdcch->dci.beamPdcchInfo.numPrgs = 1;
779    pdcch->dci.beamPdcchInfo.prgSize = 1;
780    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
781    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
782    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
783    pdcch->dci.txPdcchPower.powerValue = 0;
784    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
785    /* Storing pdschCfg pointer here. Required to access pdsch config while
786       fillig up pdcch pdu */
787    pdcch->dci.pdschCfg = pdsch; 
788
789    /* fill the PDSCH PDU */
790    uint8_t cwCount = 0;
791    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
792    pdsch->rnti = 0xFFFF; /* SI-RNTI */
793    pdsch->pduIndex = 0;
794    pdsch->numCodewords = 1;
795    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
796    {
797       pdsch->codeword[cwCount].targetCodeRate = 308;
798       pdsch->codeword[cwCount].qamModOrder = 2;
799       pdsch->codeword[cwCount].mcsIndex = sib1SchCfg->sib1Mcs;
800       pdsch->codeword[cwCount].mcsTable = 0; /* notqam256 */
801       pdsch->codeword[cwCount].rvIndex = 0;
802       tbSize = schCalcTbSize(sib1SchCfg->sib1PduLen + TX_PAYLOAD_HDR_LEN);
803       pdsch->codeword[cwCount].tbSize = tbSize;
804    }
805    pdsch->dataScramblingId                   = pci;
806    pdsch->numLayers                          = 1;
807    pdsch->transmissionScheme                 = 0;
808    pdsch->refPoint                           = 0;
809    pdsch->dmrs.dlDmrsSymbPos                 = 4; /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
810    pdsch->dmrs.dmrsConfigType                = 0; /* type-1 */
811    pdsch->dmrs.dlDmrsScramblingId            = pci;
812    pdsch->dmrs.scid                          = 0;
813    pdsch->dmrs.numDmrsCdmGrpsNoData          = 1;
814    pdsch->dmrs.dmrsPorts                     = 0x0001;
815    pdsch->dmrs.mappingType                   = DMRS_MAP_TYPE_A; /* Type-A */
816    pdsch->dmrs.nrOfDmrsSymbols               = NUM_DMRS_SYMBOLS;
817    pdsch->dmrs.dmrsAddPos                    = DMRS_ADDITIONAL_POS;
818
819    pdsch->pdschFreqAlloc.resourceAllocType   = 1; /* RAT type-1 RIV format */
820    pdsch->pdschFreqAlloc.freqAlloc.startPrb  = offsetPointA + SCH_SSB_NUM_PRB + 1; /* the RB numbering starts from coreset0,
821                                                                             and PDSCH is always above SSB */
822    pdsch->pdschFreqAlloc.freqAlloc.numPrb    = schCalcNumPrb(tbSize,sib1SchCfg->sib1Mcs,numPdschSymbols);
823    pdsch->pdschFreqAlloc.vrbPrbMapping       = 0; /* non-interleaved */
824    pdsch->pdschTimeAlloc.rowIndex            = 1;
825    /* This is Intel's requirement. PDSCH should start after PDSCH DRMS symbol */
826    pdsch->pdschTimeAlloc.timeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
827    pdsch->pdschTimeAlloc.timeAlloc.numSymb   = numPdschSymbols;
828    pdsch->beamPdschInfo.numPrgs              = 1;
829    pdsch->beamPdschInfo.prgSize              = 1;
830    pdsch->beamPdschInfo.digBfInterfaces      = 0;
831    pdsch->beamPdschInfo.prg[0].pmIdx         = 0;
832    pdsch->beamPdschInfo.prg[0].beamIdx[0]    = 0;
833    pdsch->txPdschPower.powerControlOffset    = 0;
834    pdsch->txPdschPower.powerControlOffsetSS  = 0;
835
836 }
837
838 /**
839  * @brief cell config from MAC to SCH.
840  *
841  * @details
842  *
843  *     Function : macSchCellCfgReq
844  *      
845  *      This API is invoked by MAC to send cell config to SCH
846  *           
847  *  @param[in]  Pst            *pst
848  *  @param[in]  SchCellCfg     *schCellCfg
849  *  @return  int
850  *      -# ROK 
851  *      -# RFAILED 
852  **/
853 uint8_t SchHdlCellCfgReq(Pst *pst, SchCellCfg *schCellCfg)
854 {
855    uint8_t ret = ROK;
856    SchCellCb *cellCb;
857    SchCellCfgCfm schCellCfgCfm;
858    Pst rspPst;
859    Inst inst = pst->dstInst-1; 
860
861 #ifdef CALL_FLOW_DEBUG_LOG
862    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SCH_CELL_CFG\n");
863 #endif 
864
865    schInitCellCb(inst, schCellCfg);
866    cellCb = schCb[inst].cells[inst]; //cells is of MAX_CELLS, why inst
867    cellCb->macInst = pst->srcInst;
868
869    /* derive the SIB1 config parameters */
870    fillSchSib1Cfg(schCellCfg->numerology, schCellCfg->bandwidth, cellCb->numSlots,
871          &(schCellCfg->sib1SchCfg), schCellCfg->phyCellId,
872          schCellCfg->ssbSchCfg.ssbOffsetPointA);
873    memcpy(&cellCb->cellCfg, schCellCfg, sizeof(SchCellCfg));
874
875    /* Initializing global variables */
876    cellCb->actvUeBitMap = 0;
877    cellCb->boIndBitMap = 0;
878
879    /* Fill and send Cell config confirm */
880    memset(&rspPst, 0, sizeof(Pst));
881    FILL_PST_SCH_TO_MAC(rspPst, pst->dstInst);
882    rspPst.event = EVENT_SCH_CELL_CFG_CFM;
883
884    schCellCfgCfm.cellId = schCellCfg->cellId; 
885    schCellCfgCfm.rsp = RSP_OK;
886
887    ret = (*SchCellCfgCfmOpts[rspPst.selector])(&rspPst, &schCellCfgCfm);
888    return ret;
889
890 }
891
892 /*******************************************************************
893  *
894  * @brief Processes DL RLC BO info from MAC
895  *
896  * @details
897  *
898  *    Function : MacSchDlRlcBoInfo
899  *
900  *    Functionality:
901  *       Processes DL RLC BO info from MAC
902  *
903  * @params[in] 
904  * @return ROK     - success
905  *         RFAILED - failure
906  *
907  * ****************************************************************/
908 uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
909 {
910    uint8_t  lcId = 0;
911    uint16_t ueIdx = 0;
912    uint16_t slot;
913 #ifdef NR_TDD
914    uint16_t slotIdx = 0;
915 #endif
916    SchUeCb *ueCb = NULLP;
917    SchCellCb *cell = NULLP;
918    SchDlSlotInfo *schDlSlotInfo = NULLP;
919    Inst  inst = pst->dstInst-SCH_INST_START;
920
921 #ifdef CALL_FLOW_DEBUG_LOG
922    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_DL_RLC_BO_INFO_TO_SCH\n");
923 #endif
924
925    DU_LOG("\nDEBUG  -->  SCH : Received RLC BO Status indication");
926    cell = schCb[inst].cells[inst];
927
928    if(cell == NULLP)
929    {
930       DU_LOG("\nERROR  -->  SCH : MacSchDlRlcBoInfo(): Cell does not exists");
931       return RFAILED;
932    }
933
934    GET_UE_IDX(dlBoInfo->crnti, ueIdx);
935    ueCb = &cell->ueCb[ueIdx-1];
936    lcId  = dlBoInfo->lcId;
937
938    if(lcId == SRB1_LCID || lcId == SRB2_LCID || lcId == SRB3_LCID || \
939          (lcId >= MIN_DRB_LCID && lcId <= MAX_DRB_LCID))
940    {
941       SET_ONE_BIT(ueIdx, cell->boIndBitMap);
942       ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
943    }
944    else if(lcId != SRB0_LCID)
945    {
946       DU_LOG("\nERROR  -->  SCH : Invalid LC Id %d in MacSchDlRlcBoInfo", lcId);
947       return RFAILED;
948    }
949
950    slot = (cell->slotInfo.slot + SCHED_DELTA + PHY_DELTA_DL + BO_DELTA) % cell->numSlots;
951 #ifdef NR_TDD
952    while(schGetSlotSymbFrmt(cell->slotFrmtBitMap, slot) != DL_SLOT)
953    {
954       slot = (slot + 1)%cell->numSlots;
955       slotIdx++;
956       if(slotIdx==cell->numSlots)
957       {
958          DU_LOG("\nERROR  -->  SCH : No DL Slot available");
959          return RFAILED;
960       }
961    }
962 #endif
963
964    schDlSlotInfo = cell->schDlSlotInfo[slot];
965
966    if(schDlSlotInfo == NULLP)
967    {
968       DU_LOG("\nERROR  -->  SCH : MacSchDlRlcBoInfo(): schDlSlotInfo does not exists");
969       return RFAILED;
970    }
971    SCH_ALLOC(schDlSlotInfo->dlMsgInfo, sizeof(DlMsgInfo));
972    if(schDlSlotInfo->dlMsgInfo == NULLP)
973    {
974       DU_LOG("\nERROR  -->  SCH : Memory allocation failed for dlMsgInfo");
975       schDlSlotInfo = NULL;
976       return RFAILED;
977    }
978    
979    schDlSlotInfo->dlMsgInfo->crnti = dlBoInfo->crnti;
980    schDlSlotInfo->dlMsgInfo->ndi = 1;
981    schDlSlotInfo->dlMsgInfo->harqProcNum = 0;
982    schDlSlotInfo->dlMsgInfo->dlAssignIdx = 0;
983    schDlSlotInfo->dlMsgInfo->pucchTpc = 0;
984    schDlSlotInfo->dlMsgInfo->pucchResInd = 0;
985    schDlSlotInfo->dlMsgInfo->harqFeedbackInd = 0;
986    schDlSlotInfo->dlMsgInfo->dciFormatId = 1;
987    if(lcId == SRB0_LCID)
988    {
989       schDlSlotInfo->dlMsgInfo->isMsg4Pdu = true;
990       schDlSlotInfo->dlMsgInfo->dlMsgPduLen = dlBoInfo->dataVolume;
991    }
992    return ROK;
993 }
994
995 /*******************************************************************
996  *
997  * @brief Processes BSR indiation from MAC
998  *
999  * @details
1000  *
1001  *    Function : MacSchBsr
1002  *
1003  *    Functionality:
1004  *       Processes DL BSR from MAC
1005  *
1006  * @params[in]    Pst pst
1007  *                UlBufferStatusRptInd bsrInd
1008  * @return ROK     - success
1009  *         RFAILED - failure
1010  *
1011  * ****************************************************************/
1012 uint8_t MacSchBsr(Pst *pst, UlBufferStatusRptInd *bsrInd)
1013 {
1014    Inst           schInst       = pst->dstInst-SCH_INST_START;
1015    SchCellCb      *cellCb       = NULLP;
1016    SchUeCb        *ueCb         = NULLP;
1017    uint8_t        lcgIdx;
1018
1019 #ifdef CALL_FLOW_DEBUG_LOG
1020    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SHORT_BSR\n");
1021 #endif
1022
1023    DU_LOG("\nDEBUG  -->  SCH : Received BSR");
1024    cellCb = schCb[schInst].cells[schInst];
1025    ueCb = schGetUeCb(cellCb, bsrInd->crnti);
1026
1027    /* store dataVolume per lcg in uecb */
1028    for(lcgIdx = 0; lcgIdx < bsrInd->numLcg; lcgIdx++)
1029    {
1030       ueCb->bsrInfo[lcgIdx].priority = 1; //TODO: determining LCG priority?
1031       ueCb->bsrInfo[lcgIdx].dataVol = bsrInd->dataVolInfo[lcgIdx].dataVol;
1032    }
1033    return ROK;
1034 }
1035
1036 /*******************************************************************
1037  *
1038  * @brief Processes SR UCI indication from MAC 
1039  *
1040  * @details
1041  *
1042  *    Function : MacSchSrUciInd
1043  *
1044  *    Functionality:
1045  *      Processes SR UCI indication from MAC
1046  *
1047  * @params[in] Post structure
1048  *             UCI Indication
1049  * @return ROK     - success
1050  *         RFAILED - failure
1051  *
1052  * ****************************************************************/
1053 uint8_t MacSchSrUciInd(Pst *pst, SrUciIndInfo *uciInd)
1054 {
1055    Inst  inst = pst->dstInst-SCH_INST_START;
1056
1057    SchUeCb   *ueCb; 
1058    SchCellCb *cellCb = schCb[inst].cells[inst];
1059
1060 #ifdef CALL_FLOW_DEBUG_LOG
1061    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_UCI_IND_TO_SCH\n");
1062 #endif
1063
1064    DU_LOG("\nDEBUG  -->  SCH : Received SR");
1065
1066    ueCb = schGetUeCb(cellCb, uciInd->crnti);
1067
1068    if(uciInd->numSrBits)
1069    {
1070       ueCb->srRcvd = true;
1071    }
1072    return ROK;
1073 }
1074 /**********************************************************************
1075   End of file
1076  **********************************************************************/