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