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