#include "sch.h"
#include "sch_utils.h"
-SchCb schCb[SCH_MAX_INST];
void SchFillCfmPst(Pst *reqPst,Pst *cfmPst,RgMngmt *cfm);
+
/* local defines */
SchCellCfgCfmFunc SchCellCfgCfmOpts[] =
{
for(uint8_t idx=0; idx<cnt; idx++)
{
/* start symbol determined using {2, 8} + 14n */
- ssbStartSymbArr[symbIdx++] = 2 + SCH_SYMBOL_PER_SLOT*idx;
- ssbStartSymbArr[symbIdx++] = 8 + SCH_SYMBOL_PER_SLOT*idx;
+ ssbStartSymbArr[symbIdx++] = 2 + MAX_SYMB_PER_SLOT*idx;
+ ssbStartSymbArr[symbIdx++] = 8 + MAX_SYMB_PER_SLOT*idx;
}
}
break;
for(uint8_t idx=0; idx<cnt; idx++)
{
/* start symbol determined using {4, 8, 16, 20} + 28n */
- ssbStartSymbArr[symbIdx++] = 4 + SCH_SYMBOL_PER_SLOT*idx;
- ssbStartSymbArr[symbIdx++] = 8 + SCH_SYMBOL_PER_SLOT*idx;
- ssbStartSymbArr[symbIdx++] = 16 + SCH_SYMBOL_PER_SLOT*idx;
- ssbStartSymbArr[symbIdx++] = 20 + SCH_SYMBOL_PER_SLOT*idx;
+ ssbStartSymbArr[symbIdx++] = 4 + MAX_SYMB_PER_SLOT*idx;
+ ssbStartSymbArr[symbIdx++] = 8 + MAX_SYMB_PER_SLOT*idx;
+ ssbStartSymbArr[symbIdx++] = 16 + MAX_SYMB_PER_SLOT*idx;
+ ssbStartSymbArr[symbIdx++] = 20 + MAX_SYMB_PER_SLOT*idx;
}
}
break;
SCH_ALLOC(schDlSlotInfo, sizeof(SchDlSlotInfo));
if(!schDlSlotInfo)
{
- DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb");
- return RFAILED;
+ DU_LOG("\nERROR --> SCH : Memory allocation failed in schInitCellCb");
+ return RFAILED;
}
/* UL Alloc */
uint8_t mValue = 0;
uint8_t firstSymbol = 0; /* need to calculate using formula mentioned in 38.213 */
uint8_t slotIndex = 0;
- /* TODO : This should be filled through freqDomRscAllocType0() */
- uint8_t FreqDomainResource[6] = {15, 0, 0, 0, 0, 0};
+ uint8_t FreqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
uint16_t tbSize = 0;
- uint8_t numPdschSymbols = 11; /* considering pdsch region from symbols 3 to 13 */
uint8_t ssbIdx = 0;
PdcchCfg *pdcch = &(sib1SchCfg->sib1PdcchCfg);
slotIndex = (int)((oValue*pow(2, mu)) + floor(ssbIdx*mValue))%numSlots;
sib1SchCfg->n0 = slotIndex;
- /* calculate the PRBs */
- //freqDomRscAllocType0(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
-
/* fill BWP */
switch(bandwidth)
{
pdcch->coresetCfg.coreSetSize = numRbs;
pdcch->coresetCfg.startSymbolIndex = firstSymbol;
pdcch->coresetCfg.durationSymbols = numSymbols;
- memcpy(pdcch->coresetCfg.freqDomainResource,FreqDomainResource,6);
+
+ /* Fill Bitmap for PRBs in coreset */
+ fillCoresetFeqDomAllocMap(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
+ covertFreqDomRsrcMapToIAPIFormat(FreqDomainResource, pdcch->coresetCfg.freqDomainResource);
+
pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
pdcch->coresetCfg.regBundleSize = 6; /* spec-38.211 sec 7.3.2.2 */
pdcch->coresetCfg.interleaverSize = 2; /* spec-38.211 sec 7.3.2.2 */
pdsch->dmrs.dmrsAddPos = DMRS_ADDITIONAL_POS;
pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
- pdsch->pdschFreqAlloc.freqAlloc.startPrb = offsetPointA + SCH_SSB_NUM_PRB + 1; /* the RB numbering starts from coreset0,
- and PDSCH is always above SSB */
- pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize,sib1SchCfg->sib1Mcs,numPdschSymbols);
+ /* the RB numbering starts from coreset0, and PDSCH is always above SSB */
+ pdsch->pdschFreqAlloc.freqAlloc.startPrb = offsetPointA + SCH_SSB_NUM_PRB;
+ pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize,sib1SchCfg->sib1Mcs, NUM_PDSCH_SYMBOL);
pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
pdsch->pdschTimeAlloc.rowIndex = 1;
/* This is Intel's requirement. PDSCH should start after PDSCH DRMS symbol */
pdsch->pdschTimeAlloc.timeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
- pdsch->pdschTimeAlloc.timeAlloc.numSymb = numPdschSymbols;
+ pdsch->pdschTimeAlloc.timeAlloc.numSymb = NUM_PDSCH_SYMBOL;
pdsch->beamPdschInfo.numPrgs = 1;
pdsch->beamPdschInfo.prgSize = 1;
pdsch->beamPdschInfo.digBfInterfaces = 0;
SchCellCfgCfm schCellCfgCfm;
Pst rspPst;
Inst inst = pst->dstInst-1;
+ uint8_t coreset0Idx = 0;
+ uint8_t numRbs = 0;
+ uint8_t offset = 0;
+ uint8_t freqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
SchPdschConfig pdschCfg;
#ifdef CALL_FLOW_DEBUG_LOG
schCellCfg->ssbSchCfg.ssbOffsetPointA);
memcpy(&cellCb->cellCfg, schCellCfg, sizeof(SchCellCfg));
+ /* Fill coreset frequencyDomainResource bitmap */
+ coreset0Idx = cellCb->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.coresetId;
+ numRbs = coresetIdxTable[coreset0Idx][1];
+ offset = coresetIdxTable[coreset0Idx][3];
+ fillCoresetFeqDomAllocMap(((cellCb->cellCfg.ssbSchCfg.ssbOffsetPointA - offset)/6), (numRbs/6), freqDomainResource);
+ covertFreqDomRsrcMapToIAPIFormat(freqDomainResource, \
+ cellCb->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc);
+
/* Fill K0 - K1 table for common cfg*/
BuildK0K1Table(cellCb, &cellCb->cellCfg.schInitialDlBwp.k0K1InfoTbl, true, cellCb->cellCfg.schInitialDlBwp.pdschCommon,
pdschCfg, DEFAULT_UL_ACK_LIST_COUNT, defaultUlAckTbl);
{
uint8_t lcId = 0;
uint16_t ueIdx = 0;
- uint16_t slot;
+ uint16_t slot = 0;
#ifdef NR_TDD
uint16_t slotIdx = 0;
#endif
+ DlMsgInfo dlMsgInfo;
SchUeCb *ueCb = NULLP;
SchCellCb *cell = NULLP;
SchDlSlotInfo *schDlSlotInfo = NULLP;
ueCb = &cell->ueCb[ueIdx-1];
lcId = dlBoInfo->lcId;
- if(lcId == SRB1_LCID || lcId == SRB2_LCID || lcId == SRB3_LCID || \
- (lcId >= MIN_DRB_LCID && lcId <= MAX_DRB_LCID))
+ memset(&dlMsgInfo, 0, sizeof(DlMsgInfo));
+ dlMsgInfo.crnti = dlBoInfo->crnti;
+ dlMsgInfo.ndi = 1;
+ dlMsgInfo.harqProcNum = 0;
+ dlMsgInfo.dlAssignIdx = 0;
+ dlMsgInfo.pucchTpc = 0;
+ dlMsgInfo.pucchResInd = 0;
+ dlMsgInfo.harqFeedbackInd = 0;
+ dlMsgInfo.dciFormatId = 1;
+
+ if(lcId == SRB0_LCID)
{
- SET_ONE_BIT(ueIdx, cell->boIndBitMap);
- ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
+ cell->raCb[ueIdx -1].msg4recvd = true;
+ dlMsgInfo.dlMsgPduLen = dlBoInfo->dataVolume;
+ cell->raCb[ueIdx -1].dlMsgInfo = dlMsgInfo;
}
- else if(lcId != SRB0_LCID)
+ else
{
- DU_LOG("\nERROR --> SCH : Invalid LC Id %d in MacSchDlRlcBoInfo", lcId);
- return RFAILED;
- }
+ /* TODO : These part of changes will be corrected during DL scheduling as
+ * per K0 - K1 -K2 */
+ if(lcId == SRB1_LCID || lcId == SRB2_LCID || lcId == SRB3_LCID || \
+ (lcId >= MIN_DRB_LCID && lcId <= MAX_DRB_LCID))
+ {
+ SET_ONE_BIT(ueIdx, cell->boIndBitMap);
+ if(ueCb->dlInfo.dlLcCtxt[lcId].lcId == lcId)
+ {
+ ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
+ }
+ else
+ {
+ DU_LOG("ERROR --> SCH: LCID:%d is not configured in SCH Cb",lcId);
+ return RFAILED;
+ }
+ }
+ else if(lcId != SRB0_LCID)
+ {
+ DU_LOG("\nERROR --> SCH : Invalid LC Id %d in MacSchDlRlcBoInfo", lcId);
+ return RFAILED;
+ }
- slot = (cell->slotInfo.slot + SCHED_DELTA + PHY_DELTA_DL + BO_DELTA) % cell->numSlots;
+ slot = (cell->slotInfo.slot + SCHED_DELTA + PHY_DELTA_DL + BO_DELTA) % cell->numSlots;
#ifdef NR_TDD
- while(schGetSlotSymbFrmt(cell->slotFrmtBitMap, slot) != DL_SLOT)
- {
- slot = (slot + 1)%cell->numSlots;
- slotIdx++;
- if(slotIdx==cell->numSlots)
+ while(schGetSlotSymbFrmt(cell->slotFrmtBitMap, slot) != DL_SLOT)
{
- DU_LOG("\nERROR --> SCH : No DL Slot available");
- return RFAILED;
+ slot = (slot + 1)%cell->numSlots;
+ slotIdx++;
+ if(slotIdx==cell->numSlots)
+ {
+ DU_LOG("\nERROR --> SCH : No DL Slot available");
+ return RFAILED;
+ }
}
- }
#endif
- schDlSlotInfo = cell->schDlSlotInfo[slot];
+ schDlSlotInfo = cell->schDlSlotInfo[slot];
+ if(schDlSlotInfo == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH : MacSchDlRlcBoInfo(): schDlSlotInfo does not exists");
+ return RFAILED;
+ }
- if(schDlSlotInfo == NULLP)
- {
- DU_LOG("\nERROR --> SCH : MacSchDlRlcBoInfo(): schDlSlotInfo does not exists");
- return RFAILED;
- }
- SCH_ALLOC(schDlSlotInfo->dlMsgInfo, sizeof(DlMsgInfo));
- if(schDlSlotInfo->dlMsgInfo == NULLP)
- {
- DU_LOG("\nERROR --> SCH : Memory allocation failed for dlMsgInfo");
- schDlSlotInfo = NULL;
- return RFAILED;
- }
-
- schDlSlotInfo->dlMsgInfo->crnti = dlBoInfo->crnti;
- schDlSlotInfo->dlMsgInfo->ndi = 1;
- schDlSlotInfo->dlMsgInfo->harqProcNum = 0;
- schDlSlotInfo->dlMsgInfo->dlAssignIdx = 0;
- schDlSlotInfo->dlMsgInfo->pucchTpc = 0;
- schDlSlotInfo->dlMsgInfo->pucchResInd = 0;
- schDlSlotInfo->dlMsgInfo->harqFeedbackInd = 0;
- schDlSlotInfo->dlMsgInfo->dciFormatId = 1;
- if(lcId == SRB0_LCID)
- {
- schDlSlotInfo->dlMsgInfo->isMsg4Pdu = true;
- schDlSlotInfo->dlMsgInfo->dlMsgPduLen = dlBoInfo->dataVolume;
+ SCH_ALLOC(schDlSlotInfo->dlMsgAlloc, sizeof(DlMsgAlloc));
+ if(schDlSlotInfo->dlMsgAlloc == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH : Memory allocation failed for dlMsgInfo");
+ schDlSlotInfo = NULL;
+ return RFAILED;
+ }
+
+ schDlSlotInfo->dlMsgAlloc->dlMsgInfo = dlMsgInfo;
}
return ROK;
}
}
return ROK;
}
+
+/*******************************************************************
+ *
+ * @brief Allocates requested PRBs for DL
+ *
+ * @details
+ *
+ * Function : allocatePrbDl
+ *
+ * Functionality:
+ * Allocates requested PRBs in DL
+ * Keeps track of allocated PRB (using bitmap) and remaining PRBs
+ *
+ * @params[in] prbAlloc table
+ * Start symbol
+ * Number of symbols
+ * Start PRB
+ * Number of PRBs
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \
+ uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
+{
+ uint8_t symbol = 0;
+ uint16_t broadcastPrbStart=0, broadcastPrbEnd=0;
+ FreePrbBlock *freePrbBlock = NULLP;
+ CmLList *freePrbNode = NULLP;
+ PduTxOccsaion ssbOccasion=0, sib1Occasion=0;
+ SchDlSlotInfo *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
+ SchPrbAlloc *prbAlloc = &schDlSlotInfo->prbAlloc;
+
+ /* If startPrb is set to MAX_NUM_RB, it means startPrb is not known currently.
+ * Search for an appropriate location in PRB grid and allocate requested resources */
+ if(*startPrb == MAX_NUM_RB)
+ {
+ /* Check if SSB/SIB1 is also scheduled in this slot */
+ ssbOccasion = schCheckSsbOcc(cell, slotTime);
+ sib1Occasion = schCheckSib1Occ(cell, slotTime);
+
+ if(ssbOccasion && sib1Occasion)
+ {
+ broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
+ broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
+ }
+ else if(ssbOccasion)
+ {
+ broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
+ broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB -1;
+ }
+ else if(sib1Occasion)
+ {
+ broadcastPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
+ broadcastPrbEnd = broadcastPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
+ }
+
+ /* Iterate through all free PRB blocks */
+ freePrbNode = prbAlloc->freePrbBlockList.first;
+ while(freePrbNode)
+ {
+ freePrbBlock = (FreePrbBlock *)freePrbNode->node;
+
+ /* If broadcast message is scheduled in this slot, then check if its PRBs belong to the current free block.
+ * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
+ if((ssbOccasion || sib1Occasion) &&
+ ((broadcastPrbStart >= freePrbBlock->startPrb) && (broadcastPrbStart <= freePrbBlock->endPrb)) && \
+ ((broadcastPrbEnd >= freePrbBlock->startPrb) && (broadcastPrbEnd <= freePrbBlock->endPrb)))
+ {
+ /* Implmentation is done such that highest-numbered free-RB is allocated first */
+ if((freePrbBlock->endPrb > broadcastPrbEnd) && ((freePrbBlock->endPrb - broadcastPrbEnd) >= numPrb))
+ {
+ /* If sufficient free PRBs are available above bradcast message then,
+ * endPrb = freePrbBlock->endPrb
+ * startPrb = endPrb - numPrb +1;
+ */
+ *startPrb = freePrbBlock->endPrb - numPrb +1;
+ break;
+ }
+ else if((broadcastPrbStart > freePrbBlock->startPrb) && ((broadcastPrbStart - freePrbBlock->startPrb) >= numPrb))
+ {
+ /* If free PRBs are available below broadcast message then,
+ * endPrb = broadcastPrbStart - 1
+ * startPrb = endPrb - numPrb +1
+ */
+ *startPrb = broadcastPrbStart - numPrb;
+ break;
+ }
+ else
+ {
+ freePrbNode = freePrbNode->next;
+ continue;
+ }
+ }
+ else
+ {
+ /* Check if requested number of blocks can be allocated from the current block */
+ if (freePrbBlock->numFreePrb < numPrb)
+ {
+ freePrbNode = freePrbNode->next;
+ continue;
+ }
+ *startPrb = freePrbBlock->endPrb - numPrb +1;
+ break;
+ }
+ }
+
+ /* If no free block can be used to allocated request number of RBs */
+ if(*startPrb == MAX_NUM_RB)
+ return RFAILED;
+ }
+
+ /* If startPrb is known already, check if requested PRBs are available for allocation */
+ else
+ {
+ freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
+ if(!freePrbNode)
+ {
+ DU_LOG("\nERROR --> SCH: Requested DL PRB unavailable");
+ return RFAILED;
+ }
+ }
+
+ /* Update bitmap to allocate PRBs */
+ for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
+ {
+ if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
+ {
+ DU_LOG("\nERROR --> SCH: fillPrbBitmap() failed for symbol [%d] in DL", symbol);
+ return RFAILED;
+ }
+ }
+
+ /* Update the remaining number for free PRBs */
+ removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Allocates requested PRBs for UL
+ *
+ * @details
+ *
+ * Function : allocatePrbUl
+ *
+ * Functionality:
+ * Allocates requested PRBs in UL
+ * Keeps track of allocated PRB (using bitmap) and remaining PRBs
+ *
+ * @params[in] prbAlloc table
+ * Start symbol
+ * Number of symbols
+ * Start PRB
+ * Number of PRBs
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \
+ uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
+{
+ uint8_t symbol = 0;
+ uint16_t prachStartPrb, prachNumPrb, prachEndPrb;
+ bool isPrachOccasion;
+ FreePrbBlock *freePrbBlock = NULLP;
+ CmLList *freePrbNode = NULLP;
+ SchPrbAlloc *prbAlloc = &cell->schUlSlotInfo[slotTime.slot]->prbAlloc;
+
+ /* If startPrb is set to MAX_NUM_RB, it means startPrb is not known currently.
+ * Search for an appropriate location in PRB grid and allocate requested resources */
+ if(*startPrb == MAX_NUM_RB)
+ {
+ /* Check if PRACH is also scheduled in this slot */
+ isPrachOccasion = schCheckPrachOcc(cell, slotTime);
+ if(isPrachOccasion)
+ {
+ prachStartPrb = cell->cellCfg.schRachCfg.msg1FreqStart;
+ prachNumPrb = schCalcPrachNumRb(cell);
+ prachEndPrb = prachStartPrb + prachNumPrb -1;
+ }
+
+ /* Iterate through all free PRB blocks */
+ freePrbNode = prbAlloc->freePrbBlockList.first;
+ while(freePrbNode)
+ {
+ freePrbBlock = (FreePrbBlock *)freePrbNode->node;
+
+ /* If PRACH is scheduled in this slot, then check if its PRBs belong to the current free block.
+ * PRBs required for PRACH cannot be allocated to any other message */
+ if((isPrachOccasion) &&
+ ((prachStartPrb >= freePrbBlock->startPrb) && (prachStartPrb <= freePrbBlock->endPrb)) &&
+ ((prachEndPrb >= freePrbBlock->startPrb) && (prachEndPrb <= freePrbBlock->endPrb)))
+ {
+ /* Implmentation is done such that highest-numbered free-RB is allocated first */
+ if((freePrbBlock->endPrb > prachEndPrb) && ((freePrbBlock->endPrb - prachEndPrb) >= numPrb))
+ {
+ /* If sufficient free PRBs are available above PRACH message then,
+ * endPrb = freePrbBlock->endPrb
+ * startPrb = endPrb - numPrb +1;
+ */
+ *startPrb = freePrbBlock->endPrb - numPrb +1;
+ break;
+ }
+ else if((prachStartPrb > freePrbBlock->startPrb) && ((prachStartPrb - freePrbBlock->startPrb) >= numPrb))
+ {
+ /* If free PRBs are available below PRACH message then,
+ * endPrb = prachStartPrb - 1
+ * startPrb = endPrb - numPrb +1
+ */
+ *startPrb = prachStartPrb - numPrb;
+ break;
+ }
+ else
+ {
+ freePrbNode = freePrbNode->next;
+ continue;
+ }
+ }
+ else
+ {
+ /* Check if requested number of PRBs can be allocated from currect block */
+ if(freePrbBlock->numFreePrb < numPrb)
+ {
+ freePrbNode = freePrbNode->next;
+ continue;
+ }
+ *startPrb = freePrbBlock->endPrb - numPrb +1;
+ break;
+ }
+ }
+
+ /* If no free block can be used to allocated requested number of RBs */
+ if(*startPrb == MAX_NUM_RB)
+ return RFAILED;
+ }
+ else
+ {
+ /* If startPrb is known already, check if requested PRBs are available for allocation */
+ freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
+ if(!freePrbNode)
+ {
+ DU_LOG("\nERROR --> SCH: Requested UL PRB unavailable");
+ return RFAILED;
+ }
+ }
+
+ /* Update bitmap to allocate PRBs */
+ for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
+ {
+ if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
+ {
+ DU_LOG("\nERROR --> SCH: fillPrbBitmap() failed for symbol [%d] in UL", symbol);
+ return RFAILED;
+ }
+ }
+
+ /* Update the remaining number for free PRBs */
+ removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
+
+ return ROK;
+}
+
+/*******************************************************************************
+ *
+ * @brief Try to find Best Free Block with Max Num PRB
+ *
+ * @details
+ *
+ * Function : searchLargestFreeBlockDL
+ *
+ * Functionality:
+ * Finds the FreeBlock with MaxNum of FREE PRB considering SSB/SIB1 ocassions.
+ *
+ * @params[in] I/P > prbAlloc table (FreeBlock list)
+ * I/P > Slot timing Info
+ * O/P > Start PRB
+ *
+ *
+ * @return Max Number of Free PRB
+ * If 0, then no Suitable Free Block
+ *
+ * ********************************************************************************/
+
+uint16_t searchLargestFreeBlockDL(SchCellCb *cell, SlotTimingInfo slotTime,uint16_t *startPrb)
+{
+ uint16_t broadcastPrbStart=0, broadcastPrbEnd=0, maxFreePRB = 0;
+ PduTxOccsaion ssbOccasion=0, sib1Occasion=0;
+ FreePrbBlock *freePrbBlock = NULLP;
+ CmLList *freePrbNode = NULLP;
+
+ SchDlSlotInfo *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
+ SchPrbAlloc *prbAlloc = &schDlSlotInfo->prbAlloc;
+
+ ssbOccasion = schCheckSsbOcc(cell, slotTime);
+ sib1Occasion = schCheckSib1Occ(cell, slotTime);
+
+ if(ssbOccasion && sib1Occasion)
+ {
+ broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
+ broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
+ }
+ else if(ssbOccasion)
+ {
+ broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
+ broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB -1;
+ }
+ else if(sib1Occasion)
+ {
+ broadcastPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
+ broadcastPrbEnd = broadcastPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
+ }
+
+
+ freePrbNode = prbAlloc->freePrbBlockList.first;
+ *startPrb = 0; /*Initialize the StartPRB to zero*/
+ while(freePrbNode)
+ {
+ freePrbBlock = (FreePrbBlock *)freePrbNode->node;
+
+ /*For block with same numFreeBlocks, choose the one with HighestPRB range
+ *Since FreeBLockList are arranged in Descending order of PRB range thus Skipping this block*/
+ if(maxFreePRB >= freePrbBlock->numFreePrb)
+ {
+ //skip this block
+ freePrbNode = freePrbNode->next;
+ continue;
+ }
+
+ /* If broadcast message is scheduled in this slot, then check if its PRBs belong to the current free block.
+ * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
+ if((ssbOccasion || sib1Occasion) &&
+ ((broadcastPrbStart >= freePrbBlock->startPrb) && (broadcastPrbStart <= freePrbBlock->endPrb)) && \
+ ((broadcastPrbEnd >= freePrbBlock->startPrb) && (broadcastPrbEnd <= freePrbBlock->endPrb)))
+ {
+
+ /* Implmentation is done such that highest-numbered free-RB is Checked first
+ and freePRB in this block is greater than Max till now */
+ if((freePrbBlock->endPrb > broadcastPrbEnd) && ((freePrbBlock->endPrb - broadcastPrbEnd) > maxFreePRB))
+ {
+ /* If sufficient free PRBs are available above broadcast message*/
+ *startPrb = broadcastPrbEnd + 1;
+ maxFreePRB = (freePrbBlock->endPrb - broadcastPrbEnd);
+ }
+ /*Also check the other freeBlock (i.e. Above the broadcast message) for MAX FREE PRB*/
+ if((broadcastPrbStart > freePrbBlock->startPrb) && ((broadcastPrbStart - freePrbBlock->startPrb) > maxFreePRB))
+ {
+ /* If free PRBs are available below broadcast message*/
+ *startPrb = freePrbBlock->startPrb;
+ maxFreePRB = (broadcastPrbStart - freePrbBlock->startPrb);
+ }
+ }
+ else //Best Block
+ {
+ if(maxFreePRB < freePrbBlock->numFreePrb)
+ {
+ *startPrb = freePrbBlock->startPrb;
+ maxFreePRB = freePrbBlock->numFreePrb;
+ }
+
+ }
+ freePrbNode = freePrbNode->next;
+ }
+ return(maxFreePRB);
+}
+
/**********************************************************************
End of file
**********************************************************************/