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