[Epic-ID: ODUHIGH-405][Task-ID: ODUHIGH-437] Establishing communication between Sourc...
[o-du/l2.git] / src / 5gnrsch / sch_slot_ind.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:     5G NR SCH layer
22
23 Type:     C source file
24
25 Desc:     C source code for Entry point fucntions for slot indications
26
27 File:     sch_slot_ind.c
28
29  **********************************************************************/
30
31 /** @file sch_slot_ind.c
32   @brief This module processes slot indications
33  */
34 #include "common_def.h"
35 #include "tfu.h"
36 #include "lrg.h"
37 #include "tfu.x"
38 #include "lrg.x"
39 #include "du_log.h"
40 #include "du_app_mac_inf.h"
41 #include "mac_sch_interface.h"
42 #include "sch.h"
43 #include "sch_utils.h"
44
45 SchMacDlAllocFunc schMacDlAllocOpts[] =
46 {
47    packSchMacDlAlloc,
48    MacProcDlAlloc,
49    packSchMacDlAlloc
50 };
51
52 /*******************************************************************
53  *
54  * @brief Handles sending DL broadcast alloc to MAC 
55  *
56  * @details
57  *
58  *    Function : sendDlAllocToMac
59  *
60  *    Functionality:
61  *     Sends DL Broadcast Resource Allocation to MAC from SCH
62  *
63  * @params[in] 
64  * @return ROK     - success
65  *         RFAILED - failure
66  *
67  * ****************************************************************/
68 uint8_t sendDlAllocToMac(DlSchedInfo *dlSchedInfo, Inst inst)
69 {
70    Pst pst;
71
72    memset(&pst, 0, sizeof(Pst));
73    FILL_PST_SCH_TO_MAC(pst, inst);
74    pst.event = EVENT_DL_SCH_INFO;
75
76    return(*schMacDlAllocOpts[pst.selector])(&pst, dlSchedInfo);
77
78 }
79
80 /*******************************************************************
81  *
82  * @brief Handles slot indication at SCH 
83  *
84  * @details
85  *
86  *    Function : schCalcSlotValues
87  *
88  *    Functionality:
89  *     Handles TTI indication received from PHY
90  *
91  * @params[in] 
92  * @return ROK     - success
93  *         RFAILED - failure
94  *
95  * ****************************************************************/
96 void schCalcSlotValues(SlotTimingInfo slotInd, SchSlotValue *schSlotValue)
97 {
98    /****************************************************************
99     * PHY_DELTA - the physical layer delta                         * 
100     * SCHED_DELTA - scheduler schedules one slot ahead             *
101     * BO_DELTA - this delay is considered for BO response and      *
102     *            RLC buffer packet to received at MAC              *
103     * lower-mac (FAPI filling) will be working on PHY_DELTA        *
104     * brdcast scheduler will working on PHY_DELTA + SCHED_DELTA    *
105     * RAR scheduler will working on PHY_DELTA + SCHED_DELTA        *
106     * msg4 scheduler will working on PHY_DELTA + SCHED_DELTA       *
107     * dedicated DL msg scheduler will working                      *
108     *        on PHY_DELTA + SCHED_DELTA + BO_DELTA                 *
109     ****************************************************************/
110
111    ADD_DELTA_TO_TIME(slotInd, schSlotValue->currentTime, PHY_DELTA_DL);
112    ADD_DELTA_TO_TIME(slotInd, schSlotValue->broadcastTime, PHY_DELTA_DL + SCHED_DELTA);
113    ADD_DELTA_TO_TIME(slotInd, schSlotValue->rarTime, PHY_DELTA_DL + SCHED_DELTA);
114    ADD_DELTA_TO_TIME(slotInd, schSlotValue->dlMsgTime, PHY_DELTA_DL + SCHED_DELTA);
115    ADD_DELTA_TO_TIME(slotInd, schSlotValue->ulDciTime, PHY_DELTA_DL + SCHED_DELTA);
116 }
117
118 /*******************************************************************
119  *
120  * @brief Checks if a slot is to be scheduled for SSB transmission
121  *
122  * @details
123  *
124  *    Function : schCheckSsbOcc 
125  *
126  *    Functionality:
127  *       Checks if a slot is to be scheduled for SSB transmission
128  *
129  * @params[in] SlotTimingInfo slotTime
130  *             SchCellCb *cell 
131  * @return  Pdu transmission 
132  *
133  * ****************************************************************/
134 PduTxOccsaion schCheckSsbOcc(SchCellCb *cell, SlotTimingInfo slotTime)
135 {
136    uint8_t  ssb_rep;
137
138    ssb_rep = cell->cellCfg.ssbSchCfg.ssbPeriod;
139
140    /* Identify SSB ocassion*/
141    if ((slotTime.sfn % SCH_MIB_TRANS == 0) && (slotTime.slot ==0))
142    {
143       return NEW_TRANSMISSION;
144    }
145    else if(cell->firstSsbTransmitted) 
146    {
147       if((ssb_rep == 5) && ((slotTime.slot == 0 || slotTime.slot == 10)))
148          return REPEATITION;
149       else if((slotTime.sfn % (ssb_rep/10) == 0) && slotTime.slot == 0)
150          return REPEATITION;
151    }
152    /* not SSB occassion */
153    return NO_TRANSMISSION;
154 }
155
156 /*******************************************************************
157  *
158  * @brief Checks if a slot is to be scheduled for SIB1 transmission
159  *
160  * @details
161  *
162  *    Function : schCheckSib1Occ
163  *
164  *    Functionality:
165  *       Checks if a slot is to be scheduled for SIB1 transmission
166  *
167  * @params[in] SlotTimingInfo slotTime
168  *             SchCellCb *cell
169  * @return  Pdu transmission
170  *
171  * ****************************************************************/
172 PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
173 {
174    /* Identify SIB1 occasions */
175    if((slotTime.sfn % SCH_SIB1_TRANS == 0) && (slotTime.slot ==0))
176    {
177       return NEW_TRANSMISSION;
178    }
179    else if(cell->firstSib1Transmitted) 
180    {
181       if((slotTime.sfn % (cell->cellCfg.sib1SchCfg.sib1RepetitionPeriod/10) == 0) &&
182             (slotTime.slot == 0))
183       {
184          return REPEATITION;
185       }
186    }
187    /* not SIB1 occassion */
188    return NO_TRANSMISSION;
189 }
190
191 /*******************************************************************
192  *
193  * @brief find correct combination of k0-k1 value
194  *
195  * @details
196  *
197  *    Function : findValidK0K1Value
198  *
199  *    Functionality:
200  *       find correct combination of k0-k1 value
201  *
202  * @params[in]
203  * @return ROK     - success
204  *         RFAILED - failure
205  *
206  *******************************************************************/
207 bool findValidK0K1Value(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool dedMsg, uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen, SlotTimingInfo *pdcchTime,  SlotTimingInfo *pdschTime, SlotTimingInfo *pucchTime)
208 {
209    uint8_t numK0 = 0, k0TblIdx = 0, k0Val = 0, k0Index =0 ;
210    uint8_t k1TblIdx = 0, k1Index = 0, k1Val = 0, numK1 = 0;
211    SchUeCb *ueCb = NULLP;
212    SchK0K1TimingInfoTbl *k0K1InfoTbl;
213
214    ADD_DELTA_TO_TIME(currTime, (*pdcchTime), PHY_DELTA_DL + SCHED_DELTA);
215 #ifdef NR_TDD
216    if(schGetSlotSymbFrmt(pdcchTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
217    {
218       /* If it is not a DL slot, cannot schedule PDCCH. Return from here. */
219       return false;
220    }
221 #endif
222
223    if(cell->schDlSlotInfo[pdcchTime->slot]->pdcchUe != 0)
224    {
225       return false;
226    }
227
228    if(dedMsg == true)
229    {
230       ueCb = &cell->ueCb[ueId-1];
231       k0K1InfoTbl = &ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1InfoTbl;
232    }
233    else
234    {
235       k0K1InfoTbl = &cell->cellCfg.schInitialDlBwp.k0K1InfoTbl;
236    }
237
238    numK0 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].numK0;
239    for(k0TblIdx = 0; k0TblIdx < numK0; k0TblIdx++)
240    {
241       k0Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k0Index;
242       if(dedMsg != true)
243       {
244          k0Val = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
245          *pdschStartSymbol = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
246          *pdschSymblLen = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
247       }
248       else
249       {
250          if(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0 != NULLP)
251          {
252             k0Val = *(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0);
253             *pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
254             *pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
255          }
256       }
257
258       ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val);
259 #ifdef NR_TDD
260       if(schGetSlotSymbFrmt(pdschTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
261       {
262          continue;
263       }
264 #endif
265       if(cell->schDlSlotInfo[pdschTime->slot]->pdschUe != 0)
266       {
267          continue; 
268       }
269
270       numK1 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.numK1;
271       for(k1TblIdx = 0; k1TblIdx < numK1; k1TblIdx++)
272       {
273          k1Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.k1Indexes[k1TblIdx];
274          if(dedMsg != true)
275          {
276             k1Val = defaultUlAckTbl[k1Index];
277          }
278          else
279          {
280             if(ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck)
281             {
282                k1Val = ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
283             }
284          }
285          ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val);
286 #ifdef NR_TDD
287          if(schGetSlotSymbFrmt(pucchTime->slot, cell->slotFrmtBitMap) == DL_SLOT)
288          {
289             continue;
290          }
291 #endif
292          if(cell->schUlSlotInfo[pucchTime->slot]->pucchUe != 0)
293          {
294             continue; 
295          }
296          return true;
297       }
298    }
299    return false;
300 }
301
302 /*******************************************************************
303  *
304  * @brief 
305  *
306  * @details
307  *
308  *    Function : schFillBoGrantDlSchedInfo 
309  *
310  *    Functionality:
311  
312  *
313  * @params[in] 
314  * @return ROK     - success
315  *         RFAILED - failure
316  *
317  * ****************************************************************/
318 bool schFillBoGrantDlSchedInfo(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId)
319 {
320    uint8_t lcIdx = 0;
321    uint8_t pdschNumSymbols = 0, pdschStartSymbol = 0;
322    uint16_t startPrb = 0, maxFreePRB = 0;
323    uint16_t crnti = 0, mcsIdx = 0;
324    uint32_t accumalatedSize = 0;
325    SchUeCb *ueCb = NULLP;
326    CmLListCp *lcLL = NULLP;
327    DlMsgAlloc *dciSlotAlloc, *dlMsgAlloc;
328    SlotTimingInfo pdcchTime, pdschTime, pucchTime;
329
330    /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
331     * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
332     * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
333     * else if only Default list is present then first node in this List will add this overhead len*/
334    bool isTxPayloadLenAdded = FALSE;
335
336    GET_CRNTI(crnti,ueId);
337    ueCb = &cell->ueCb[ueId-1];
338
339    if(findValidK0K1Value(cell, currTime, ueId, ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1TblPrsnt,\
340             &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime, &pucchTime) != true )
341    {
342       /* If a valid combination of slots to scheduled PDCCH, PDSCH and PUCCH is
343        * not found, do not perform resource allocation. Return from here. */
344       return false;
345    }
346
347    /* allocate PDCCH and PDSCH resources for the ue */
348    if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
349    {
350
351       SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgAlloc));
352       if(!dciSlotAlloc)
353       {
354          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for ded DL msg alloc");
355          return false;
356       }
357       cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = dciSlotAlloc;
358       memset(dciSlotAlloc, 0, sizeof(DlMsgAlloc));
359       dciSlotAlloc->crnti = crnti;
360    }
361    else
362    {
363       dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1];
364    }
365    /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
366    fillDlMsgInfo(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].dlMsgInfo, dciSlotAlloc->crnti);
367
368    /*Re-Initalization per UE*/
369    /* scheduled LC data fill */
370    dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].numLc = 0;
371    isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
372    accumalatedSize = 0;
373
374    for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
375    {
376       if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
377       {
378          /*Check the LC is Dedicated or default and accordingly LCList will
379           * be used*/
380          if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
381          {
382             lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
383          }
384          else
385          {
386             lcLL = &(ueCb->dlLcPrbEst.defLcList);
387          }
388
389          /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
390          if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
391                   (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
392          {
393             DU_LOG("\nERROR  --> SCH : Updation in LC List Failed");
394             /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
395             if(dciSlotAlloc->numSchedInfo == 0)
396             {
397                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
398                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
399             }
400             else
401                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
402             return false;
403          }
404       }
405       ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
406    }//End of for loop
407
408
409    if ((ueCb->dlLcPrbEst.defLcList.count == 0) && \
410          ((ueCb->dlLcPrbEst.dedLcInfo == NULL) || (ueCb->dlLcPrbEst.dedLcInfo->dedLcList.count == 0)))
411    {
412       DU_LOG("\nDEBUG  -->  SCH : No pending BO for any LC id\n");
413       UNSET_ONE_BIT(ueId, cell->boIndBitMap);
414
415       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
416       if(dciSlotAlloc->numSchedInfo == 0)
417       {
418          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
419          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
420       }
421       else
422          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
423
424       /*TRUE because this UE has nothing to be scheduled*/
425       return true;
426    }
427
428    /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
429    maxFreePRB = searchLargestFreeBlock(cell, pdschTime, &startPrb, DIR_DL);
430
431    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
432     * the list based on RRM policy*/
433
434    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
435     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
436    if(maxFreePRB != 0)
437    {
438       mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
439       if((ueCb->dlLcPrbEst.dedLcInfo == NULLP) 
440             || ((maxFreePRB <  ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB)))
441       { 
442          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB;
443          DU_LOG("\nDEBUG  --> SCH : DL Only Default Slice is scheduled, sharedPRB Count:%d",\
444                ueCb->dlLcPrbEst.sharedNumPrb);
445
446          /*PRB Alloc for Default LCs*/
447          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
448                &(ueCb->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded, NULLP);
449       }
450       else
451       {
452          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB - ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB;
453
454          /*PRB Alloc for Dedicated LCs*/
455          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
456                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
457
458          /*PRB Alloc for Default LCs*/
459          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
460                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
461       }
462    }
463
464    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
465     * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/ 
466    if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
467       updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
468
469    updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.defLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
470
471    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
472    if (!accumalatedSize)
473    {
474       if(maxFreePRB == 0)
475       {
476          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
477       }
478       else
479       {
480          /*Schedule the LC for next slot*/
481          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
482       }
483       /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
484        * Allocation can be done in next slot*/
485       return false;
486    }
487
488    /*[Step6]: pdcch and pdsch data is filled */
489    if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb, pdschStartSymbol, pdschNumSymbols)) != ROK)
490    {
491       DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
492
493       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
494       if(dciSlotAlloc->numSchedInfo == 0)
495       {
496          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
497          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
498       }
499       else
500          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
501       return false;
502    }
503
504    /* TODO : Update the scheduling byte report for multiple LC based on QCI
505     * and Priority */
506    /* As of now, the total number of bytes scheduled for a slot is divided
507     * equally amongst all LC with pending data. This is avoid starving of any
508     * LC 
509     * */
510 #if 0
511    accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
512    for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
513       dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
514 #endif
515    
516    /* Check if both DCI and DL_MSG are sent in the same slot.
517     * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
518
519    if(pdcchTime.slot == pdschTime.slot)
520    {
521       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = BOTH;
522       dciSlotAlloc->numSchedInfo++;
523    }
524    else
525    {
526       /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
527       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
528       {
529          SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgAlloc));
530          if(dlMsgAlloc == NULLP)
531          {
532             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc");
533             if(dciSlotAlloc->numSchedInfo == 0)
534             {
535                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
536                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
537             }
538             else
539                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
540             return false;
541          }
542          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
543          memset(dlMsgAlloc, 0, sizeof(DlMsgAlloc));
544          dlMsgAlloc->crnti = dciSlotAlloc->crnti;
545       }
546       else
547          dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
548
549       /* Copy all DL_MSG info */
550       memcpy(&dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo], \
551             &dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], sizeof(DlMsgSchInfo));
552       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdcchCfg.dci.pdschCfg = \
553             &dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdschCfg;
554
555       /* Assign correct PDU types in corresponding slots */
556       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].pduPres = PDSCH_PDU;
557       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = PDCCH_PDU;
558       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pdschSlot = pdschTime.slot;
559
560       dciSlotAlloc->numSchedInfo++;
561       dlMsgAlloc->numSchedInfo++;
562    }
563
564    schAllocPucchResource(cell, pucchTime, crnti);
565    cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
566    cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
567    cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
568
569    /* after allocation is done, unset the bo bit for that ue */
570    UNSET_ONE_BIT(ueId, cell->boIndBitMap);
571  
572    return true;
573 }
574
575 /*******************************************************************
576  *
577  * @brief Handles slot indication at SCH 
578  *
579  * @details
580  *
581  *    Function : schProcessSlotInd
582  *
583  *    Functionality:
584  *     Handles TTI indication received from PHY
585  *
586  * @params[in] 
587  * @return ROK     - success
588  *         RFAILED - failure
589  *
590  * ****************************************************************/
591 uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst)
592 {
593    uint8_t   ueId, ueIdx, ret = ROK;
594    uint16_t  slot;
595    bool      isRarPending = false, isRarScheduled = false;
596    bool      isMsg4Pending = false, isMsg4Scheduled = false;
597    bool      isUlGrantPending = false, isUlGrantScheduled = false;
598    bool      isDlMsgPending = false, isDlMsgScheduled = false;
599    CmLList       *pendingUeNode;
600    DlSchedInfo   dlSchedInfo;
601    DlBrdcstAlloc *dlBrdcstAlloc = NULLP;
602    SchCellCb     *cell = NULLP;
603
604    memset(&dlSchedInfo, 0, sizeof(DlSchedInfo));
605    schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue);
606    dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
607    dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
608    dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
609
610    cell = schCb[schInst].cells[schInst];
611    if(cell == NULLP)
612    {
613       DU_LOG("\nERROR  -->  SCH : Cell Does not exist");
614       return RFAILED;
615    }
616    memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
617    dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
618
619    dlSchedInfo.cellId = cell->cellId;
620    slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
621
622    /* Check for SSB occassion */
623    dlBrdcstAlloc->ssbTrans = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); 
624    if(dlBrdcstAlloc->ssbTrans)
625    {
626       if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
627       {
628          DU_LOG("\nERROR  -->  SCH : schBroadcastSsbAlloc failed");
629          dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
630       }
631       else 
632       {
633          dlSchedInfo.isBroadcastPres = true;
634          if((dlBrdcstAlloc->ssbTrans == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
635             cell->firstSsbTransmitted = true;
636       }
637    }
638
639    /* Check for SIB1 occassion */
640    dlBrdcstAlloc->sib1Trans = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
641    if(dlBrdcstAlloc->sib1Trans)
642    {
643       if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
644       {
645          DU_LOG("\nERROR  -->  SCH : schBroadcastSib1Alloc failed");
646          dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
647       }
648       else 
649       {
650          dlSchedInfo.isBroadcastPres = true;
651          if((dlBrdcstAlloc->sib1Trans == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
652             cell->firstSib1Transmitted = true;
653       }
654    }
655
656    /* Select first UE in the linked list to be scheduled next */
657    pendingUeNode = cell->ueToBeScheduled.first;
658    if(pendingUeNode)
659    {
660       if(pendingUeNode->node)
661       {
662          ueId = *(uint8_t *)(pendingUeNode->node);
663
664          /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and 
665           * PUSCH to receive MSG3 as per k0-k2 configuration*/
666          if(cell->raReq[ueId-1] != NULLP)
667          {
668             isRarPending = true;
669             isRarScheduled = schProcessRaReq(schInst, cell, *slotInd, ueId);
670          }
671
672          /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
673           * PUCCH to receive UL msg as per k0-k1 configuration  */
674          if(cell->raCb[ueId-1].msg4recvd)
675          {
676             isMsg4Pending = true;
677             isMsg4Scheduled = schProcessMsg4Req(cell, *slotInd, ueId);
678          }
679
680          if(isRarPending || isMsg4Pending)
681          {
682             /* If RAR or MSG is successfully scheduled then
683              * remove UE from linked list since no pending msgs for this UE */
684             if(isRarScheduled || isMsg4Scheduled)
685             {
686                SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
687                deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
688             }
689             /* If RAR/MSG4 is pending but couldnt be scheduled then,
690              * put this UE at the end of linked list to be scheduled later */
691             else 
692             {
693                cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
694             }
695          }
696
697          if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
698          {
699             isUlGrantPending = true;
700             isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId);
701          }
702
703          if((cell->boIndBitMap) & (1<<ueId))
704          {
705             isDlMsgPending = true;
706             isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId);
707          }
708          if(!isUlGrantPending && !isDlMsgPending)
709          {
710             /* No action required */  
711          }
712          else if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
713          {
714             cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
715          }
716          else
717          {
718             SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
719             deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
720          }
721       }
722    }
723
724    /* Check if any PDU is scheduled at this slot for any UE */
725    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
726    {
727       /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface 
728        * structure to send to MAC */
729       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
730       {
731          slot = dlSchedInfo.schSlotValue.rarTime.slot;
732          dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
733          cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
734       }
735
736       /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill 
737        * specific interface structure to send to MAC */
738       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
739       {
740          slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
741          dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
742          cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
743       }
744
745    }
746
747    if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.ulDciTime.slot]->ulGrant != NULLP)
748    {
749       slot = dlSchedInfo.schSlotValue.ulDciTime.slot;
750       dlSchedInfo.ulGrant = cell->schDlSlotInfo[slot]->ulGrant;
751       cell->schDlSlotInfo[slot]->ulGrant = NULLP;
752    }
753
754    /* Send msg to MAC */
755    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
756    if(ret != ROK)
757    {
758       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
759       return (ret);
760    }
761
762    schInitDlSlot(cell->schDlSlotInfo[slot]);
763    schUlResAlloc(cell, schInst);
764
765    return ret;
766 }
767
768 /**********************************************************************
769   End of file
770  **********************************************************************/
771
772