Merge "[Epic-ID: ODUHIGH-556][Task-ID: ODUHIGH-570] UL Candidate Sel and Res Alloc...
[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_tmr.h"
44 #include "sch_utils.h"
45 #ifdef NR_DRX 
46 #include "sch_drx.h"
47 #endif
48
49 /*******************************************************************
50  *
51  * @brief Handles sending DL broadcast alloc to MAC 
52  *
53  * @details
54  *
55  *    Function : sendDlAllocToMac
56  *
57  *    Functionality:
58  *     Sends DL Broadcast Resource Allocation to MAC from SCH
59  *
60  * @params[in] 
61  * @return ROK     - success
62  *         RFAILED - failure
63  *
64  * ****************************************************************/
65 uint8_t sendDlAllocToMac(DlSchedInfo *dlSchedInfo, Inst inst)
66 {
67    Pst pst;
68
69    memset(&pst, 0, sizeof(Pst));
70    FILL_PST_SCH_TO_MAC(pst, inst);
71    pst.event = EVENT_DL_SCH_INFO;
72
73    return(MacMessageRouter(&pst, (void *)dlSchedInfo));
74 }
75
76 /*******************************************************************
77  *
78  * @brief 
79  *
80  * @details
81  *
82  *    Function : schFillBoGrantDlSchedInfo 
83  *
84  *    Functionality:
85  
86  *
87  * @params[in] SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
88  * @params[in] bool isRetx, SchDlHqProcCb **hqP
89  * @return ROK     - success
90  *         RFAILED - failure
91  *
92  * ****************************************************************/
93 bool schFillBoGrantDlSchedInfo(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool isRetx, SchDlHqProcCb **hqP)
94 {
95    uint8_t pdschNumSymbols = 0, pdschStartSymbol = 0;
96    uint8_t lcIdx = 0;
97    uint16_t startPrb = 0;
98    uint16_t crnti = 0;
99    uint32_t accumalatedSize = 0;
100    SchUeCb *ueCb = NULLP;
101    DlMsgSchInfo *dciSlotAlloc, *dlMsgAlloc;
102    SlotTimingInfo pdcchTime, pdschTime, pucchTime;
103    SchPdcchAllocInfo pdcchAllocInfo;
104
105    GET_CRNTI(crnti,ueId);
106    ueCb = &cell->ueCb[ueId-1];
107
108    if (isRetx == FALSE)
109    {
110       if(schDlGetAvlHqProcess(cell, ueCb, hqP) != ROK)
111       {
112          return false;
113       }
114    }
115
116    memset(&pdcchAllocInfo,0,sizeof(SchPdcchAllocInfo));
117    if(findValidK0K1Value(cell, currTime, ueId, ueCb->k0K1TblPrsnt,\
118             &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime, \
119             &pucchTime, isRetx, *hqP, &pdcchAllocInfo) != true )
120    {
121       /* If a valid combination of slots to scheduled PDCCH, PDSCH and PUCCH is
122        * not found, do not perform resource allocation. Return from here. */
123       return false;
124    }
125    
126    /* allocate PDCCH and PDSCH resources for the ue */
127    if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
128    {
129
130       SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgSchInfo));
131       if(!dciSlotAlloc)
132       {
133          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for ded DL msg alloc");
134          return false;
135       }
136       cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = dciSlotAlloc;
137       memset(dciSlotAlloc, 0, sizeof(DlMsgSchInfo));
138    }
139    else
140    {
141       dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1];
142    }
143    /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
144    fillDlMsgInfo(dciSlotAlloc, crnti, isRetx, *hqP);
145    dciSlotAlloc->transportBlock[0].ndi = isRetx;
146
147    accumalatedSize = cell->api->SchScheduleDlLc(pdcchTime, pdschTime, pdschNumSymbols, &startPrb, isRetx, hqP);
148
149    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
150    if (!accumalatedSize)
151       return false;
152
153    /*[Step6]: pdcch and pdsch data is filled */
154    if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb,\
155                            pdschStartSymbol, pdschNumSymbols, isRetx, *hqP, pdcchAllocInfo)) != ROK)
156    {
157       DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
158
159       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
160       if(!dciSlotAlloc->dlMsgPdschCfg)
161       {
162          SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
163          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
164       }
165       return false;
166    }
167
168    /* TODO : Update the scheduling byte report for multiple LC based on QCI
169     * and Priority */
170    /* As of now, the total number of bytes scheduled for a slot is divided
171     * equally amongst all LC with pending data. This is avoid starving of any
172     * LC 
173     * */
174 #if 0
175    accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
176    for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
177       dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
178 #endif
179    
180    /* Check if both DCI and DL_MSG are sent in the same slot.
181     * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
182
183    if(pdcchTime.slot == pdschTime.slot)
184    {
185       SCH_ALLOC(dciSlotAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
186       if(!dciSlotAlloc->dlMsgPdschCfg)
187       {
188          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciSlotAlloc->dlMsgPdschCfg");
189          SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
190          SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
191          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
192          return false;
193       }
194       memcpy(dciSlotAlloc->dlMsgPdschCfg,\
195          &dciSlotAlloc->dlMsgPdcchCfg->dci[dciSlotAlloc->dlMsgPdcchCfg->numDlDci - 1].pdschCfg,  sizeof(PdschCfg));
196    }
197    else
198    {
199       /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
200       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
201       {
202          SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgSchInfo));
203          if(dlMsgAlloc == NULLP)
204          {
205             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc");
206             SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
207             if(dciSlotAlloc->dlMsgPdschCfg == NULLP)
208             {
209                SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
210                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
211             }
212             return false;
213          }
214          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
215          memset(dlMsgAlloc, 0, sizeof(DlMsgSchInfo));
216       }
217       else
218          dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
219
220       /* Copy all DL_MSG info */
221       dlMsgAlloc->crnti =crnti;
222       dlMsgAlloc->bwp = dciSlotAlloc->bwp;
223       SCH_ALLOC(dlMsgAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
224       if(dlMsgAlloc->dlMsgPdschCfg)
225       {
226          memcpy(dlMsgAlloc->dlMsgPdschCfg,\
227                 &dciSlotAlloc->dlMsgPdcchCfg->dci[dciSlotAlloc->dlMsgPdcchCfg->numDlDci - 1].pdschCfg, sizeof(PdschCfg));
228       }
229       else
230       {
231          SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));    
232          if(dciSlotAlloc->dlMsgPdschCfg == NULLP)
233          {
234             SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
235             cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
236
237          }
238          SCH_FREE(dlMsgAlloc, sizeof(DlMsgSchInfo));
239          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
240          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc->dlMsgPdschCfg");
241          return false;
242       }
243    }
244
245    /*Re-setting the BO's of all DL LCs in this UE*/
246    for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
247    {
248       ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
249    }
250
251    /* after allocation is done, unset the bo bit for that ue */
252    UNSET_ONE_BIT(ueId, cell->boIndBitMap);
253    return true;
254 }
255
256 /*******************************************************************
257  *
258  * @brief Handles sending DL Page alloc to MAC 
259  *
260  * @details
261  *
262  *    Function : sendDlPAgeAllocToMac
263  *
264  *    Functionality:
265  *     Sends DL Page Resource Allocation to MAC from SCH
266  *
267  * @params[in] 
268  * @return ROK     - success
269  *         RFAILED - failure
270  *
271  * ****************************************************************/
272 uint8_t sendDlPageAllocToMac(DlPageAlloc *dlPageAlloc, Inst inst)
273 {
274    Pst pst;
275
276    memset(&pst, 0, sizeof(Pst));
277    FILL_PST_SCH_TO_MAC(pst, inst);
278    pst.event = EVENT_DL_PAGING_ALLOC;
279
280    return(MacMessageRouter(&pst, (void *)dlPageAlloc));
281 }
282
283 /*******************************************************************
284  *
285  * @brief Handles slot indication at SCH 
286  *
287  * @details
288  *
289  *    Function : schCalcSlotValues
290  *
291  *    Functionality:
292  *     Handles TTI indication received from PHY
293  *
294  * @params[in] 
295  * @return ROK     - success
296  *         RFAILED - failure
297  *
298  * ****************************************************************/
299 void schCalcSlotValues(SlotTimingInfo slotInd, SchSlotValue *schSlotValue, uint16_t numOfSlots)
300 {
301    /****************************************************************
302     * PHY_DELTA - the physical layer delta                         * 
303     * SCHED_DELTA - scheduler schedules one slot ahead             *
304     * BO_DELTA - this delay is considered for BO response and      *
305     *            RLC buffer packet to received at MAC              *
306     * lower-mac (FAPI filling) will be working on PHY_DELTA        *
307     * brdcast scheduler will working on PHY_DELTA + SCHED_DELTA    *
308     * RAR scheduler will working on PHY_DELTA + SCHED_DELTA        *
309     * msg4 scheduler will working on PHY_DELTA + SCHED_DELTA       *
310     * dedicated DL msg scheduler will working                      *
311     *        on PHY_DELTA + SCHED_DELTA + BO_DELTA                 *
312     ****************************************************************/
313
314    ADD_DELTA_TO_TIME(slotInd, schSlotValue->currentTime, gConfigInfo.gPhyDeltaDl, numOfSlots);
315    ADD_DELTA_TO_TIME(slotInd, schSlotValue->broadcastTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, numOfSlots);
316    ADD_DELTA_TO_TIME(slotInd, schSlotValue->rarTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, numOfSlots);
317    ADD_DELTA_TO_TIME(slotInd, schSlotValue->dlMsgTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, numOfSlots);
318    ADD_DELTA_TO_TIME(slotInd, schSlotValue->ulDciTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, numOfSlots);
319 }
320
321 /*******************************************************************
322  *
323  * @brief Checks if a slot is to be scheduled for SSB transmission
324  *
325  * @details
326  *
327  *    Function : schCheckSsbOcc 
328  *
329  *    Functionality:
330  *       Checks if a slot is to be scheduled for SSB transmission
331  *
332  * @params[in] SlotTimingInfo slotTime
333  *             SchCellCb *cell 
334  * @return  Pdu transmission 
335  *
336  * ****************************************************************/
337 PduTxOccsaion schCheckSsbOcc(SchCellCb *cell, SlotTimingInfo slotTime)
338 {
339    uint8_t  ssb_rep;
340
341    ssb_rep = cell->cellCfg.ssbPeriod;
342
343    /* Identify SSB ocassion*/
344    if ((slotTime.sfn % SCH_MIB_TRANS == 0) && (slotTime.slot ==0))
345    {
346       return NEW_TRANSMISSION;
347    }
348    else if(cell->firstSsbTransmitted) 
349    {
350       if((ssb_rep == 5) && ((slotTime.slot == 0 || slotTime.slot == 10)))
351          return REPEATITION;
352       else if((slotTime.sfn % (ssb_rep/10) == 0) && slotTime.slot == 0)
353          return REPEATITION;
354    }
355    /* not SSB occassion */
356    return NO_TRANSMISSION;
357 }
358
359 /*******************************************************************
360  *
361  * @brief Checks if a slot is to be scheduled for SIB1 transmission
362  *
363  * @details
364  *
365  *    Function : schCheckSib1Occ
366  *
367  *    Functionality:
368  *       Checks if a slot is to be scheduled for SIB1 transmission
369  *
370  * @params[in] SlotTimingInfo slotTime
371  *             SchCellCb *cell
372  * @return  Pdu transmission
373  *
374  * ****************************************************************/
375 PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
376 {
377    /* Identify SIB1 occasions */
378    if((slotTime.sfn % SCH_SIB1_TRANS == 0) && (slotTime.slot ==0))
379    {
380       return NEW_TRANSMISSION;
381    }
382    else if(cell->firstSib1Transmitted) 
383    {
384       if((slotTime.sfn % (SIB1_REPETITION_PERIOD/10) == 0) &&
385             (slotTime.slot == 0))
386       {
387          return REPEATITION;
388       }
389    }
390    /* not SIB1 occassion */
391    return NO_TRANSMISSION;
392 }
393
394 /*******************************************************************
395  *
396  * @brief find correct combination of k0-k1 value
397  *
398  * @details
399  *
400  *    Function : findValidK0K1Value
401  *
402  *    Functionality:
403  *       find correct combination of k0-k1 value
404  *
405  * @params[in] SchCellCb *cell, SlotTimingInfo currTime
406  * @params[in] uint8_t ueId, bool dedMsg
407  * @params[in] uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen
408  * @params[in] SlotTimingInfo *pdcchTime, SlotTimingInfo *pdschTime
409  * @params[in] SlotTimingInfo *pucchTime, bool isRetx, SchDlHqProcCb *hqP
410  * @return ROK     - success
411  *         RFAILED - failure
412  *
413  *******************************************************************/
414 bool findValidK0K1Value(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool dedMsg,
415                         uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen, SlotTimingInfo *pdcchTime,
416                         SlotTimingInfo *pdschTime, SlotTimingInfo *pucchTime, bool isRetx, SchDlHqProcCb *hqP,
417                         SchPdcchAllocInfo *pdcchAllocInfo)
418 {
419    uint8_t numK0 = 0, k0TblIdx = 0, k0Val = 0, k0Index =0 ;
420    uint8_t k1TblIdx = 0, k1Index = 0, k1Val = 0, numK1 = 0;
421    uint8_t ret = RFAILED;
422    uint16_t  crnti = 0;
423    SchUeCb *ueCb = NULLP;
424    SchK0K1TimingInfoTbl *k0K1InfoTbl;
425
426    ADD_DELTA_TO_TIME(currTime, (*pdcchTime), gConfigInfo.gPhyDeltaDl + SCHED_DELTA, cell->numSlots);
427 #ifdef NR_TDD
428    if(schGetSlotSymbFrmt(pdcchTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
429    {
430       /* If it is not a DL slot, cannot schedule PDCCH. Return from here. */
431       return false;
432    }
433 #endif
434
435    ueCb = &cell->ueCb[ueId-1];
436    GET_CRNTI(crnti, ueId);
437    if(dedMsg == true)
438    {
439       k0K1InfoTbl = &ueCb->k0K1InfoTbl;
440       if(schDlCandidateSelection(ueCb, *pdcchTime, pdcchAllocInfo) == false)
441       {
442          DU_LOG("\nDEBUG  --> SCH: DL candidate Selection failed bcz PDCCH is unavailable for this slot");
443          return false;     
444       }
445    }
446    else
447    {
448       k0K1InfoTbl = &cell->k0K1InfoTbl;
449    }
450
451    numK0 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].numK0;
452    for(k0TblIdx = 0; k0TblIdx < numK0; k0TblIdx++)
453    {
454       k0Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k0Index;
455       if(dedMsg != true)
456       {
457          k0Val = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
458          *pdschStartSymbol = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
459          *pdschSymblLen = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
460       }
461       else
462       {
463          if(ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0 != NULLP)
464          {
465             k0Val = *(ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0);
466             *pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
467             *pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
468          }
469          else
470          {
471             k0Val = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
472             *pdschStartSymbol = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
473             *pdschSymblLen = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
474          }
475       }
476
477       ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val, cell->numSlots);
478 #ifdef NR_TDD
479       if(schGetSlotSymbFrmt(pdschTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
480       {
481          continue;
482       }
483 #endif
484
485       numK1 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.numK1;
486       for(k1TblIdx = 0; k1TblIdx < numK1; k1TblIdx++)
487       {
488          k1Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.k1Indexes[k1TblIdx];
489          if(dedMsg != true)
490          {
491             k1Val = defaultUlAckTbl[k1Index];
492          }
493          else
494          {
495             if(ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg.dlDataToUlAck)
496             {
497                k1Val = ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
498             }
499             else
500             {
501                k1Val = defaultUlAckTbl[k1Index];
502             }
503          }
504          ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val, cell->numSlots);
505 #ifdef NR_TDD
506          if(schGetSlotSymbFrmt(pucchTime->slot, cell->slotFrmtBitMap) == DL_SLOT)
507          {
508             continue;
509          }
510 #endif
511          if(cell->schUlSlotInfo[pucchTime->slot]->schPucchInfo[ueId - 1].crnti == crnti)
512          {
513             continue; 
514          }
515          if(hqP)
516          {
517             ADD_DELTA_TO_TIME((*pucchTime), hqP->pucchTime, 0, cell->numSlots);
518          }
519          pdcchTime->cellId = cell->cellId;
520          pdschTime->cellId = cell->cellId;
521          
522          cell->schUlSlotInfo[pucchTime->slot]->schPucchInfo[ueId - 1].crnti = crnti;
523
524          /*Availability of PUCCH for HARQ resources*/
525          ret = schAllocPucchResource(cell, ueId, *pucchTime, ueCb, hqP, pdcchAllocInfo);
526          if(ret == RFAILED)
527          {
528             /*DL allocation can't go through as PUCCH is unavailable*/
529             return false;
530          }
531          return true;
532       }
533    }
534
535
536    /*
537     * Number of symbols in case of retransmisson should be same as it was in
538     * original transmisson. Symbol availablity checks need to be added.
539     */
540    return false;
541 }
542
543 /*******************************************************************
544 *
545 * @brief Process DL Resource allocation for Page
546 *
547 * @details
548 *
549 *    Function : schProcDlPageAlloc
550 *
551 *    Functionality: Process DL Resource allocation for Page
552 *
553 * @params[in] SchCellCb *cell, SlotTimingInfo currTime, Inst schInst
554 *
555 * @return pointer to return Value(ROK, RFAILED)
556 *
557 * ****************************************************************/
558 uint8_t schProcDlPageAlloc(SchCellCb *cell, SlotTimingInfo currTime, Inst schInst)
559 {
560    DlPageAlloc      dlPageAlloc;
561    CmLList          *pageInfoNode = NULLP;
562    SchPageInfo      *pageInfo = NULLP;
563    SlotTimingInfo   pdschTime;
564    uint32_t         tbSize = 0;
565    uint16_t         startPrb = 0, maxFreePRB = 0, nPRB = 0;
566    uint8_t          ret = RFAILED;
567
568    pageInfoNode = schPageInfoSearchFromPageList(currTime, &(cell->pageCb.pageIndInfoRecord[currTime.sfn]));
569
570    if(pageInfoNode == NULLP)
571    {
572       return ROK;
573    }
574    pageInfo = (SchPageInfo *)pageInfoNode->node;
575    
576    while(true)
577    {
578       dlPageAlloc.cellId = currTime.cellId;
579
580       ADD_DELTA_TO_TIME(currTime, dlPageAlloc.dlPageTime, gConfigInfo.gPhyDeltaDl + SCHED_DELTA, cell->numSlots);
581       dlPageAlloc.shortMsgInd  = FALSE;
582       pdschTime = dlPageAlloc.dlPageTime;
583
584       /*Calculate Best FREE BLOCK with MAX PRB count*/
585       maxFreePRB = searchLargestFreeBlock(cell, pdschTime, &startPrb, DIR_DL);
586
587       if(maxFreePRB != 0)
588       {
589          tbSize = calculateEstimateTBSize(pageInfo->msgLen, pageInfo->mcs, NUM_PDSCH_SYMBOL, maxFreePRB, &nPRB);
590       }
591       else
592       {
593          DU_LOG("\nERROR  --> SCH: Unable to get any free block for Paging at SFN:%d, SLOT:%d",\
594                pdschTime.sfn, pdschTime.slot);
595          break;
596       }
597       /*Fill PDCCH: PDCCH Cfg is same as SIB1 as Paging will be a broadcast message*/
598       memcpy(dlPageAlloc.pageDlDci.freqDomainResource, cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.freqDomainResource, 6 * sizeof(uint8_t));
599       dlPageAlloc.pageDlDci.durationSymbols = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.durationSymbols;
600       dlPageAlloc.pageDlDci.cceRegMappingType = INTERLEAVED_CCE_REG_MAPPING;
601       dlPageAlloc.pageDlDci.cceReg.interleaved.regBundleSize = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.regBundleSize;
602       dlPageAlloc.pageDlDci.cceReg.interleaved.interleaverSize = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.interleaverSize;
603       dlPageAlloc.pageDlDci.cceReg.interleaved.shiftIndex = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.shiftIndex;
604       dlPageAlloc.pageDlDci.ssStartSymbolIndex = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.startSymbolIndex;
605       dlPageAlloc.pageDlDci.cceIndex = cell->sib1SchCfg.sib1PdcchCfg.dci[0].cceIndex;
606       dlPageAlloc.pageDlDci.aggregLevel = cell->sib1SchCfg.sib1PdcchCfg.dci[0].aggregLevel;
607       dlPageAlloc.pageDlDci.precoderGranularity = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.precoderGranularity;
608       dlPageAlloc.pageDlDci.coreSetSize = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.coreSetSize;
609       /*Fill BWP*/
610       memcpy(&dlPageAlloc.bwp, &cell->sib1SchCfg.bwp, sizeof(BwpCfg)); 
611
612       /*Fill PDSCH*/
613       if(schFillPagePdschCfg(cell, &dlPageAlloc.pageDlSch, pdschTime, tbSize, pageInfo->mcs, startPrb) != ROK)
614       {
615          DU_LOG("\nERROR  --> SCH: Issue in PDSCH Allocation for Paging at SFN:%d, SLOT:%d",\
616                pdschTime.sfn, pdschTime.slot);
617          break;
618       }
619
620       /*Fill Page PDU information*/
621       dlPageAlloc.pageDlSch.dlPagePduLen = pageInfo->msgLen;
622
623       SCH_ALLOC(dlPageAlloc.pageDlSch.dlPagePdu, sizeof(dlPageAlloc.pageDlSch.dlPagePduLen));
624
625       if(dlPageAlloc.pageDlSch.dlPagePdu == NULLP)
626       {
627          DU_LOG("\nERROR  --> SCH: Memory Allocation Failed during Page Resource allocation");
628          break;
629       }
630       memcpy(dlPageAlloc.pageDlSch.dlPagePdu, pageInfo->pagePdu, dlPageAlloc.pageDlSch.dlPagePduLen);
631
632       /* Send msg to MAC */
633       if(sendDlPageAllocToMac(&dlPageAlloc, schInst) != ROK)
634       {
635          DU_LOG("\nERROR  -->  SCH : Sending DL Paging allocation from SCH to MAC failed");
636          SCH_FREE(dlPageAlloc.pageDlSch.dlPagePdu, sizeof(dlPageAlloc.pageDlSch.dlPagePduLen));
637          break;
638       }
639       ret = ROK;
640       break;
641    }
642
643    /*Remove the Page Node*/
644    SCH_FREE(pageInfo->pagePdu, pageInfo->msgLen);
645    schDeleteFromPageInfoList(&(cell->pageCb.pageIndInfoRecord[currTime.sfn]), pageInfoNode);
646
647    return(ret);
648
649 }
650
651 /*******************************************************************
652  *
653  * @brief Handles slot indication at SCH 
654  *
655  * @details
656  *
657  *    Function : SchProcSlotInd
658  *
659  *    Functionality:
660  *     Handles TTI indication received from PHY
661  *
662  * @params[in] 
663  * @return ROK     - success
664  *         RFAILED - failure
665  *
666  * ****************************************************************/
667 uint8_t SchProcSlotInd(Pst *pst, SlotTimingInfo *slotInd)
668 {
669    uint8_t        ueIdx, ret = ROK;
670    uint16_t       slot;
671    DlSchedInfo    dlSchedInfo;
672    DlBrdcstAlloc  *dlBrdcstAlloc = NULLP;
673    SchCellCb      *cell = NULLP;
674    Inst           schInst = pst->dstInst-SCH_INST_START;
675    CmLList        *node = NULLP;
676    TotalPrbUsage  *dlTotalPrbUsage = NULLP;
677
678    cell = schCb[schInst].cells[schInst];
679    if(cell == NULLP)
680    {
681       DU_LOG("\nERROR  -->  SCH : Cell Does not exist");
682       return RFAILED;
683    }
684    memset(&dlSchedInfo, 0, sizeof(DlSchedInfo));
685    schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue, cell->numSlots);
686    dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
687    dlBrdcstAlloc->ssbTransmissionMode = NO_TRANSMISSION;
688    dlBrdcstAlloc->sib1TransmissionMode = NO_TRANSMISSION;
689
690    memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
691    dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
692
693    dlSchedInfo.cellId = cell->cellId;
694    slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
695
696 #ifdef NR_DRX 
697    schHandleStartDrxTimer(cell);
698 #endif
699    
700    /* Check for SSB occassion */
701    dlBrdcstAlloc->ssbTransmissionMode = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); 
702    if(dlBrdcstAlloc->ssbTransmissionMode)
703    {
704       if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
705       {
706          DU_LOG("\nERROR  -->  SCH : schBroadcastSsbAlloc failed");
707          dlBrdcstAlloc->ssbTransmissionMode = NO_TRANSMISSION;
708       }
709       else 
710       {
711          dlSchedInfo.isBroadcastPres = true;
712          if((dlBrdcstAlloc->ssbTransmissionMode == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
713             cell->firstSsbTransmitted = true;
714       }
715    }
716
717    /* Check for SIB1 occassion */
718    dlBrdcstAlloc->sib1TransmissionMode = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
719    if(dlBrdcstAlloc->sib1TransmissionMode)
720    {
721       if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
722       {
723          DU_LOG("\nERROR  -->  SCH : schBroadcastSib1Alloc failed");
724          dlBrdcstAlloc->sib1TransmissionMode = NO_TRANSMISSION;
725       }
726       else 
727       {
728          dlSchedInfo.isBroadcastPres = true;
729          if((dlBrdcstAlloc->sib1TransmissionMode == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
730             cell->firstSib1Transmitted = true;
731       }
732    }
733
734    /*Process Paging Msg*/
735    schProcDlPageAlloc(cell, *slotInd, schInst);
736
737    cell->api->SchScheduleSlot(cell, slotInd, schInst);
738
739    /* Check if any PDU is scheduled at this slot for any UE */
740    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
741    {
742       /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface 
743        * structure to send to MAC */
744       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
745       {
746          slot = dlSchedInfo.schSlotValue.rarTime.slot;
747          dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
748          cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
749       }
750
751       /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill 
752        * specific interface structure to send to MAC */
753       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
754       {
755          slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
756          dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
757          cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
758       }
759    }
760
761    if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.ulDciTime.slot]->ulGrant != NULLP)
762    {
763       slot = dlSchedInfo.schSlotValue.ulDciTime.slot;
764       dlSchedInfo.ulGrant = cell->schDlSlotInfo[slot]->ulGrant;
765       cell->schDlSlotInfo[slot]->ulGrant = NULLP;
766    }
767
768    /* Send msg to MAC */
769    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
770    if(ret != ROK)
771    {
772       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
773       return (ret);
774    }
775
776    /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
777    node = cmLListFirst(&schCb[schInst].statistics.activeKpiList.dlTotPrbUseList);
778    while(node)
779    {
780       dlTotalPrbUsage = (TotalPrbUsage *)node->node;
781       if(dlTotalPrbUsage)
782       {
783          dlTotalPrbUsage->numPrbUsedForTx += cell->schDlSlotInfo[slot]->prbAlloc.numPrbAlloc;
784          dlTotalPrbUsage->totalPrbAvailForTx += MAX_NUM_RB;
785       }
786       node = node->next;
787    }
788    
789    /* Re-initialize DL slot */
790    schInitDlSlot(cell->schDlSlotInfo[slot]);
791
792    /* Send UL Resource allocation to MAC */
793    schUlResAlloc(cell, schInst);
794
795 #ifdef NR_DRX 
796    schHandleExpiryDrxTimer(cell);
797 #endif   
798
799    return ret;
800 }
801
802 /**********************************************************************
803   End of file
804  **********************************************************************/
805
806