+/*******************************************************************************
+################################################################################
+# Copyright (c) [2017-2019] [Radisys] #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+################################################################################
+ *******************************************************************************/
+
+/* This file contains UE management handling functionality for MAC */
+
+/* header include files (.h) */
+#include "common_def.h"
+#include "tfu.h"
+#include "lrg.h"
+
+#include "tfu.x"
+#include "lrg.x"
+
+#include "du_app_mac_inf.h"
+#include "mac.h"
+#include "du_log.h"
+
+/* function pointers for packing slot ind from mac to sch */
+MacSchUeCreateReqFunc macSchUeCreateReqOpts[] =
+{
+ packMacSchUeCreateReq, /* packing for loosely coupled */
+ macSchUeCreateReq, /* packing for tightly coupled */
+ packMacSchUeCreateReq /* packing for light weight loosely coupled */
+};
+
+DuMacUeCreateRspFunc DuMacUeCreateRspOpts[] =
+{
+ packDuMacUeCreateRsp, /* packing for loosely coupled */
+ duHandleMacUeCreateRsp, /* packing for tightly coupled */
+ packDuMacUeCreateRsp, /* packing for light weight loosly coupled */
+};
+
+/*******************************************************************
+ *
+ * @brief Fills mac cell group config to be sent to scheduler
+ *
+ * @details
+ *
+ * Function : fillMacCellGroupCfg
+ *
+ * Functionality: Fills mac cell group config to be sent to sch
+ *
+ * @params[in] macCellGrp : mac cell group config at MAC
+ * *macCellGrpCfg : mac cell group cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillMacCellGroupCfg(MacCellGrpCfg macCellGrp, SchMacCellGrpCfg *macCellGrpCfg)
+{
+ uint8_t idx;
+ SchSchedReqCfg *schedReqCfg;
+ SchTagCfg *tagCfg;
+
+ /* Copy scheduling request config */
+ schedReqCfg = &macCellGrpCfg->schedReqCfg;
+ schedReqCfg->addModListCount = macCellGrp.schReqCfg.addModListCount;
+ if(schedReqCfg->addModListCount > MAX_NUM_SR_CFG_PER_CELL_GRP)
+ {
+ DU_LOG("\nMAC : Scheduling Request Add/Mod Count %d exceeds max limit %d", \
+ schedReqCfg->addModListCount, MAX_NUM_SR_CFG_PER_CELL_GRP);
+ return RFAILED;
+ }
+ for(idx = 0; idx < schedReqCfg->addModListCount; idx++)
+ {
+ schedReqCfg->addModList[idx].schedReqId = \
+ macCellGrp.schReqCfg.addModList[idx].schedReqId;
+ schedReqCfg->addModList[idx].srProhibitTmr = \
+ macCellGrp.schReqCfg.addModList[idx].srProhibitTmr;
+ schedReqCfg->addModList[idx].srTransMax = \
+ macCellGrp.schReqCfg.addModList[idx].srTransMax;
+ }
+ schedReqCfg->relListCount = macCellGrp.schReqCfg.relListCount;
+
+ /* copy TAG config */
+ tagCfg = &macCellGrpCfg->tagCfg;
+ tagCfg->addModListCount = macCellGrp.tagCfg.addModListCount;
+ if(tagCfg->addModListCount > MAX_NUM_TAGS)
+ {
+ DU_LOG("\nMAC : Scheduling Request Add/Mod Count %d exceeds max limit %d", \
+ tagCfg->addModListCount, MAX_NUM_TAGS);
+ return RFAILED;
+ }
+ for(idx = 0; idx < tagCfg->addModListCount; idx++)
+ {
+ tagCfg->addModList[idx].tagId = \
+ macCellGrp.tagCfg.addModList[idx].tagId;
+ tagCfg->addModList[idx].timeAlignmentTmr = \
+ macCellGrp.tagCfg.addModList[idx].timeAlignTimer;
+ }
+ tagCfg->relListCount = macCellGrp.tagCfg.relListCount;
+
+ /* Copy PHR config */
+ if(macCellGrp.phrCfgSetupPres)
+ {
+ macCellGrpCfg->phrCfg.periodicTmr = macCellGrp.phrCfg.periodicTimer;
+ macCellGrpCfg->phrCfg.prohibitTmr = macCellGrp.phrCfg.prohibitTimer;
+ macCellGrpCfg->phrCfg.txpowerFactorChange = macCellGrp.phrCfg.txPowerFactor;
+ macCellGrpCfg->phrCfg.multiplePhr = macCellGrp.phrCfg.multiplePHR;
+ macCellGrpCfg->phrCfg.dummy = macCellGrp.phrCfg.dummy;
+ macCellGrpCfg->phrCfg.type2OtherCell = macCellGrp.phrCfg.phrType2OtherCell;
+ macCellGrpCfg->phrCfg.modeOtherCG = macCellGrp.phrCfg.phrOtherCG;
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills phy cell group config to be sent to scheduler
+ *
+ * @details
+ *
+ * Function : fillPhyCellGroupCfg
+ *
+ * Functionality: Fills phy cell group config to be sent to sch
+ *
+ * @params[in] macUeCfg : Phy cell group config at MAC
+ * *schPhyCellGrp : phy cell group config to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillPhyCellGroupCfg(PhyCellGrpCfg macUeCfg, SchPhyCellGrpCfg *schPhyCellGrp)
+{
+ schPhyCellGrp->pdschHarqAckCodebook = macUeCfg.pdschHarqAckCodebook;
+ schPhyCellGrp->pNrFr1 = macUeCfg.pNrFr1;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills PDSCh serving cell config to send to scheduler
+ *
+ * @details
+ *
+ * Function : fillPdschServCellCfg
+ *
+ * Functionality: Fills PDSCh serving cell config to send to scheduler
+ *
+ * @params[in] macPdschCfg : Pdsch serving cell config at MAC
+ * *schPdschCfg : Pdsch serving cell config to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillPdschServCellCfg(PdschServCellCfg macPdschCfg, SchPdschServCellCfg *schPdschCfg)
+{
+ schPdschCfg->maxMimoLayers = NULL;
+ if(macPdschCfg.maxMimoLayers)
+ {
+ /* TODO : Optional parameter */
+ }
+
+ schPdschCfg->numHarqProcForPdsch = \
+ macPdschCfg.numHarqProcForPdsch;
+
+ schPdschCfg->maxCodeBlkGrpPerTb = NULL;
+ if(macPdschCfg.maxCodeBlkGrpPerTb)
+ {
+ /* TODO : Optional parameter */
+ }
+
+ schPdschCfg->codeBlkGrpFlushInd = NULL;
+ if(macPdschCfg.codeBlkGrpFlushInd)
+ {
+ /* TODO : Optional parameter */
+ }
+
+ schPdschCfg->xOverhead = NULL;
+ if(macPdschCfg.xOverhead)
+ {
+ /* TODO : Optional parameter */
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills PUSCH cofig in initial UL BWP config for SCH UE Cfg
+ *
+ * @details
+ *
+ * Function : fillInitalUlBwpPuschCfg
+ *
+ * Functionality:
+ * Fills PUSCH cofig in initial UL BWP config for SCH UE Cfg
+ *
+ * @params[in] macPuschCfg : Initial UL-BWP PUSCH cfg at MAC
+ * schPuschCfg : Initial UL-BWP PUSCH cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillInitalUlBwpPuschCfg(PuschCfg macPuschCfg, SchPuschCfg *schPuschCfg)
+{
+ uint8_t idx;
+
+ schPuschCfg->dmrsUlCfgForPuschMapTypeA.addPos = \
+ macPuschCfg.dmrsUlCfgForPuschMapTypeA.addPos;
+ schPuschCfg->dmrsUlCfgForPuschMapTypeA.transPrecodDisabled.scramblingId0 = \
+ macPuschCfg.dmrsUlCfgForPuschMapTypeA.transPrecodDisabled.scramblingId0;
+ schPuschCfg->resourceAllocType = macPuschCfg.resourceAllocType;
+
+ schPuschCfg->numTimeDomRsrcAlloc = macPuschCfg.numTimeDomRsrcAlloc;
+ if(schPuschCfg->numTimeDomRsrcAlloc > MAX_NUM_UL_ALLOC)
+ {
+ DU_LOG("\nMAC : Number of Time domain resource allocation [%d] exceeds max limit [%d]",\
+ schPuschCfg->numTimeDomRsrcAlloc, MAX_NUM_UL_ALLOC);
+ return RFAILED;
+ }
+ for(idx = 0; idx < schPuschCfg->numTimeDomRsrcAlloc; idx++)
+ {
+ schPuschCfg->timeDomRsrcAllocList[idx].k2 = \
+ macPuschCfg.timeDomRsrcAllocList[idx].k2;
+ schPuschCfg->timeDomRsrcAllocList[idx].mappingType = \
+ macPuschCfg.timeDomRsrcAllocList[idx].mappingType;
+ schPuschCfg->timeDomRsrcAllocList[idx].startSymbol = \
+ macPuschCfg.timeDomRsrcAllocList[idx].startSymbol;
+ schPuschCfg->timeDomRsrcAllocList[idx].symbolLength = \
+ macPuschCfg.timeDomRsrcAllocList[idx].symbolLength;
+ }
+
+ schPuschCfg->transformPrecoder = macPuschCfg.transformPrecoder;
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills initail UL BWP config to send to scheduler
+ *
+ * @details
+ *
+ * Function : fillInitialUlBwp
+ *
+ * Functionality: Fills initail UL BWP config to send to sch
+ *
+ * @params[in] macInitUlBwp : Initial UL BWP cfg at MAC
+ * schInitUlBwp : Initial UL BWP cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillInitialUlBwp(InitialUlBwp macInitUlBwp, SchInitialUlBwp *schInitUlBwp)
+{
+ schInitUlBwp->pucchCfgPres = macInitUlBwp.pucchPresent;
+ if(schInitUlBwp->pucchCfgPres)
+ {
+ /* TODO : Optional parameter */
+ }
+
+ schInitUlBwp->puschCfgPres = macInitUlBwp.puschPresent;
+ if(schInitUlBwp->puschCfgPres)
+ {
+ if(fillInitalUlBwpPuschCfg(macInitUlBwp.puschCfg, &schInitUlBwp->puschCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillInitalUlBwpPuschCfg() failed");
+ return RFAILED;
+ }
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill PDCCH cfg in Initial DL BWP for UE Cfg in Scheduler
+ *
+ * @details
+ *
+ * Function : fillInitDlBwpPdcchCfg
+ *
+ * Functionality:
+ * Fill PDCCH cfg in Initial DL BWP for UE Cfg in Scheduler
+ *
+ * @params[in] macPdcchCfg : Inital DL BWP PDCCH cfg in MAC
+ * schPdcchCfg : Inital DL BWP PDCCH cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillInitDlBwpPdcchCfg(PdcchConfig macPdcchCfg, SchPdcchConfig *schPdcchCfg)
+{
+ uint8_t idx;
+
+ /* Fill CORESET info */
+ schPdcchCfg->numCRsetToAddMod = macPdcchCfg.numCRsetToAddMod;
+ if(schPdcchCfg->numCRsetToAddMod > MAX_NUM_CRSET)
+ {
+ DU_LOG("\nMAC : Number of CORESET to ADD/MOD [%d] exceeds max limit [%d]",\
+ schPdcchCfg->numCRsetToAddMod, MAX_NUM_CRSET);
+ return RFAILED;
+ }
+
+ for(idx = 0; idx < schPdcchCfg->numCRsetToAddMod; idx++)
+ {
+ schPdcchCfg->cRSetToAddModList[idx].cRSetId = \
+ macPdcchCfg.cRSetToAddModList[idx].cRSetId;
+ memcpy(&schPdcchCfg->cRSetToAddModList[idx].freqDomainRsrc,\
+ &macPdcchCfg.cRSetToAddModList[idx].freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
+ schPdcchCfg->cRSetToAddModList[idx].duration = \
+ macPdcchCfg.cRSetToAddModList[idx].duration;
+ schPdcchCfg->cRSetToAddModList[idx].cceRegMappingType = \
+ macPdcchCfg.cRSetToAddModList[idx].cceRegMappingType;
+ schPdcchCfg->cRSetToAddModList[idx].precoderGranularity = \
+ macPdcchCfg.cRSetToAddModList[idx].precoderGranularity;
+ schPdcchCfg->cRSetToAddModList[idx].dmrsScramblingId = \
+ macPdcchCfg.cRSetToAddModList[idx].dmrsScramblingId;
+ }
+
+ schPdcchCfg->numCRsetToRel = macPdcchCfg.numCRsetToRel;
+ if(schPdcchCfg->numCRsetToAddMod > MAX_NUM_CRSET)
+ {
+ DU_LOG("\nMAC : Number of CORESET to release [%d] exceeds max limit [%d]",\
+ schPdcchCfg->numCRsetToRel, MAX_NUM_CRSET);
+ return RFAILED;
+ }
+
+ for(idx = 0; idx < schPdcchCfg->numCRsetToRel; idx++)
+ {
+ /* TODO */
+ }
+
+ /* Fill Search space info */
+ schPdcchCfg->numSearchSpcToAddMod = macPdcchCfg.numSearchSpcToAddMod;
+ if(schPdcchCfg->numSearchSpcToAddMod > MAX_NUM_SEARCH_SPC)
+ {
+ DU_LOG("\nMAC : Number of search space to ADD/MOD [%d] exceeds max [%d]", \
+ schPdcchCfg->numSearchSpcToAddMod, MAX_NUM_SEARCH_SPC);
+ return RFAILED;
+ }
+ for(idx = 0; idx < schPdcchCfg->numSearchSpcToAddMod; idx++)
+ {
+ schPdcchCfg->searchSpcToAddModList[idx].searchSpaceId = \
+ macPdcchCfg.searchSpcToAddModList[idx].searchSpaceId;
+ schPdcchCfg->searchSpcToAddModList[idx].cRSetId = \
+ macPdcchCfg.searchSpcToAddModList[idx].cRSetId;
+ schPdcchCfg->searchSpcToAddModList[idx].mSlotPeriodicityAndOffset = \
+ macPdcchCfg.searchSpcToAddModList[idx].mSlotPeriodicityAndOffset;
+ memcpy(&schPdcchCfg->searchSpcToAddModList[idx].mSymbolsWithinSlot,
+ &macPdcchCfg.searchSpcToAddModList[idx].mSymbolsWithinSlot, \
+ MONITORING_SYMB_WITHIN_SLOT_SIZE);
+ schPdcchCfg->searchSpcToAddModList[idx].numCandidatesAggLevel1 = \
+ macPdcchCfg.searchSpcToAddModList[idx].numCandidatesAggLevel1;
+ schPdcchCfg->searchSpcToAddModList[idx].numCandidatesAggLevel2 = \
+ macPdcchCfg.searchSpcToAddModList[idx].numCandidatesAggLevel2;
+ schPdcchCfg->searchSpcToAddModList[idx].numCandidatesAggLevel4 = \
+ macPdcchCfg.searchSpcToAddModList[idx].numCandidatesAggLevel4;
+ schPdcchCfg->searchSpcToAddModList[idx].numCandidatesAggLevel8 = \
+ macPdcchCfg.searchSpcToAddModList[idx].numCandidatesAggLevel8;
+ schPdcchCfg->searchSpcToAddModList[idx].numCandidatesAggLevel16 = \
+ macPdcchCfg.searchSpcToAddModList[idx].numCandidatesAggLevel16;
+ schPdcchCfg->searchSpcToAddModList[idx].searchSpaceType = \
+ macPdcchCfg.searchSpcToAddModList[idx].searchSpaceType;
+ schPdcchCfg->searchSpcToAddModList[idx].ueSpecificDciFormat = \
+ macPdcchCfg.searchSpcToAddModList[idx].ueSpecificDciFormat;
+ }
+
+ schPdcchCfg->numSearchSpcToRel = macPdcchCfg.numSearchSpcToRel;
+ if(schPdcchCfg->numSearchSpcToRel > MAX_NUM_SEARCH_SPC)
+ {
+ DU_LOG("\nMAC : Number of search space to release [%d] exceeds max [%d]", \
+ schPdcchCfg->numSearchSpcToRel, MAX_NUM_SEARCH_SPC);
+ return RFAILED;
+ }
+ for(idx = 0; idx < schPdcchCfg->numSearchSpcToRel; idx++)
+ {
+ /* TODO */
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill PDSCH cfg in Initial DL BWP for UE Cfg in Scheduler
+ *
+ * @details
+ *
+ * Function : fillInitDlBwpPdschCfg
+ *
+ * Functionality:
+ * Fill PDSCH cfg in Initial DL BWP for UE Cfg in Scheduler
+ *
+ * @params[in] macPdschCfg : Inital DL BWP PDSCH cfg at MAC
+ * schPdschCfg : Inital DL BWP PDSCH cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillInitDlBwpPdschCfg(PdschConfig macPdschCfg, SchPdschConfig *schPdschCfg)
+{
+ uint8_t idx;
+
+ schPdschCfg->dmrsDlCfgForPdschMapTypeA.addPos = \
+ macPdschCfg.dmrsDlCfgForPdschMapTypeA.addPos;
+ schPdschCfg->resourceAllocType = macPdschCfg.resourceAllocType;
+ schPdschCfg->numTimeDomRsrcAlloc = macPdschCfg.numTimeDomRsrcAlloc;
+ if(schPdschCfg->numTimeDomRsrcAlloc > MAX_NUM_DL_ALLOC)
+ {
+ DU_LOG("\nMAC : Number of time domain resource allocation [%d], exceeds\
+ max limit [%d]", schPdschCfg->numTimeDomRsrcAlloc, MAX_NUM_DL_ALLOC);
+ return RFAILED;
+ }
+
+ for(idx = 0; idx < schPdschCfg->numTimeDomRsrcAlloc; idx++)
+ {
+ schPdschCfg->timeDomRsrcAllociList[idx].mappingType = \
+ macPdschCfg.timeDomRsrcAllociList[idx].mappingType;
+ schPdschCfg->timeDomRsrcAllociList[idx].startSymbol = \
+ macPdschCfg.timeDomRsrcAllociList[idx].startSymbol;
+ schPdschCfg->timeDomRsrcAllociList[idx].symbolLength = \
+ macPdschCfg.timeDomRsrcAllociList[idx].symbolLength;
+ }
+
+ schPdschCfg->rbgSize = macPdschCfg.rbgSize;
+ schPdschCfg->numCodeWordsSchByDci = macPdschCfg.numCodeWordsSchByDci;
+ schPdschCfg->bundlingType = macPdschCfg.bundlingType;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill Initial DL BWP for SCH UE config
+ *
+ * @details
+ *
+ * Function : fillInitialDlBwp
+ *
+ * Functionality: Fill Initial DL BWP for SCH UE config
+ *
+ * @params[in] macInitDlBwp : Inital DL BWP cfg at MAC
+ * schInitDlBwp : Inital DL BWP cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillInitialDlBwp(InitialDlBwp macInitDlBwp, SchInitalDlBwp *schInitDlBwp)
+{
+ schInitDlBwp->pdcchCfgPres = macInitDlBwp.pdcchPresent;
+ if(schInitDlBwp->pdcchCfgPres)
+ {
+ if(fillInitDlBwpPdcchCfg(macInitDlBwp.pdcchCfg, &schInitDlBwp->pdcchCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillInitDlBwpPdcchCfg() failed");
+ return RFAILED;
+ }
+ }
+
+ schInitDlBwp->pdschCfgPres = macInitDlBwp.pdschPresent;
+ if(schInitDlBwp->pdschCfgPres)
+ {
+ if(fillInitDlBwpPdschCfg(macInitDlBwp.pdschCfg,&schInitDlBwp->pdschCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillInitDlBwpPdschCfg() failed");
+ return RFAILED;
+ }
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills Sp Cell config to be sent to scheduler
+ *
+ * @details
+ *
+ * Function : fillSpCellCfg
+ *
+ * Functionality: Fills Sp Cell config to be sent to scheduler
+ *
+ * @params[in] macSpCellCfg : SP cell cfg at MAC
+ * schSpCellCfg : SP cell cfg to be filled
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillSpCellCfg(SpCellCfg macSpCellCfg, SchSpCellCfg *schSpCellCfg)
+{
+ uint8_t idx;
+ SchServCellCfgInfo *servCellCfg;
+
+ schSpCellCfg->servCellIdx = macSpCellCfg.servCellIdx;
+ servCellCfg = &schSpCellCfg->servCellCfg;
+
+ /* Fill initial DL BWP */
+ if(fillInitialDlBwp(macSpCellCfg.servCellCfg.initDlBwp, \
+ &servCellCfg->initDlBwp) != ROK )
+ {
+ DU_LOG("\nMAC : fillInitialDlBwp() failed");
+ return RFAILED;
+ }
+
+ servCellCfg->numDlBwpToAdd = macSpCellCfg.servCellCfg.numDlBwpToAdd;
+ if(servCellCfg->numDlBwpToAdd > MAX_NUM_BWP)
+ {
+ DU_LOG("\nMAC : Number of DL BWP to ADD/MOD [%d] exceeds max limit [%d]",\
+ servCellCfg->numDlBwpToAdd, MAX_NUM_BWP);
+ return RFAILED;
+ }
+ for(idx = 0; idx < servCellCfg->numDlBwpToAdd; idx++)
+ {
+ /* TODO : As of now numDlBwpToAdd = 0 */
+ }
+
+ servCellCfg->firstActvDlBwpId = macSpCellCfg.servCellCfg.firstActvDlBwpId;
+ servCellCfg->defaultDlBwpId = macSpCellCfg.servCellCfg.defaultDlBwpId;
+ servCellCfg->bwpInactivityTmr = NULL;
+ if(macSpCellCfg.servCellCfg.bwpInactivityTmr)
+ {
+ /* TODO : This is an optional parameter, not filled currently */
+ }
+
+ /* Fill PDSCH serving cell config */
+ if(fillPdschServCellCfg(macSpCellCfg.servCellCfg.pdschServCellCfg, \
+ &servCellCfg->pdschServCellCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillPdschServCellCfg() failed");
+ return RFAILED;
+ }
+
+ /* Fill Initail UL BWP */
+ if(fillInitialUlBwp(macSpCellCfg.servCellCfg.initUlBwp, \
+ &servCellCfg->initUlBwp) != ROK)
+ {
+ DU_LOG("\nMAC : fillInitialUlBwp() failed");
+ return RFAILED;
+ }
+
+ servCellCfg->numUlBwpToAdd = macSpCellCfg.servCellCfg.numUlBwpToAdd;
+ if(servCellCfg->numUlBwpToAdd > MAX_NUM_BWP)
+ {
+ DU_LOG("\nMAC : Number of UL BWP to ADD/MOD [%d] exceeds max limit [%d]",\
+ servCellCfg->numUlBwpToAdd, MAX_NUM_BWP);
+ return RFAILED;
+ }
+ for(idx = 0; idx < servCellCfg->numUlBwpToAdd; idx++)
+ {
+ /* TODO : As of now numDlBwpToAdd = 0 */
+ }
+ servCellCfg->firstActvUlBwpId = macSpCellCfg.servCellCfg.firstActvUlBwpId;
+
+ return ROK;
+}
+
+
+/*******************************************************************
+ *
+ * @brief Fill logical channel configuration
+ *
+ * @details
+ *
+ * Function : fillLogicalChannelCfg
+ *
+ * Functionality: Fill logical channel configuration
+ *
+ * @params[in] macLcCfg : Logical channel Cfg at MAC
+ * schLcCfg : LC cfg to fill at scheduler
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillLogicalChannelCfg(LcCfg macLcCfg, SchLcCfg *schLcCfg)
+{
+ schLcCfg->lcId = macLcCfg.lcId;
+ schLcCfg->dlLcCfg.lcp = macLcCfg.dlLcCfg.lcp;
+
+ schLcCfg->drbQos = NULL;
+ if(macLcCfg.drbQos)
+ {
+ /* TODO : Optional Parameter */
+ }
+
+ schLcCfg->snssai = NULL;
+ if(macLcCfg.snssai)
+ {
+ /* TODO : Optional Parameter */
+ }
+
+ schLcCfg->ulLcCfg = NULL;
+ if(macLcCfg.ulLcCfg)
+ {
+ /* TODO : Optional Parameter */
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills and sends UE configuration to Scheduler
+ *
+ * @details
+ *
+ * Function : sendAddUeCreateReqToSch
+ *
+ * Functionality: Fills and sends UE configuration to Scheduler
+ *
+ * @params[in] Ue configuration from DU APP
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t sendAddUeCreateReqToSch(MacUeCfg *ueCfg)
+{
+ Pst pst;
+ uint8_t idx;
+ SchUeCfg schUeCfg;
+
+ schUeCfg.cellId = ueCfg->cellId;
+ schUeCfg.crnti = ueCfg->crnti;
+
+ /* Copy MAC cell group config */
+ memset(&schUeCfg.macCellGrpCfg, 0, sizeof(SchMacCellGrpCfg));
+ if(fillMacCellGroupCfg(ueCfg->macCellGrpCfg, &schUeCfg.macCellGrpCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillMacCellGroupCfg() failed");
+ return RFAILED;
+ }
+
+ /* Copy Physical cell group config */
+ memset(&schUeCfg.phyCellGrpCfg, 0,sizeof(SchPhyCellGrpCfg));
+ if(fillPhyCellGroupCfg(ueCfg->phyCellGrpCfg, &schUeCfg.phyCellGrpCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillPhyCellGroupCfg() failed");
+ return RFAILED;
+ }
+
+ /* Copy sp cell config */
+ memset(&schUeCfg.spCellCfg, 0, sizeof(SchSpCellCfg));
+ if(fillSpCellCfg(ueCfg->spCellCfg, &schUeCfg.spCellCfg) != ROK)
+ {
+ DU_LOG("\nMAC : fillSpCellCfg() failed");
+ return RFAILED;
+ }
+
+ schUeCfg.aggrMaxBitRate = NULL;
+ if(ueCfg->maxAggrBitRate != NULL)
+ {
+
+ MAC_ALLOC(schUeCfg.aggrMaxBitRate, sizeof(SchAggrMaxBitRate));
+ if(!schUeCfg.aggrMaxBitRate)
+ {
+ DU_LOG("\nMAC : Memory allocation failed in sendAddUeCreateReqToSch");
+ return RFAILED;
+ }
+ schUeCfg.aggrMaxBitRate->ulBitRate = ueCfg->maxAggrBitRate->ulBits;
+ schUeCfg.aggrMaxBitRate->dlBitRate = ueCfg->maxAggrBitRate->dlBits;
+ }
+
+ schUeCfg.numLc = ueCfg->numLcs;
+ if(schUeCfg.numLc > MAX_NUM_LOGICAL_CHANNELS)
+ {
+ DU_LOG("\nMAC : Number of Logical channels %d exceeds max limit %d",\
+ schUeCfg.numLc, MAX_NUM_LOGICAL_CHANNELS);
+ }
+ for(idx = 0; idx < schUeCfg.numLc; idx++)
+ {
+ if(fillLogicalChannelCfg(ueCfg->lcCfgList[idx], &schUeCfg.lcCfgList[idx]) != ROK)
+ {
+ DU_LOG("\nMAC : fillLogicalChannelCfg() failed");
+ return RFAILED;
+ }
+ }
+
+ fillMacToSchPst(&pst);
+ pst.event = EVENT_UE_CREATE_REQ_TO_SCH;
+
+ return(*macSchUeCreateReqOpts[pst.selector])(&pst, &schUeCfg);
+}
+
+/*******************************************************************
+ *
+ * @brief Creates UE Cb and fills ueCfg
+ *
+ * @details
+ *
+ * Function : createUeCb
+ *
+ * Functionality: Creates UE Cb and fills ueCfg
+ *
+ * @params[in] MAC UE Configuration
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t createUeCb(MacUeCfg *ueCfg)
+{
+ uint16_t ueIdx, lcIdx;
+ MacUeCb *ueCb;
+
+ /* Validate cell id */
+ if(macCb.macCell->cellId != ueCfg->cellId)
+ {
+ DU_LOG("\nMAC : Cell Id %d not configured", ueCfg->cellId);
+ return RFAILED;
+ }
+
+ /* Check if max number of UE configured */
+ if(macCb.macCell->numActvUe > MAX_UE)
+ {
+ DU_LOG("MAC : Max number of UE [%d] already configured", MAX_UE);
+ return RFAILED;
+ }
+
+ /* Check if UE already configured */
+ ueCb = &macCb.macCell->ueCb[ueCfg->ueIdx];
+ if(ueCb)
+ {
+ if((ueCb->ueIdx == ueCfg->ueIdx) && (ueCb->crnti == ueCfg->crnti) &&\
+ (ueCb->state == UE_STATE_ACTIVE))
+ {
+ DU_LOG("\n MAC : CRNTI %d already configured ", ueCfg->crnti);
+ return ROKDUP;
+ }
+ }
+
+ /* Fill received Ue Configuration in UeCb */
+ memset(ueCb, 0, sizeof(MacUeCb));
+
+ ueCb->crnti = ueCfg->crnti;
+ ueCb->cellCb = macCb.macCell;
+ ueCb->dlInfo.dlHarqEnt.numHarqProcs = \
+ ueCfg->spCellCfg.servCellCfg.pdschServCellCfg.numHarqProcForPdsch;
+ ueCb->state = UE_STATE_ACTIVE;
+
+ /* Fill BSR info */
+ switch(ueCfg->macCellGrpCfg.bsrTmrCfg.periodicTimer)
+ {
+ case 0:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_1MS;
+ break;
+ case 1:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_5MS;
+ break;
+ case 2:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_10MS;
+ break;
+ case 3:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_16MS;
+ break;
+ case 4:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_20MS;
+ break;
+ case 5:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_32MS;
+ break;
+ case 6:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_40MS;
+ break;
+ case 7:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_60MS;
+ break;
+ case 8:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_80MS;
+ break;
+ case 9:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_128MS;
+ break;
+ case 10:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_160MS;
+ break;
+ case 11:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_320MS;
+ break;
+ case 12:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_640MS;
+ break;
+ case 13:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_1280MS;
+ break;
+ case 14:
+ ueCb->bsrTmrCfg.periodicTimer = PERIODIC_BSR_TMR_2560MS;
+ break;
+ default:
+ DU_LOG("\nMAC : Invalid BSR Periodic Timer");
+ return RFAILED;
+ }
+
+ switch(ueCfg->macCellGrpCfg.bsrTmrCfg.retxTimer)
+ {
+ case 0:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_10MS;
+ break;
+ case 1:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_20MS;
+ break;
+ case 2:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_40MS;
+ break;
+ case 3:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_80MS;
+ break;
+ case 4:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_160MS;
+ break;
+ case 5:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_320MS;
+ break;
+ case 6:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_640MS;
+ break;
+ case 7:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_1280MS;
+ break;
+ case 8:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_2560MS;
+ break;
+ case 9:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_5120MS;
+ break;
+ case 10:
+ ueCb->bsrTmrCfg.retxTimer = RETX_BSR_TMR_10240MS;
+ break;
+ default:
+ DU_LOG("\nMAC : Invalid BSR retransmission timer");
+ break;
+ }
+
+ switch(ueCfg->macCellGrpCfg.bsrTmrCfg.srDelayTimer)
+ {
+ case 0:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_20MS;
+ break;
+ case 1:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_40MS;
+ break;
+ case 2:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_64MS;
+ break;
+ case 3:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_128MS;
+ break;
+ case 4:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_512MS;
+ break;
+ case 5:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_1024MS;
+ break;
+ case 6:
+ ueCb->bsrTmrCfg.srDelayTimer = SR_DELAY_TMR_2560MS;
+ break;
+ default:
+ DU_LOG("\nMAC : Invalid SR delay timer");
+ return RFAILED;
+ }
+
+ /* Fill SRB1 info */
+ if(ueCfg->numLcs > MAX_NUM_LOGICAL_CHANNELS)
+ {
+ DU_LOG("\nMAC : Number of LC to configure[%d] exceeds limit[%d]",\
+ ueCfg->numLcs, MAX_NUM_LOGICAL_CHANNELS);
+ return RFAILED;
+ }
+
+ for(lcIdx = 0; lcIdx < ueCfg->numLcs; lcIdx++)
+ {
+ ueCb->dlInfo.lcCb[ueCb->dlInfo.numDlLc].lcId = ueCfg->lcCfgList[lcIdx].lcId;
+ ueCb->dlInfo.lcCb[ueCb->dlInfo.numDlLc].lcState = LC_STATE_ACTIVE;
+ ueCb->dlInfo.numDlLc++;
+ }
+
+ /* Copy RA Cb */
+ for(ueIdx = 0; ueIdx < MAX_UE; ueIdx++)
+ {
+ if(macCb.macCell->macRaCb[ueIdx].crnti == ueCb->crnti)
+ {
+ ueCb->raCb = &macCb.macCell->macRaCb[ueIdx];
+ break;
+ }
+ }
+
+ macCb.macCell->numActvUe++;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Handles UE create requst from DU APP
+ *
+ * @details
+ *
+ * Function : MacHdlUeCreateReq
+ *
+ * Functionality: Handles UE create requst from DU APP
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t MacHdlUeCreateReq(Pst *pst, MacUeCfg *ueCfg)
+{
+ uint8_t ret;
+
+ DU_LOG("\nMAC : UE Create Request for CRNTI[%d]", ueCfg->crnti);
+
+ if(ueCfg)
+ {
+ ret = createUeCb(ueCfg);
+ if(ret == ROK)
+ {
+ ret = sendAddUeCreateReqToSch(ueCfg);
+ if(ret != ROK)
+ {
+ DU_LOG("\nMAC : Failed to send UE Create request to scheduler");
+ }
+ }
+ else
+ {
+ DU_LOG("\nMAC : Failed to create MAC UE Cb ");
+ }
+ }
+ else
+ {
+ DU_LOG("\nMAC : MAC UE Create request processing failed");
+ ret = RFAILED;
+ }
+ /* FREE shared memory */
+ MAC_FREE_SHRABL_BUF(pst->region, pst->pool, ueCfg, sizeof(MacUeCfg));
+
+ return ret;
+}
+
+uint8_t MacSendUeCreateRsp(MacRsp result, SchUeCfgRsp *schCfgRsp)
+{
+ MacUeCfgRsp *cfgRsp;
+ Pst rspPst;
+
+ MAC_ALLOC_SHRABL_BUF(cfgRsp, sizeof(MacUeCfgRsp));
+ if(!cfgRsp)
+ {
+ DU_LOG("\nMAC: Memory allocation for UE config response failed");
+ return RFAILED;
+ }
+
+ /* Filling UE Config response */
+ memset(cfgRsp, 0, sizeof(MacUeCfgRsp));
+ cfgRsp->cellId = schCfgRsp->cellId;
+ cfgRsp->ueIdx = schCfgRsp->ueIdx;
+ cfgRsp->result = result;
+
+ /* Filling Post structure */
+ memset(&rspPst, 0, sizeof(Pst));
+ rspPst.selector = ODU_SELECTOR_LWLC;
+ rspPst.srcEnt = ENTRG;
+ rspPst.dstEnt = ENTDUAPP;
+ rspPst.dstInst = 0;
+ rspPst.srcInst = macCb.macInst;
+ rspPst.dstProcId = macCb.procId;
+ rspPst.srcProcId = macCb.procId;
+ rspPst.region = MAC_MEM_REGION;
+ rspPst.pool = MAC_POOL;
+ rspPst.event = EVENT_MAC_UE_CREATE_RSP;
+
+ return DuMacUeCreateRspOpts[rspPst.selector](&rspPst, cfgRsp);
+
+}
+
+
+/*******************************************************************
+ *
+ * @brief Processes UE create response from scheduler
+ *
+ * @details
+ *
+ * Function : MacProcSchUeCfgRsp
+ *
+ * Functionality:
+ * Processes UE create response from scheduler
+ * Sends UE create response to DU APP
+ *
+ * @params[in] Pst : Post structure
+ * schCfgRsp : Scheduler UE cfg response
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t MacProcSchUeCfgRsp(Pst *pst, SchUeCfgRsp *schCfgRsp)
+{
+ uint8_t result = MAC_DU_APP_RSP_NOK;
+ uint8_t ret = ROK;
+
+ if(schCfgRsp->rsp == RSP_NOK)
+ {
+ DU_LOG("\nMAC : SCH UE Create Response : FAILURE [CRNTI %d]", schCfgRsp->crnti);
+ memset(&macCb.macCell->ueCb[schCfgRsp->ueIdx], 0, sizeof(MacUeCb));
+ macCb.macCell->numActvUe--;
+ result = MAC_DU_APP_RSP_NOK;
+ }
+ else
+ {
+ DU_LOG("\nMAC : SCH UE Create Response : SUCCESS [CRNTI %d]", schCfgRsp->crnti);
+ result = MAC_DU_APP_RSP_OK;
+ }
+ ret = MacSendUeCreateRsp(result, schCfgRsp);
+ return ret;
+}
+
+
+/**********************************************************************
+ End of file
+ **********************************************************************/