1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for scheduler fucntions
29 **********************************************************************/
32 @brief This file implements the schedulers main access to MAC layer code.
34 #include "common_def.h"
35 #include "du_app_mac_inf.h"
40 #include "rg_sch_inf.h"
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"
49 #include "sch_utils.h"
53 SchCellCfgCfmFunc SchCellCfgCfmOpts[] =
55 packSchCellCfgCfm, /* LC */
56 MacProcSchCellCfgCfm, /* TC */
57 packSchCellCfgCfm /* LWLC */
60 SchSliceCfgRspFunc SchSliceCfgRspOpts[] =
62 packSchSliceCfgRsp, /* LC */
63 MacProcSchSliceCfgRsp, /* TC */
64 packSchSliceCfgRsp /* LWLC */
68 SchSliceRecfgRspFunc SchSliceRecfgRspOpts[] =
70 packSchSliceRecfgRsp, /* LC */
71 MacProcSchSliceRecfgRsp, /* TC */
72 packSchSliceRecfgRsp /* LWLC */
76 * @brief Task Initiation function.
80 * Function : schActvInit
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.
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
90 * @param[in] Reason Reason.
94 uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason)
96 Inst inst = (instId - SCH_INST_START);
98 /* Initialize the MAC TskInit structure to zero */
99 memset ((uint8_t *)&schCb[inst], 0, sizeof(schCb));
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();
117 * @brief Scheduler instance Configuration Handler.
121 * Function : SchInstCfg
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.
127 * @param[in] RgCfg *cfg, the Configuaration information
129 * -# LCM_REASON_NOT_APPL
130 * -# LCM_REASON_INVALID_MSGTYPE
131 * -# LCM_REASON_MEM_NOAVAIL
133 uint8_t SchInstCfg(RgCfg *cfg, Inst dInst)
135 uint16_t ret = LCM_REASON_NOT_APPL;
136 Inst inst = (dInst - SCH_INST_START);
138 DU_LOG("\nDEBUG --> SCH : Entered SchInstCfg()");
139 /* Check if Instance Configuration is done already */
140 if (schCb[inst].schInit.cfgDone == TRUE)
142 return LCM_REASON_INVALID_MSGTYPE;
144 /* Update the Pst structure for LM interface */
145 memcpy(&schCb[inst].schInit.lmPst, &cfg->s.schInstCfg.genCfg.lmPst, sizeof(Pst));
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 +
152 schCb[inst].schInit.lmPst.event = EVTNONE;
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;
158 schCb[inst].genCfg.forceCntrlSrbBoOnPCel = cfg->s.schInstCfg.genCfg.forceCntrlSrbBoOnPCel;
159 schCb[inst].genCfg.isSCellActDeactAlgoEnable = cfg->s.schInstCfg.genCfg.isSCellActDeactAlgoEnable;
161 schCb[inst].genCfg.startCellId = cfg->s.schInstCfg.genCfg.startCellId;
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;
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)
173 DU_LOG("\nERROR --> SCH : SchInstCfg(): Failed to "
175 return (LCM_REASON_MEM_NOAVAIL);
178 /* Set Config done in TskInit */
179 schCb[inst].schInit.cfgDone = TRUE;
180 DU_LOG("\nINFO --> SCH : Scheduler gen config done");
186 * @brief Layer Manager Configuration request handler.
190 * Function : SchProcGenCfgReq
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.
198 * @param[in] Pst *pst, the post structure
199 * @param[in] RgMngmt *cfg, the configuration parameter's structure
203 uint8_t SchProcGenCfgReq(Pst *pst, RgMngmt *cfg)
205 uint8_t ret = LCM_PRIM_OK;
206 uint16_t reason = LCM_REASON_NOT_APPL;
210 #ifdef CALL_FLOW_DEBUG_LOG
211 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : GENERAL_CFG_REQ\n");
214 if(pst->dstInst < SCH_INST_START)
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);
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);
226 memset(&cfm, 0, sizeof(RgMngmt));
233 cfm.hdr.elmId.elmnt = cfg->hdr.elmId.elmnt;
234 switch(cfg->hdr.elmId.elmnt)
237 reason = SchInstCfg(&cfg->t.cfg,pst->dstInst );
241 reason = LCM_REASON_INVALID_ELMNT;
242 DU_LOG("\nERROR --> SCH : Invalid Elmnt=%d", cfg->hdr.elmId.elmnt);
246 if (reason != LCM_REASON_NOT_APPL)
251 cfm.cfm.status = ret;
252 cfm.cfm.reason = reason;
254 SchSendCfgCfm(&cfmPst, &cfm);
255 /* SCH_FREE(pst->region, pst->pool, (Data *)cfg, sizeof(RgMngmt)); */
258 }/*-- SchProcGenCfgReq --*/
261 * @brief slot indication from MAC to SCH.
265 * Function : MacSchSlotInd
267 * This API is invoked by PHY to indicate slot indication to Scheduler for
270 * @param[in] Pst *pst
271 * @param[in] SlotTimingInfo *slotInd
276 uint8_t MacSchSlotInd(Pst *pst, SlotTimingInfo *slotInd)
278 Inst inst = pst->dstInst-SCH_INST_START;
280 #ifdef CALL_FLOW_DEBUG_LOG
281 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SLOT_IND_TO_SCH\n");
284 schProcessSlotInd(slotInd, inst);
287 } /* MacSchSlotInd */
289 /*******************************************************************
291 * @brief Processes Rach indication from MAC
295 * Function : MacSchRachInd
298 * Processes Rach indication from MAC
301 * @return ROK - success
304 * ****************************************************************/
305 uint8_t MacSchRachInd(Pst *pst, RachIndInfo *rachInd)
307 Inst inst = pst->dstInst-SCH_INST_START;
309 #ifdef CALL_FLOW_DEBUG_LOG
310 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_RACH_IND_TO_SCH\n");
313 DU_LOG("\nINFO --> SCH : Received Rach indication");
314 schProcessRachInd(rachInd, inst);
318 /*******************************************************************
320 * @brief Processes CRC indication from MAC
324 * Function : MacSchCrcInd
327 * Processes CRC indication from MAC
329 * @params[in] Post structure
331 * @return ROK - success
334 * ****************************************************************/
335 uint8_t MacSchCrcInd(Pst *pst, CrcIndInfo *crcInd)
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");
342 schProcessCrcInd(crcInd, inst);
348 *@brief Returns TDD periodicity in micro seconds
352 * Function : schGetPeriodicityInMsec
354 * This API retunrs TDD periodicity in micro seconds
356 * @param[in] DlUlTxPeriodicity
357 * @return periodicityInMsec
360 uint16_t schGetPeriodicityInMsec(DlUlTxPeriodicity tddPeriod)
362 uint16_t periodicityInMsec = 0;
365 case TX_PRDCTY_MS_0P5:
367 periodicityInMsec = 500;
370 case TX_PRDCTY_MS_0P625:
372 periodicityInMsec = 625;
377 periodicityInMsec = 1000;
380 case TX_PRDCTY_MS_1P25:
382 periodicityInMsec = 1250;
387 periodicityInMsec = 2000;
390 case TX_PRDCTY_MS_2P5:
392 periodicityInMsec = 2500;
397 periodicityInMsec = 5000;
400 case TX_PRDCTY_MS_10:
402 periodicityInMsec = 10000;
407 DU_LOG("\nERROR --> SCH : Invalid DlUlTxPeriodicity:%d", tddPeriod);
411 return periodicityInMsec;
416 * @brief init TDD slot config
420 * Function : schInitTddSlotCfg
422 * This API is invoked after receiving schCellCfg
424 * @param[in] schCellCb *cell
425 * @param[in] SchCellCfg *schCellCfg
428 void schInitTddSlotCfg(SchCellCb *cell, SchCellCfg *schCellCfg)
430 uint16_t periodicityInMicroSec = 0;
431 int8_t slotIdx, symbIdx;
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--)
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)
444 switch(schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx])
448 /*BitMap to be set to 00 */
449 cell->slotFrmtBitMap = (cell->slotFrmtBitMap<<2);
454 /*BitMap to be set to 01 */
455 cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (UL_SLOT));
459 DU_LOG("\nERROR --> SCH : Invalid slot Config in schInitTddSlotCfg");
463 /* slot config is flexible. First set slotBitMap to 10 */
464 cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (FLEXI_SLOT));
466 /* Now set symbol bitmap */
467 for(symbIdx = MAX_SYMB_PER_SLOT-1; symbIdx >= 0; symbIdx--)
469 switch(schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx])
473 /*symbol BitMap to be set to 00 */
474 cell->symbFrmtBitMap = (cell->symbFrmtBitMap<<2);
479 /*symbol BitMap to be set to 01 */
480 cell->symbFrmtBitMap = ((cell->symbFrmtBitMap<<2) | (UL_SLOT));
485 /*symbol BitMap to be set to 10 */
486 cell->symbFrmtBitMap = ((cell->symbFrmtBitMap<<2) | (FLEXI_SLOT));
490 DU_LOG("\nERROR --> SCH : Invalid slot Config in schInitTddSlotCfg");
498 * @brief Fill SSB start symbol
502 * Function : fillSsbStartSymb
504 * This API stores SSB start index per beam
506 * @param[in] SchCellCb *cellCb
511 void fillSsbStartSymb(SchCellCb *cellCb)
513 uint8_t cnt, scs, symbIdx, ssbStartSymbArr[SCH_MAX_SSB_BEAM];
515 scs = cellCb->cellCfg.ssbSchCfg.scsCommon;
517 memset(ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
519 /* Determine value of "n" based on Section 4.1 of 3GPP TS 38.213 */
524 if(cellCb->cellCfg.dlFreq <= 300000)
525 cnt = 2;/* n = 0, 1 */
527 cnt = 4; /* n = 0, 1, 2, 3 */
528 for(uint8_t idx=0; idx<cnt; idx++)
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;
538 if(cellCb->cellCfg.dlFreq <= 300000)
541 cnt = 2; /* n = 0, 1 */
542 for(uint8_t idx=0; idx<cnt; idx++)
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;
553 DU_LOG("\nERROR --> SCH : SCS %d is currently not supported", scs);
555 memset(cellCb->ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
556 memcpy(cellCb->ssbStartSymbArr, ssbStartSymbArr, SCH_MAX_SSB_BEAM);
562 * @brief init cellCb based on cellCfg
566 * Function : schInitCellCb
568 * This API is invoked after receiving schCellCfg
570 * @param[in] schCellCb *cell
571 * @param[in] SchCellCfg *schCellCfg
576 uint8_t schInitCellCb(Inst inst, SchCellCfg *schCellCfg)
578 SchCellCb *cell= NULLP;
579 SCH_ALLOC(cell, sizeof(SchCellCb));
582 DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb");
586 cell->cellId = schCellCfg->cellId;
587 cell->instIdx = inst;
588 switch(schCellCfg->numerology)
590 case SCH_NUMEROLOGY_0:
592 cell->numSlots = SCH_MU0_NUM_SLOTS;
595 case SCH_NUMEROLOGY_1:
597 cell->numSlots = SCH_MU1_NUM_SLOTS;
600 case SCH_NUMEROLOGY_2:
602 cell->numSlots = SCH_MU2_NUM_SLOTS;
605 case SCH_NUMEROLOGY_3:
607 cell->numSlots = SCH_MU3_NUM_SLOTS;
610 case SCH_NUMEROLOGY_4:
612 cell->numSlots = SCH_MU4_NUM_SLOTS;
616 DU_LOG("\nERROR --> SCH : Numerology %d not supported", schCellCfg->numerology);
619 schInitTddSlotCfg(cell, schCellCfg);
622 SCH_ALLOC(cell->schDlSlotInfo, cell->numSlots * sizeof(SchDlSlotInfo*));
623 if(!cell->schDlSlotInfo)
625 DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb for schDlSlotInfo");
629 SCH_ALLOC(cell->schUlSlotInfo, cell->numSlots * sizeof(SchUlSlotInfo*));
630 if(!cell->schUlSlotInfo)
632 DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb for schUlSlotInfo");
636 for(uint8_t idx=0; idx<cell->numSlots; idx++)
638 SchDlSlotInfo *schDlSlotInfo;
639 SchUlSlotInfo *schUlSlotInfo;
642 SCH_ALLOC(schDlSlotInfo, sizeof(SchDlSlotInfo));
645 DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb");
650 SCH_ALLOC(schUlSlotInfo, sizeof(SchUlSlotInfo));
653 DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb");
657 schInitDlSlot(schDlSlotInfo);
658 schInitUlSlot(schUlSlotInfo);
660 cell->schDlSlotInfo[idx] = schDlSlotInfo;
661 cell->schUlSlotInfo[idx] = schUlSlotInfo;
664 cell->firstSsbTransmitted = false;
665 cell->firstSib1Transmitted = false;
666 fillSsbStartSymb(cell);
667 cmLListInit(&cell->ueToBeScheduled);
670 memset(cell->drxCb, 0, MAX_DRX_SIZE*sizeof(SchDrxCb));
672 schCb[inst].cells[inst] = cell;
674 DU_LOG("\nINFO --> SCH : Cell init completed for cellId:%d", cell->cellId);
680 * @brief Fill SIB1 configuration
684 * Function : fillSchSib1Cfg
686 * Fill SIB1 configuration
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
695 void fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots, SchSib1Cfg *sib1SchCfg, uint16_t pci, uint8_t offsetPointA)
697 uint8_t coreset0Idx = 0;
698 uint8_t searchSpace0Idx = 0;
699 //uint8_t ssbMuxPattern = 0;
701 uint8_t numSymbols = 0;
704 //uint8_t numSearchSpacePerSlot = 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};
712 PdcchCfg *pdcch = &(sib1SchCfg->sib1PdcchCfg);
713 PdschCfg *pdsch = &(sib1SchCfg->sib1PdschCfg);
714 BwpCfg *bwp = &(sib1SchCfg->bwp);
716 coreset0Idx = sib1SchCfg->coresetZeroIndex;
717 searchSpace0Idx = sib1SchCfg->searchSpaceZeroIndex;
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];
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];
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;
742 case BANDWIDTH_20MHZ:
744 bwp->freqAlloc.numPrb = TOTAL_PRB_20MHZ_MU0;
747 case BANDWIDTH_100MHZ:
749 bwp->freqAlloc.numPrb = TOTAL_PRB_100MHZ_MU1;
753 DU_LOG("\nERROR --> SCH : Bandwidth %d not supported", bandwidth);
756 bwp->freqAlloc.startPrb = 0;
757 bwp->subcarrierSpacing = 0; /* 15Khz */
758 bwp->cyclicPrefix = 0; /* normal */
760 /* fill the PDCCH PDU */
761 pdcch->coresetCfg.coreSetSize = numRbs;
762 pdcch->coresetCfg.startSymbolIndex = firstSymbol;
763 pdcch->coresetCfg.durationSymbols = numSymbols;
765 /* Fill Bitmap for PRBs in coreset */
766 fillCoresetFeqDomAllocMap(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
767 covertFreqDomRsrcMapToIAPIFormat(FreqDomainResource, pdcch->coresetCfg.freqDomainResource);
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 */
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;
792 /* fill the PDSCH PDU */
794 pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
795 pdsch->rnti = 0xFFFF; /* SI-RNTI */
797 pdsch->numCodewords = 1;
798 for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
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;
808 pdsch->dataScramblingId = pci;
809 pdsch->numLayers = 1;
810 pdsch->transmissionScheme = 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;
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;
842 * @brief cell config from MAC to SCH.
846 * Function : macSchCellCfgReq
848 * This API is invoked by MAC to send cell config to SCH
850 * @param[in] Pst *pst
851 * @param[in] SchCellCfg *schCellCfg
856 uint8_t SchHdlCellCfgReq(Pst *pst, SchCellCfg *schCellCfg)
860 SchCellCfgCfm schCellCfgCfm;
862 Inst inst = pst->dstInst - SCH_INST_START;
863 uint8_t coreset0Idx = 0;
866 uint8_t freqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
867 SchPdschConfig pdschCfg;
869 #ifdef CALL_FLOW_DEBUG_LOG
870 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SCH_CELL_CFG\n");
873 schInitCellCb(inst, schCellCfg);
874 cellCb = schCb[inst].cells[inst]; //cells is of MAX_CELLS, why inst
875 cellCb->macInst = pst->srcInst;
877 /* derive the SIB1 config parameters */
878 fillSchSib1Cfg(schCellCfg->numerology, schCellCfg->bandwidth, cellCb->numSlots,
879 &(schCellCfg->sib1SchCfg), schCellCfg->phyCellId,
880 schCellCfg->ssbSchCfg.ssbOffsetPointA);
883 memcpy(&cellCb->cellCfg, schCellCfg, sizeof(SchCellCfg));
884 schProcPagingCfg(cellCb);
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);
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);
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;
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;
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;
915 schCellCfgCfm.cellId = schCellCfg->cellId;
916 schCellCfgCfm.rsp = RSP_OK;
918 ret = (*SchCellCfgCfmOpts[rspPst.selector])(&rspPst, &schCellCfgCfm);
923 /*******************************************************************
925 * @brief Processes DL RLC BO info from MAC
929 * Function : MacSchDlRlcBoInfo
932 * Processes DL RLC BO info from MAC
935 * @return ROK - success
938 * ****************************************************************/
939 uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
943 bool isLcIdValid = false;
944 SchUeCb *ueCb = NULLP;
945 SchCellCb *cell = NULLP;
946 Inst inst = pst->dstInst-SCH_INST_START;
948 #ifdef CALL_FLOW_DEBUG_LOG
949 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_DL_RLC_BO_INFO_TO_SCH\n");
951 DU_LOG("\nDEBUG --> SCH : Received RLC BO Status indication LCId [%d] BO [%d]", dlBoInfo->lcId, dlBoInfo->dataVolume);
952 cell = schCb[inst].cells[inst];
956 DU_LOG("\nERROR --> SCH : MacSchDlRlcBoInfo(): Cell does not exists");
960 GET_UE_ID(dlBoInfo->crnti, ueId);
961 ueCb = &cell->ueCb[ueId-1];
962 if(ueCb->ueCfg.dataTransmissionAction == STOP_DATA_TRANSMISSION)
964 DU_LOG("INFO --> SCH : DL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId);
968 lcId = dlBoInfo->lcId;
969 CHECK_LCID(lcId, isLcIdValid);
970 if(isLcIdValid == FALSE)
972 DU_LOG("ERROR --> SCH: LCID:%d is not valid", lcId);
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)
981 /* TODO : Check the LC is Dedicated or default and accordingly LCList
986 if(lcId == SRB0_LCID)
988 cell->raCb[ueId -1].msg4recvd = true;
989 cell->raCb[ueId -1].dlMsgPduLen = dlBoInfo->dataVolume;
993 /* TODO : These part of changes will be corrected during DL scheduling as
995 SET_ONE_BIT(ueId, cell->boIndBitMap);
996 if(ueCb->dlInfo.dlLcCtxt[lcId].lcId == lcId)
998 ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
1002 DU_LOG("ERROR --> SCH: LCID:%d is not configured in SCH Cb",lcId);
1006 /* Adding UE Id to list of pending UEs to be scheduled */
1007 addUeToBeScheduled(cell, ueId);
1011 /*******************************************************************
1013 * @brief Processes BSR indiation from MAC
1017 * Function : MacSchBsr
1020 * Processes DL BSR from MAC
1022 * @params[in] Pst pst
1023 * UlBufferStatusRptInd bsrInd
1024 * @return ROK - success
1027 * ****************************************************************/
1028 uint8_t MacSchBsr(Pst *pst, UlBufferStatusRptInd *bsrInd)
1030 Inst schInst = pst->dstInst-SCH_INST_START;
1031 SchCellCb *cellCb = NULLP;
1032 SchUeCb *ueCb = NULLP;
1035 #ifdef CALL_FLOW_DEBUG_LOG
1036 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SHORT_BSR\n");
1039 DU_LOG("\nDEBUG --> SCH : Received BSR");
1042 DU_LOG("\nERROR --> SCH : BSR Ind is empty");
1045 cellCb = schCb[schInst].cells[schInst];
1048 DU_LOG("\nERROR --> SCH : CellCb is empty");
1051 ueCb = schGetUeCb(cellCb, bsrInd->crnti);
1055 DU_LOG("\nERROR --> SCH : UeCB is empty");
1059 if(ueCb->ueCfg.dataTransmissionAction == STOP_DATA_TRANSMISSION)
1061 DU_LOG("\nINFO --> SCH: UL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId);
1065 ueCb->bsrRcvd = true;
1066 /* store dataVolume per lcg in uecb */
1067 for(lcgIdx = 0; lcgIdx < bsrInd->numLcg; lcgIdx++)
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;
1073 /* Adding UE Id to list of pending UEs to be scheduled */
1074 addUeToBeScheduled(cellCb, ueCb->ueId);
1078 /*******************************************************************
1080 * @brief Processes SR UCI indication from MAC
1084 * Function : MacSchSrUciInd
1087 * Processes SR UCI indication from MAC
1089 * @params[in] Post structure
1091 * @return ROK - success
1094 * ****************************************************************/
1095 uint8_t MacSchSrUciInd(Pst *pst, SrUciIndInfo *uciInd)
1097 Inst inst = pst->dstInst-SCH_INST_START;
1100 SchCellCb *cellCb = schCb[inst].cells[inst];
1102 #ifdef CALL_FLOW_DEBUG_LOG
1103 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_UCI_IND_TO_SCH\n");
1106 DU_LOG("\nDEBUG --> SCH : Received SR");
1108 ueCb = schGetUeCb(cellCb, uciInd->crnti);
1110 if(ueCb->state == SCH_UE_STATE_INACTIVE)
1112 DU_LOG("\nERROR --> SCH : Crnti %d is inactive", uciInd->crnti);
1115 if(ueCb->ueCfg.dataTransmissionAction == STOP_DATA_TRANSMISSION)
1117 DU_LOG("\nINFO --> SCH: UL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId);
1120 if(uciInd->numSrBits)
1122 ueCb->srRcvd = true;
1123 /* Adding UE Id to list of pending UEs to be scheduled */
1124 addUeToBeScheduled(cellCb, ueCb->ueId);
1129 /*******************************************************************
1131 * @brief Processes DL HARQ indication from MAC
1135 * Function : MacSchDlHarqInd
1138 * Processes DL HARQ indication from MAC
1140 * @params[in] Post structure
1141 * DL HARQ Indication
1142 * @return ROK - success
1145 * ****************************************************************/
1146 uint8_t MacSchDlHarqInd(Pst *pst, DlHarqInd *dlHarqInd)
1148 Inst inst = pst->dstInst-SCH_INST_START;
1150 SchCellCb *cellCb = schCb[inst].cells[inst];
1152 #ifdef CALL_FLOW_DEBUG_LOG
1153 DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_DL_HARQ_IND_TO_SCH\n");
1156 DU_LOG("\nDEBUG --> SCH : Received HARQ");
1158 ueCb = schGetUeCb(cellCb, dlHarqInd->crnti);
1160 if(ueCb->state == SCH_UE_STATE_INACTIVE)
1162 DU_LOG("\nERROR --> SCH : Crnti %d is inactive", dlHarqInd->crnti);
1166 schUpdateHarqFdbk(ueCb, dlHarqInd->numHarq, dlHarqInd->harqPayload, &dlHarqInd->slotInd);
1171 /*******************************************************************
1173 * @brief Allocates requested PRBs for DL
1177 * Function : allocatePrbDl
1180 * Allocates requested PRBs in DL
1181 * Keeps track of allocated PRB (using bitmap) and remaining PRBs
1183 * @params[in] prbAlloc table
1189 * @return ROK - success
1192 * ****************************************************************/
1193 uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \
1194 uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
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;
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)
1208 /* Check if SSB/SIB1 is also scheduled in this slot */
1209 ssbOccasion = schCheckSsbOcc(cell, slotTime);
1210 sib1Occasion = schCheckSib1Occ(cell, slotTime);
1212 if(ssbOccasion && sib1Occasion)
1214 broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
1215 broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1217 else if(ssbOccasion)
1219 broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
1220 broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB -1;
1222 else if(sib1Occasion)
1224 broadcastPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
1225 broadcastPrbEnd = broadcastPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1228 /* Iterate through all free PRB blocks */
1229 freePrbNode = prbAlloc->freePrbBlockList.first;
1232 freePrbBlock = (FreePrbBlock *)freePrbNode->node;
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)))
1240 /* Implmentation is done such that highest-numbered free-RB is allocated first */
1241 if((freePrbBlock->endPrb > broadcastPrbEnd) && ((freePrbBlock->endPrb - broadcastPrbEnd) >= numPrb))
1243 /* If sufficient free PRBs are available above bradcast message then,
1244 * endPrb = freePrbBlock->endPrb
1245 * startPrb = endPrb - numPrb +1;
1247 *startPrb = freePrbBlock->endPrb - numPrb +1;
1250 else if((broadcastPrbStart > freePrbBlock->startPrb) && ((broadcastPrbStart - freePrbBlock->startPrb) >= numPrb))
1252 /* If free PRBs are available below broadcast message then,
1253 * endPrb = broadcastPrbStart - 1
1254 * startPrb = endPrb - numPrb +1
1256 *startPrb = broadcastPrbStart - numPrb;
1261 freePrbNode = freePrbNode->next;
1267 /* Check if requested number of blocks can be allocated from the current block */
1268 if (freePrbBlock->numFreePrb < numPrb)
1270 freePrbNode = freePrbNode->next;
1273 *startPrb = freePrbBlock->endPrb - numPrb +1;
1278 /* If no free block can be used to allocated request number of RBs */
1279 if(*startPrb == MAX_NUM_RB)
1283 /* If startPrb is known already, check if requested PRBs are available for allocation */
1286 freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
1289 DU_LOG("\nERROR --> SCH: Requested DL PRB unavailable");
1294 /* Update bitmap to allocate PRBs */
1295 for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
1297 if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
1299 DU_LOG("\nERROR --> SCH: fillPrbBitmap() failed for symbol [%d] in DL", symbol);
1304 /* Update the remaining number for free PRBs */
1305 removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
1310 /*******************************************************************
1312 * @brief Allocates requested PRBs for UL
1316 * Function : allocatePrbUl
1319 * Allocates requested PRBs in UL
1320 * Keeps track of allocated PRB (using bitmap) and remaining PRBs
1322 * @params[in] prbAlloc table
1328 * @return ROK - success
1331 * ****************************************************************/
1332 uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \
1333 uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
1336 uint16_t prachStartPrb, prachNumPrb, prachEndPrb;
1337 bool isPrachOccasion;
1338 FreePrbBlock *freePrbBlock = NULLP;
1339 CmLList *freePrbNode = NULLP;
1340 SchPrbAlloc *prbAlloc = NULLP;
1344 DU_LOG("\nERROR --> SCH : allocatePrbUl(): Received cellCb is null");
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)
1353 /* Check if PRACH is also scheduled in this slot */
1354 isPrachOccasion = schCheckPrachOcc(cell, slotTime);
1357 prachStartPrb = cell->cellCfg.schRachCfg.msg1FreqStart;
1358 prachNumPrb = schCalcPrachNumRb(cell);
1359 prachEndPrb = prachStartPrb + prachNumPrb -1;
1362 /* Iterate through all free PRB blocks */
1363 freePrbNode = prbAlloc->freePrbBlockList.first;
1366 freePrbBlock = (FreePrbBlock *)freePrbNode->node;
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)))
1374 /* Implmentation is done such that highest-numbered free-RB is allocated first */
1375 if((freePrbBlock->endPrb > prachEndPrb) && ((freePrbBlock->endPrb - prachEndPrb) >= numPrb))
1377 /* If sufficient free PRBs are available above PRACH message then,
1378 * endPrb = freePrbBlock->endPrb
1379 * startPrb = endPrb - numPrb +1;
1381 *startPrb = freePrbBlock->endPrb - numPrb +1;
1384 else if((prachStartPrb > freePrbBlock->startPrb) && ((prachStartPrb - freePrbBlock->startPrb) >= numPrb))
1386 /* If free PRBs are available below PRACH message then,
1387 * endPrb = prachStartPrb - 1
1388 * startPrb = endPrb - numPrb +1
1390 *startPrb = prachStartPrb - numPrb;
1395 freePrbNode = freePrbNode->next;
1401 /* Check if requested number of PRBs can be allocated from currect block */
1402 if(freePrbBlock->numFreePrb < numPrb)
1404 freePrbNode = freePrbNode->next;
1407 *startPrb = freePrbBlock->endPrb - numPrb +1;
1412 /* If no free block can be used to allocated requested number of RBs */
1413 if(*startPrb == MAX_NUM_RB)
1418 /* If startPrb is known already, check if requested PRBs are available for allocation */
1419 freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
1422 DU_LOG("\nERROR --> SCH: Requested UL PRB unavailable");
1427 /* Update bitmap to allocate PRBs */
1428 for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
1430 if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
1432 DU_LOG("\nERROR --> SCH: fillPrbBitmap() failed for symbol [%d] in UL", symbol);
1437 /* Update the remaining number for free PRBs */
1438 removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
1443 /*******************************************************************
1445 * @brief Add UE to ueToBeScheduled List
1449 * Function : addUeToBeScheduled
1452 * Search if UE entry present in the list
1454 * If no, add UE to the list
1456 * @params[in] Cell control block
1457 * Ue Idx to be added
1459 * @return ROK - success
1462 * ****************************************************************/
1463 uint8_t addUeToBeScheduled(SchCellCb *cell, uint8_t ueIdToAdd)
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;
1473 ueId = (uint8_t *)node->node;
1474 if(*ueId == ueIdToAdd)
1479 /* If UE entry not present already, add UE to the end of ueToBeScheduled list */
1480 SCH_ALLOC(ueId, sizeof(uint8_t));
1483 DU_LOG("\nERROR --> SCH : Memory allocation failure in addUeToBeScheduled");
1487 if(addNodeToLList(&cell->ueToBeScheduled, ueId, NULLP) != ROK)
1489 DU_LOG("\nERROR --> SCH : Failed to add ueId [%d] to cell->ueToBeScheduled list", *ueId);
1495 /*******************************************************************************
1497 * @brief Try to find Best Free Block with Max Num PRB
1501 * Function : searchLargestFreeBlock
1504 * Finds the FreeBlock with MaxNum of FREE PRB considering SSB/SIB1 ocassions.
1506 * @params[in] I/P > prbAlloc table (FreeBlock list)
1507 * I/P > Slot timing Info
1509 * I/P > Direction (UL/DL)
1512 * @return Max Number of Free PRB
1513 * If 0, then no Suitable Free Block
1515 * ********************************************************************************/
1517 uint16_t searchLargestFreeBlock(SchCellCb *cell, SlotTimingInfo slotTime,uint16_t *startPrb, Direction dir)
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;
1525 *startPrb = 0; /*Initialize the StartPRB to zero*/
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*/
1532 SchDlSlotInfo *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
1533 PduTxOccsaion ssbOccasion=0, sib1Occasion=0;
1535 prbAlloc = &schDlSlotInfo->prbAlloc;
1537 ssbOccasion = schCheckSsbOcc(cell, slotTime);
1538 sib1Occasion = schCheckSib1Occ(cell, slotTime);
1540 checkOccasion = TRUE;
1541 if(ssbOccasion && sib1Occasion)
1543 reservedPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
1544 reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB + \
1545 cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1547 else if(ssbOccasion)
1549 reservedPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
1550 reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB -1;
1552 else if(sib1Occasion)
1554 reservedPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
1555 reservedPrbEnd = reservedPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1559 checkOccasion = FALSE;
1562 else if(dir == DIR_UL)
1564 prbAlloc = &cell->schUlSlotInfo[slotTime.slot]->prbAlloc;
1566 /* Check if PRACH is also scheduled in this slot */
1567 checkOccasion = schCheckPrachOcc(cell, slotTime);
1570 reservedPrbStart = cell->cellCfg.schRachCfg.msg1FreqStart;
1571 reservedPrbEnd = reservedPrbStart + (schCalcPrachNumRb(cell)) -1;
1576 DU_LOG("\nERROR --> SCH: Invalid Direction!");
1577 return (maxFreePRB);
1580 freePrbNode = prbAlloc->freePrbBlockList.first;
1583 freePrbBlock = (FreePrbBlock *)freePrbNode->node;
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)
1590 freePrbNode = freePrbNode->next;
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 */
1597 ((reservedPrbStart >= freePrbBlock->startPrb) && (reservedPrbStart <= freePrbBlock->endPrb)) && \
1598 ((reservedPrbEnd >= freePrbBlock->startPrb) && (reservedPrbEnd <= freePrbBlock->endPrb)))
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))
1605 /* If sufficient free PRBs are available above reserved message*/
1606 *startPrb = reservedPrbEnd + 1;
1607 maxFreePRB = (freePrbBlock->endPrb - reservedPrbEnd);
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))
1612 /* If free PRBs are available below reserved message*/
1613 *startPrb = freePrbBlock->startPrb;
1614 maxFreePRB = (reservedPrbStart - freePrbBlock->startPrb);
1619 if(maxFreePRB < freePrbBlock->numFreePrb)
1621 *startPrb = freePrbBlock->startPrb;
1622 maxFreePRB = freePrbBlock->numFreePrb;
1626 freePrbNode = freePrbNode->next;
1631 /*******************************************************************************
1633 * @brief This function is used to send Slice Cfg rsp to MAC
1637 * Function : SchSendSliceCfgRspToMac
1640 * function is used to send Slice Cfg rsp to MAC
1642 * @params[in] Pst *pst, SchSliceCfgRsp sliceCfgRsp
1646 * ********************************************************************************/
1647 void SchSendSliceCfgRspToMac(Inst inst, SchSliceCfgRsp sliceCfgRsp)
1651 memset(&rspPst, 0, sizeof(Pst));
1652 FILL_PST_SCH_TO_MAC(rspPst, inst);
1653 rspPst.event = EVENT_SLICE_CFG_RSP_TO_MAC;
1655 SchSliceCfgRspOpts[rspPst.selector](&rspPst, &sliceCfgRsp);
1658 /*******************************************************************************
1660 * @brief fill slice configuration response
1664 * Function : fillSliceCfgRsp
1667 * fill slice configuration response
1669 * @params[in] SchCellCb, SchSliceCfgReq, SchSliceCfgRsp,uint8_t count
1675 * ********************************************************************************/
1676 uint8_t fillSliceCfgRsp(bool sliceRecfg, SchSliceCfg *storedSliceCfg, SchCellCb *cellCb, SchSliceCfgReq *schSliceCfgReq, SchSliceCfgRsp *schSliceCfgRsp, uint8_t *count)
1678 bool sliceFound = false;
1679 uint8_t cfgIdx = 0, sliceIdx = 0;
1681 schSliceCfgRsp->numSliceCfgRsp = schSliceCfgReq->numOfConfiguredSlice;
1682 SCH_ALLOC(schSliceCfgRsp->listOfSliceCfgRsp, schSliceCfgRsp->numSliceCfgRsp * sizeof(SliceRsp*));
1683 if(schSliceCfgRsp->listOfSliceCfgRsp == NULLP)
1685 DU_LOG("\nERROR --> SCH : Memory allocation failed at fillSliceCfgRsp");
1689 for(cfgIdx = 0; cfgIdx<schSliceCfgRsp->numSliceCfgRsp ; cfgIdx++)
1692 /* Here comparing the slice cfg request with the slice stored in cellCfg */
1693 if(sliceRecfg != true)
1695 for(sliceIdx = 0; sliceIdx<cellCb->cellCfg.plmnInfoList.numSliceSupport; sliceIdx++)
1697 if(!memcmp(&schSliceCfgReq->listOfConfirguration[cfgIdx]->snssai, cellCb->cellCfg.plmnInfoList.snssai[sliceIdx], sizeof(Snssai)))
1707 /* Here comparing the slice cfg request with the slice stored in SchDb */
1708 if(storedSliceCfg->listOfConfirguration)
1710 for(sliceIdx = 0; sliceIdx<storedSliceCfg->numOfSliceConfigured; sliceIdx++)
1712 if(!memcmp(&schSliceCfgReq->listOfConfirguration[cfgIdx]->snssai, &storedSliceCfg->listOfConfirguration[sliceIdx]->snssai,\
1723 SCH_ALLOC(schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx], sizeof(SliceRsp));
1724 if(schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx] == NULLP)
1726 DU_LOG("\nERROR --> SCH : Failed to allocate memory in fillSliceCfgRsp");
1731 schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->snssai = schSliceCfgReq->listOfConfirguration[cfgIdx]->snssai;
1732 if(sliceFound == true)
1733 schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->rsp = RSP_OK;
1736 schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->rsp = RSP_NOK;
1737 schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->cause = SLICE_NOT_FOUND;
1743 /*******************************************************************************
1745 * @brief This function is used to store the slice configuration Sch DB
1749 * Function : addSliceCfgInSchDb
1752 * function is used to store the slice configuration Sch DB
1754 * @params[in] SchSliceCfg *storeSliceCfg, SchSliceCfgReq *cfgReq,
1755 * SchSliceCfgRsp cfgRsp, uint8_t count
1761 * ********************************************************************************/
1762 uint8_t addSliceCfgInSchDb(SchSliceCfg *storeSliceCfg, SchSliceCfgReq *cfgReq, SchSliceCfgRsp cfgRsp, uint8_t count)
1764 uint8_t cfgIdx = 0, sliceIdx = 0;
1768 storeSliceCfg->numOfSliceConfigured = count;
1769 SCH_ALLOC(storeSliceCfg->listOfConfirguration, storeSliceCfg->numOfSliceConfigured * sizeof(SchRrmPolicyOfSlice*));
1770 if(storeSliceCfg->listOfConfirguration == NULLP)
1772 DU_LOG("\nERROR --> SCH : Failed to allocate memory in addSliceCfgInSchDb");
1776 for(cfgIdx = 0; cfgIdx<storeSliceCfg->numOfSliceConfigured; cfgIdx++)
1778 if(cfgRsp.listOfSliceCfgRsp[cfgIdx]->rsp == RSP_OK)
1780 SCH_ALLOC(storeSliceCfg->listOfConfirguration[sliceIdx], sizeof(SchRrmPolicyOfSlice));
1781 if(storeSliceCfg->listOfConfirguration[sliceIdx] == NULLP)
1783 DU_LOG("\nERROR --> SCH : Failed to allocate memory in addSliceCfgInSchDb");
1787 SCH_ALLOC(storeSliceCfg->listOfConfirguration[sliceIdx]->rrmPolicyRatioInfo, sizeof(SchRrmPolicyRatio));
1788 if(storeSliceCfg->listOfConfirguration[sliceIdx]->rrmPolicyRatioInfo == NULLP)
1790 DU_LOG("\nERROR --> SCH : Failed to allocate memory in addSliceCfgInSchDb");
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));
1804 /*******************************************************************************
1806 * @brief This function is used to free the slice cfg and re cfg request pointer
1810 * Function : freeSchSliceCfgReq
1813 * function is used to free the slice cfg and re cfg request pointer
1815 * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1820 * ********************************************************************************/
1821 void freeSchSliceCfgReq(SchSliceCfgReq *sliceCfgReq)
1827 if(sliceCfgReq->numOfConfiguredSlice)
1829 for(cfgIdx = 0; cfgIdx<sliceCfgReq->numOfConfiguredSlice; cfgIdx++)
1831 if(sliceCfgReq->listOfConfirguration[cfgIdx])
1833 SCH_FREE(sliceCfgReq->listOfConfirguration[cfgIdx]->rrmPolicyRatioInfo, sizeof(SchRrmPolicyRatio));
1834 SCH_FREE(sliceCfgReq->listOfConfirguration[cfgIdx], sizeof(SchRrmPolicyOfSlice));
1837 SCH_FREE(sliceCfgReq->listOfConfirguration, sliceCfgReq->numOfConfiguredSlice * sizeof(SchRrmPolicyOfSlice*));
1839 SCH_FREE(sliceCfgReq, sizeof(SchSliceCfgReq));
1842 /*******************************************************************************
1844 * @brief This function is used to store the slice configuration Sch DB
1848 * Function : MacSchSliceCfgReq
1851 * function is used to store the slice configuration Sch DB
1853 * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1859 * ********************************************************************************/
1860 uint8_t MacSchSliceCfgReq(Pst *pst, SchSliceCfgReq *schSliceCfgReq)
1863 Inst inst = pst->dstInst - SCH_INST_START;
1864 SchSliceCfgRsp sliceCfgRsp;
1866 DU_LOG("\nINFO --> SCH : Received Slice Cfg request from MAC");
1869 if(schSliceCfgReq->listOfConfirguration)
1871 /* filling the slice configuration response of each slice */
1872 if(fillSliceCfgRsp(false, NULLP, schCb[inst].cells[0], schSliceCfgReq, &sliceCfgRsp, &count) != ROK)
1874 DU_LOG("\nERROR --> SCH : Failed to fill the slice cfg rsp");
1878 if(addSliceCfgInSchDb(&schCb[inst].sliceCfg, schSliceCfgReq, sliceCfgRsp, count) != ROK)
1880 DU_LOG("\nERROR --> SCH : Failed to add slice cfg in sch database");
1883 freeSchSliceCfgReq(schSliceCfgReq);
1884 SchSendSliceCfgRspToMac(inst, sliceCfgRsp);
1889 DU_LOG("\nERROR --> SCH : Received SchSliceCfgReq is NULL");
1894 /*******************************************************************************
1896 * @brief This function is used to store the slice reconfiguration Sch DB
1900 * Function : modifySliceCfgInSchDb
1903 * function is used to store the slice re configuration Sch DB
1905 * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1911 * ********************************************************************************/
1912 uint8_t modifySliceCfgInSchDb(SchSliceCfg *storeSliceCfg, SchSliceRecfgReq *recfgReq, SchSliceRecfgRsp recfgRsp, uint8_t count)
1914 uint8_t cfgIdx = 0, sliceIdx = 0;
1918 if(storeSliceCfg->listOfConfirguration == NULLP)
1920 DU_LOG("\nINFO --> SCH : Memory allocation failed in modifySliceCfgInSchDb");
1924 for(cfgIdx = 0; cfgIdx<recfgReq->numOfConfiguredSlice; cfgIdx++)
1926 if(recfgRsp.listOfSliceCfgRsp[cfgIdx]->rsp == RSP_OK)
1928 for(sliceIdx = 0; sliceIdx<storeSliceCfg->numOfSliceConfigured; sliceIdx++)
1930 if(!memcmp(&storeSliceCfg->listOfConfirguration[sliceIdx]->snssai, &recfgReq->listOfConfirguration[cfgIdx]->snssai, sizeof(Snssai)))
1932 memcpy(storeSliceCfg->listOfConfirguration[sliceIdx]->rrmPolicyRatioInfo, recfgReq->listOfConfirguration[cfgIdx]->rrmPolicyRatioInfo,
1933 sizeof(SchRrmPolicyRatio));
1940 freeSchSliceCfgReq(recfgReq);
1943 /*******************************************************************************
1945 * @brief This function is used to send Slice re Cfg rsp to MAC
1949 * Function : SchSendSliceRecfgRspToMac
1952 * function is used to send Slice re Cfg rsp to MAC
1954 * @params[in] Pst *pst, SchSliceRecfgRsp schSliceRecfgRsp
1958 * ********************************************************************************/
1959 void SchSendSliceRecfgRspToMac(Inst inst, SchSliceRecfgRsp schSliceRecfgRsp)
1963 memset(&rspPst, 0, sizeof(Pst));
1964 FILL_PST_SCH_TO_MAC(rspPst, inst);
1965 rspPst.event = EVENT_SLICE_RECFG_RSP_TO_MAC;
1967 SchSliceRecfgRspOpts[rspPst.selector](&rspPst, &schSliceRecfgRsp);
1969 /*******************************************************************************
1971 * @brief This function is used to store the slice reconfiguration Sch DB
1975 * Function : MacSchSliceRecfgReq
1978 * function is used to store the slice re configuration Sch DB
1980 * @params[in] Pst *pst, SchSliceRecfgReq *schSliceRecfgReq
1986 * ********************************************************************************/
1987 uint8_t MacSchSliceRecfgReq(Pst *pst, SchSliceRecfgReq *schSliceRecfgReq)
1990 Inst inst = pst->dstInst - SCH_INST_START;
1991 SchSliceRecfgRsp schSliceRecfgRsp;
1993 DU_LOG("\nINFO --> SCH : Received Slice ReCfg request from MAC");
1994 if(schSliceRecfgReq)
1996 if(schSliceRecfgReq->listOfConfirguration)
1998 /* filling the slice configuration response of each slice */
1999 if(fillSliceCfgRsp(true, &schCb[inst].sliceCfg, NULLP, schSliceRecfgReq, &schSliceRecfgRsp, &count) != ROK)
2001 DU_LOG("\nERROR --> SCH : Failed to fill sch slice cfg response");
2005 /* Modify the slice configuration stored in schCb */
2006 if(modifySliceCfgInSchDb(&schCb[inst].sliceCfg, schSliceRecfgReq, schSliceRecfgRsp, count) != ROK)
2008 DU_LOG("\nERROR --> SCH : Failed to modify slice cfg of SchDb");
2011 SchSendSliceRecfgRspToMac(inst, schSliceRecfgRsp);
2016 DU_LOG("\nERROR --> SCH : Received SchSliceRecfgReq is NULL");
2021 /****************************************************************************
2023 * @brief Stores the Paging Configuration from DU APP in CellCb
2027 * Function : schProcPagingParam
2030 * Process the Paging Configuration when FirstPDCCHMonitoring for
2031 * Paging Ocassion is not present.
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"
2041 * @params[in] SchCellCb *cell
2045 *************************************************************************/
2046 void schProcPagingCfg(SchCellCb *cell)
2048 PageCfg *pageCfgRcvd = NULL;
2051 pageCfgRcvd = &(cell->cellCfg.sib1SchCfg.pageCfg);
2053 if(pageCfgRcvd->poPresent == TRUE)
2055 /*Fetching first Pdcch Monitoring Occasion for SFN (i_s + 1)th*/
2056 for(i_sIdx = 0; i_sIdx < pageCfgRcvd->numPO; i_sIdx++)
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 )
2061 cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot++;
2064 cell->pageCb.pagMonOcc[i_sIdx].frameOffset = 0;
2070 schCfgPdcchMonOccOfPO(cell);
2074 /****************************************************************************
2076 * @brief Calculate PO if not present in Configuration
2080 * Function : schCfgPdcchMonOccOfPO
2082 * Functionality: In this function, PO are calculated i_s * S because
2083 * FirstPDCCHMonitoring_ForPO is not present.
2085 * @params[in] SchCellCb *cellCb
2089 *************************************************************************/
2090 void schCfgPdcchMonOccOfPO(SchCellCb *cell)
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;
2097 /*Starting with First Sfn and slot*/
2098 tmpTimingInfo.sfn = 0;
2099 tmpTimingInfo.slot = 0;
2101 pdcchTime = tmpTimingInfo;
2103 while(i_sIdx < nsValue)
2105 /*Increment frame Offset if PO falls on next SFN*/
2106 if(pdcchTime.sfn != tmpTimingInfo.sfn)
2110 pdcchTime = tmpTimingInfo;
2111 schIncrSlot(&(tmpTimingInfo), incr, cell->numSlots);
2115 cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pdcchTime.slot;
2116 cell->pageCb.pagMonOcc[i_sIdx].frameOffset = frameOffSet;
2122 if((cnt == totalNumSsb) && (i_sIdx < MAX_PO_PER_PF))
2124 cell->pageCb.pagMonOcc[i_sIdx].pagingOccSlot = pdcchTime.slot;
2125 cell->pageCb.pagMonOcc[i_sIdx].frameOffset = frameOffSet;
2133 /****************************************************************************
2135 * @brief Storing the paging information in SCH database
2139 * Function : schAddPagingIndtoList
2141 * Functionality: Storing the paging information in SCH database
2143 * @params[in] CmLListCp *storedPageList, CmLList *pageIndInfo
2145 * @return ROK - sucess
2148 *************************************************************************/
2149 uint8_t schAddPagingIndtoList(CmLListCp *storedPageList,void * pageIndInfo)
2151 CmLList *firstNodeOfList = NULLP;
2152 CmLList *currentNodeInfo = NULLP;
2153 SchPageInfo *tempNode = NULLP, *recvdNode = NULLP;
2155 recvdNode = (SchPageInfo*) pageIndInfo;
2156 CM_LLIST_FIRST_NODE(storedPageList,firstNodeOfList);
2158 SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
2159 if(!currentNodeInfo)
2161 DU_LOG("\nERROR --> SCH : schAddPagingIndtoList() : Memory allocation failed");
2165 currentNodeInfo->node = (PTR)pageIndInfo;
2166 while(firstNodeOfList)
2168 tempNode = (SchPageInfo*)(firstNodeOfList->node);
2169 if ((recvdNode->pageTxTime.slot < tempNode->pageTxTime.slot))
2171 cmLListInsCrnt(storedPageList, currentNodeInfo);
2174 else if ((recvdNode->pageTxTime.slot == tempNode->pageTxTime.slot))
2176 DU_LOG("\nERROR --> SCH : schAddPagingIndtoList() : Slot[%d] is already present in the list", recvdNode->pageTxTime.slot);
2181 CM_LLIST_NEXT_NODE(storedPageList, firstNodeOfList);
2185 if(!firstNodeOfList)
2187 cmLListAdd2Tail(storedPageList, currentNodeInfo);
2189 DU_LOG("\nDEBUG --> SCH : Paging information is stored successfully for PF:%d, Slot:%d",\
2190 recvdNode->pageTxTime.sfn, recvdNode->pageTxTime.slot);
2194 /****************************************************************************
2196 * @brief Process paging indication at SCH recevied form MAC
2200 * Function : MacSchPagingInd
2202 * Functionality: Process paging indication at SCH recevied form MAC
2204 * @params[in] Pst *pst, SchPageInd *pageInd
2208 *************************************************************************/
2209 uint8_t MacSchPagingInd(Pst *pst, SchPageInd *pageInd)
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;
2219 DU_LOG("\nDEBUG --> SCH : Received paging indication from MAC for cellId[%d]",\
2223 for(cellIdx = 0; cellIdx < MAX_NUM_CELL; cellIdx++)
2225 if((schCb[inst].cells[cellIdx]) && (schCb[inst].cells[cellIdx]->cellId == pageInd->cellId))
2227 cellCb = schCb[inst].cells[cellIdx];
2233 if(pageInd->i_s > cellCb->cellCfg.sib1SchCfg.pageCfg.numPO)
2235 DU_LOG("\nERROR --> SCH : MacSchPagingInd(): i_s should not be greater than number of paging occasion");
2239 SCH_ALLOC(pageInfo, sizeof(SchPageInfo));
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)
2252 DU_LOG("\nERROR --> SCH : MacSchPagingInd(): Failed to allocate memory");
2256 memcpy(pageInfo->pagePdu, pageInd->pagePdu, pageInfo->msgLen);
2257 ret = schAddPagingIndtoList(&cellCb->pageCb.pageIndInfoRecord[pageInfo->pageTxTime.sfn], pageInfo);
2260 DU_LOG("\nERROR --> SCH : MacSchPagingInd(): Failed to store paging record");
2266 DU_LOG("\nERROR --> SCH : MacSchPagingInd(): Failed to allocate memory");
2272 DU_LOG("\nERROR --> SCH : Cell ID [%d] not found", pageInd->cellId);
2274 SCH_FREE(pageInd->pagePdu, pageInd->pduLen);
2275 SCH_FREE(pageInd, sizeof(SchPageInd));
2279 DU_LOG("\nERROR --> SCH : MacSchPagingInd(): Received null pointer");
2285 /***********************************************************
2287 * Func : SchFillCfmPst
2290 * Desc : Fills the Confirmation Post Structure cfmPst using the reqPst
2291 * and the cfm->hdr.response.
2298 * File : rg_sch_lmm.c
2300 **********************************************************/
2310 inst = (reqPst->dstInst - SCH_INST_START);
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;
2319 cfmPst->selector = cfm->hdr.response.selector;
2320 cfmPst->region = cfm->hdr.response.mem.region;
2321 cfmPst->pool = cfm->hdr.response.mem.pool;
2326 /**********************************************************************
2328 **********************************************************************/