1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /* This file contains message handling functionality for DU APP */
20 #include "common_def.h"
28 #include "du_app_mac_inf.h"
29 #include "du_app_rlc_inf.h"
34 #include "du_f1ap_msg_hdl.h"
35 #include "du_ue_mgr.h"
38 #include "lphy_stub.h"
48 extern DuCfgParams duCfgParam;
49 extern S16 packRlcConfigReq(Pst *pst, KwMngmt *cfg);
50 extern S16 cmPkLkwCntrlReq(Pst *pst, KwMngmt *cfg);
51 extern S16 cmPkLrgCfgReq(Pst *pst, RgMngmt *cfg);
52 extern S16 BuildAndSendE2SetupReq();
53 extern S16 egtpHdlDatInd(EgtpMsg egtpMsg);
54 extern uint8_t BuildAndSendDUConfigUpdate();
55 extern U16 getTransId();
56 extern S16 cmPkLrgSchCfgReq(Pst * pst,RgMngmt * cfg);
58 packMacCellCfgReq packMacCellCfgOpts[] =
60 packMacCellCfg, /* packing for loosely coupled */
61 MacProcCellCfgReq, /* packing for tightly coupled */
62 packMacCellCfg, /* packing for light weight loosly coupled */
65 DuMacCellStartReq packMacCellStartReqOpts[] =
67 packMacCellStartReq, /* Loose coupling */
68 MacProcCellStartReq, /* TIght coupling */
69 packMacCellStartReq /* Light weight-loose coupling */
72 DuMacCellStopReq packMacCellStopReqOpts[] =
74 packMacCellStopReq, /* Loose coupling */
75 MacProcCellStopReq, /* TIght coupling */
76 packMacCellStopReq /* Light weight-loose coupling */
79 /**************************************************************************
80 * @brief Function to fill configs required by RLC
84 * Function : duBuildRlcCfg
87 * Initiates general Configs towards RLC
89 * @param[in] Inst Specifies if RLC UL or RLC DL instance
90 * @return ROK - success
93 ***************************************************************************/
94 S16 duBuildRlcCfg(Inst inst)
97 KwGenCfg *genCfg = NULLP;
100 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
101 DU_SET_ZERO(&pst, sizeof(Pst));
103 genCfg = &(kwMngmt.t.cfg.s.gen);
105 /*----------- Fill General Configuration Parameters ---------*/
106 genCfg->maxUe = duCfgParam.maxUe;
107 genCfg->maxKwuSaps = 2;
108 genCfg->maxUdxSaps = 1;
109 genCfg->rlcMode = (inst == RLC_UL_INST) ?
110 LKW_RLC_MODE_UL : LKW_RLC_MODE_DL;
112 genCfg->maxRguSaps = DEFAULT_CELLS;
114 /*----------- Fill lmPst
115 * Parameters ---------*/
116 genCfg->lmPst.dstProcId = DU_PROC;
117 genCfg->lmPst.srcProcId = DU_PROC;
118 genCfg->lmPst.dstEnt = ENTDUAPP;
119 genCfg->lmPst.dstInst = DU_INST;
120 genCfg->lmPst.srcEnt = ENTKW;
121 genCfg->lmPst.srcInst = inst;
122 genCfg->lmPst.prior = PRIOR0;
123 genCfg->lmPst.route = RTESPEC;
124 genCfg->lmPst.region = (inst == RLC_UL_INST) ?
125 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
126 genCfg->lmPst.pool = RLC_POOL;
127 genCfg->lmPst.selector = ODU_SELECTOR_LC;
130 kwMngmt.hdr.msgType = TCFG;
131 kwMngmt.hdr.msgLen = 0;
132 kwMngmt.hdr.entId.ent = ENTKW;
133 kwMngmt.hdr.entId.inst = (Inst)0;
134 kwMngmt.hdr.elmId.elmnt = STGEN;
135 kwMngmt.hdr.seqNmb = 0;
136 kwMngmt.hdr.version = 0;
137 kwMngmt.hdr.transId = 0;
138 kwMngmt.hdr.response.prior = PRIOR0;
139 kwMngmt.hdr.response.route = RTESPEC;
140 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
141 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
142 kwMngmt.hdr.response.mem.pool = DU_POOL;
143 kwMngmt.hdr.response.selector = ODU_SELECTOR_LC;
146 pst.selector = ODU_SELECTOR_LC;
147 pst.srcEnt = ENTDUAPP;
150 pst.dstProcId = DU_PROC;
151 pst.srcProcId = DU_PROC;
152 pst.region = duCb.init.region;
154 DU_LOG("\nDU_APP : RLC Gen Cfg Req sent for inst %d", inst);
156 /* Send the request to RLC */
157 packRlcConfigReq(&pst, &kwMngmt);
162 /**************************************************************************
163 * @brief Function to fill configs required by RLC
167 * Function : duBuildRlcLsapCfg
170 * Initiates general Configs towards RLC
172 * @param[in] Inst Specifies if RLC UL or RLC DL instance
173 * @return ROK - success
176 ***************************************************************************/
177 S16 duBuildRlcLsapCfg(Ent ent, Inst inst, U8 lsapInst)
181 KwSapCfg *lSap = NULLP;
184 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
185 DU_SET_ZERO(&pst, sizeof(Pst));
188 kwMngmt.hdr.msgType = TCFG;
189 kwMngmt.hdr.entId.ent = ENTKW;
190 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
191 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
193 kwMngmt.hdr.response.mem.pool = RLC_POOL;
196 pst.selector = ODU_SELECTOR_LC;
197 pst.srcEnt = ENTDUAPP;
199 pst.dstProcId = DU_PROC;
201 pst.srcProcId = DU_PROC;
202 pst.region = duCb.init.region;
203 lSap = &(kwMngmt.t.cfg.s.sap);
205 lSap->mem.region = (inst == RLC_UL_INST) ?
206 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
207 lSap->mem.pool = RLC_POOL;
209 lSap->bndTmrIntvl = 10;
210 lSap->priority = PRIOR0;
211 lSap->route = RTESPEC;
214 lSap->procId = DU_PROC;
216 lSap->inst = lsapInst;
217 lSap->sapId = lsapInst; /* SapId will be stored as suId in MAC */
218 lSap->selector = (inst == RLC_UL_INST) ? ODU_SELECTOR_LWLC : ODU_SELECTOR_TC;
219 kwMngmt.hdr.elmId.elmnt = STRGUSAP;
220 DU_LOG("\nDU_APP : RLC MAC Lower Sap Cfg Req sent for inst %d", inst);
225 lSap->procId = DU_PROC;
227 lSap->inst = (inst == RLC_UL_INST) ?
228 RLC_DL_INST : RLC_UL_INST;
230 lSap->selector = ODU_SELECTOR_LC;
231 kwMngmt.hdr.elmId.elmnt = STUDXSAP;
232 DU_LOG("\nDU_APP : RLC DL/UL Lower Sap Cfg Req sent for inst %d", inst);
235 packRlcConfigReq(&pst, &kwMngmt);
239 /**************************************************************************
240 * @brief Function to fill configs required by RLC
244 * Function : duBuildRlcUsapCfg
247 * Initiates general Configs towards RLC
249 * @param[in] Inst Specifies if RLC UL or RLC DL instance
250 * @return ROK - success
253 ***************************************************************************/
254 S16 duBuildRlcUsapCfg(U8 elemId, Ent ent, Inst inst)
257 KwSapCfg *uSap = NULLP;
260 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
261 DU_SET_ZERO(&pst, sizeof(Pst));
263 uSap = &(kwMngmt.t.cfg.s.sap);
265 uSap->selector = ODU_SELECTOR_LC;
266 uSap->mem.region = (inst == RLC_UL_INST) ?
267 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
268 uSap->mem.pool = RLC_POOL;
271 uSap->procId = DU_PROC;
275 uSap->inst = (inst == RLC_UL_INST) ?
276 RLC_DL_INST : RLC_UL_INST;
277 uSap->bndTmrIntvl = 1000;
278 uSap->priority = PRIOR0;
279 uSap->route = RTESPEC;
282 kwMngmt.hdr.msgType = TCFG;
283 kwMngmt.hdr.entId.ent = ENTKW;
284 kwMngmt.hdr.elmId.elmnt = STUDXSAP;
285 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
286 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
288 kwMngmt.hdr.response.mem.pool = RLC_POOL;
291 pst.selector = ODU_SELECTOR_LC;
292 pst.srcEnt = ENTDUAPP;
294 pst.dstProcId = DU_PROC;
296 pst.srcProcId = DU_PROC;
297 pst.region = duCb.init.region;
299 DU_LOG("\nDU_APP : RLC Kwu Upper Sap Cfg Req sent for inst %d", inst);
300 packRlcConfigReq(&pst, &kwMngmt);
305 /**************************************************************************
306 * @brief Function to populate internal DS of DU APP
310 * Function : duProcCfgComplete
313 * Populates internal data structures of DU APP after
314 * receiving configurations.
317 * @return ROK - success
320 ***************************************************************************/
321 S16 duProcCfgComplete()
324 static U16 cellId = 0;
326 for(idx=0; idx< DEFAULT_CELLS; idx++)
328 DuCellCb *cell = NULLP;
329 DU_ALLOC(cell, sizeof(DuCellCb))
332 DU_LOG("\nDU_APP : Memory Allocation failed in duProcCfgComplete");
339 memset(cell, 0, sizeof(DuCellCb));
340 cell->cellId = ++cellId;
341 cell->cellInfo.nrEcgi.plmn.mcc[0] = PLMN_MCC0;
342 cell->cellInfo.nrEcgi.plmn.mcc[1] = PLMN_MCC1;
343 cell->cellInfo.nrEcgi.plmn.mcc[2] = PLMN_MCC2;
344 cell->cellInfo.nrEcgi.plmn.mnc[0] = PLMN_MNC0;
345 cell->cellInfo.nrEcgi.plmn.mnc[1] = PLMN_MNC1;
346 cell->cellInfo.nrEcgi.plmn.mnc[2] = PLMN_MNC2;
347 cell->cellInfo.nrEcgi.cellId = NR_CELL_ID;
348 cell->cellInfo.nrPci = NR_PCI;
349 cell->cellInfo.fiveGsTac = DU_TAC;
350 for(idx1=0; idx1<MAX_PLMN; idx1++)
352 cell->cellInfo.plmn[idx1].mcc[0] = PLMN_MCC0;
353 cell->cellInfo.plmn[idx1].mcc[1] = PLMN_MCC1;
354 cell->cellInfo.plmn[idx1].mcc[2] = PLMN_MCC2;
355 cell->cellInfo.plmn[idx1].mnc[0] = PLMN_MNC0;
356 cell->cellInfo.plmn[idx1].mnc[1] = PLMN_MNC1;
357 cell->cellInfo.plmn[idx1].mnc[2] = PLMN_MNC2;
359 cell->cellInfo.maxUe = duCfgParam.maxUe;
360 cell->cellStatus = CELL_OUT_OF_SERVICE;
361 nci = (U16)cell->cellInfo.nrEcgi.cellId;
363 duCb.cfgCellLst[nci-1] = cell;
369 //Start layer configs
370 ret = duSendRlcUlCfg();
374 /**************************************************************************
375 * @brief Function to invoke DU Layer Configs
379 * Function : duSendRlcUlCfg
382 * Initiates Configs towards layers of DU
385 * @return ROK - success
388 ***************************************************************************/
393 duBuildRlcCfg((Inst)RLC_UL_INST);
394 for(cellIdx = 0; cellIdx < DEFAULT_CELLS; cellIdx++)
396 duBuildRlcLsapCfg(ENTRG, (Inst)RLC_UL_INST, cellIdx);
398 duBuildRlcLsapCfg(ENTKW, (Inst)RLC_UL_INST, 0);
403 /**************************************************************************
404 * @brief Function to invoke DU Layer Configs
408 * Function : duSendRlcDlCfg
411 * Initiates Configs towards layers of DU
414 * @return ROK - success
417 ***************************************************************************/
422 duBuildRlcCfg((Inst)RLC_DL_INST);
423 duBuildRlcUsapCfg(STUDXSAP, ENTKW, (Inst)RLC_DL_INST);
424 for(cellIdx = 0; cellIdx < DEFAULT_CELLS; cellIdx++)
426 duBuildRlcLsapCfg(ENTRG, (Inst)RLC_DL_INST, cellIdx);
431 /**************************************************************************
432 * @brief Function to handle Config Confirm from RLC
436 * Function : DuHdlRlcCfgComplete
439 * Handles Gen Config Confirm from RLC
441 * @param[in] Pst *pst, Post structure of the primitive.
442 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC
443 * @return ROK - success
446 ***************************************************************************/
447 S16 DuHdlRlcCfgComplete(Pst *pst, KwMngmt *cfm)
450 if (pst->srcInst == RLC_UL_INST)
452 ret = duProcRlcUlCfgComplete(pst, cfm);
456 ret = duProcRlcDlCfgComplete(pst, cfm);
461 /**************************************************************************
462 * @brief Function to handle Control Config Confirm from RLC
466 * Function : duHdlRlcCntrlCfgComplete
469 * Handles Control Config Confirm from RLC
471 * @param[in] Pst *pst, Post structure of the primitive.
472 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC
473 * @return ROK - success
476 ***************************************************************************/
477 S16 duHdlRlcCntrlCfgComplete(Pst *pst, KwMngmt *cntrl)
481 if (cntrl->cfm.status == LCM_PRIM_OK)
483 switch (cntrl->hdr.elmId.elmnt)
487 if (pst->srcInst == RLC_DL_INST)
489 DU_LOG("\nDU_APP : BIND OF RLC DL TO MAC (RGU) SAP SUCCESSFUL");
491 if(macCfgInst < DEFAULT_CELLS)
494 duBindUnbindRlcToMacSap((Inst) RLC_DL_INST, ABND);
498 duBindUnbindRlcToMacSap((Inst) RLC_UL_INST, ABND);
503 DU_LOG("\nDU_APP : BIND OF RLC UL TO MAC (RGU) SAP SUCCESSFUL");
505 if(macCfgInst < DEFAULT_CELLS)
507 duBindUnbindRlcToMacSap((Inst) RLC_UL_INST, ABND);
521 /**************************************************************************
522 * @brief Function to handle Config Confirm from RLC UL
526 * Function : duHdlRlcUlCfgComplete
529 * Handles Config Confirm from RLC UL
531 * @param[in] Pst *pst, Post structure of the primitive.
532 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC UL
533 * @return ROK - success
536 ***************************************************************************/
537 S16 duProcRlcUlCfgComplete(Pst *pst, KwMngmt *cfm)
541 DU_LOG("\nDU_APP : RLC UL Cfg Status %d", cfm->cfm.status);
542 if (cfm->cfm.status == LCM_PRIM_OK)
544 switch(cfm->hdr.elmId.elmnt)
548 rlcUlCfg |= RLC_GEN_CFG;
554 if(numRlcMacSaps == DEFAULT_CELLS)
556 rlcUlCfg |= RLC_MAC_SAP_CFG;
563 rlcUlCfg |= RLC_UDX_SAP_CFG;
570 DU_LOG("\nDU_APP : RLC UL Cfg Cfm received for the element %d ",cfm->hdr.elmId.elmnt);
571 if(rlcUlCfg == DU_RLC_UL_CONFIGURED)
575 //Start configuration of RLC DL
582 DU_LOG("\nDU_APP : Config confirm NOK from RLC UL");
588 /**************************************************************************
589 * @brief Function to handle Config Confirm from RLC DL
593 * Function : duHdlRlcDlCfgComplete
596 * Handles Config Confirm from RLC DL
598 * @param[in] Pst *pst, Post structure of the primitive.
599 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC DL
600 * @return ROK - success
603 ***************************************************************************/
604 S16 duProcRlcDlCfgComplete(Pst *pst, KwMngmt *cfm)
606 DU_LOG("\nDU_APP : RLC DL Cfg Status %d", cfm->cfm.status);
607 if (cfm->cfm.status == LCM_PRIM_OK)
609 switch(cfm->hdr.elmId.elmnt)
613 rlcDlCfg |= RLC_GEN_CFG;
619 if(numRlcMacSaps == DEFAULT_CELLS)
621 rlcDlCfg |= RLC_MAC_SAP_CFG;
628 rlcDlCfg |= RLC_UDX_SAP_CFG;
636 DU_LOG("\nDU_APP : RLC DL Cfg Cfm received for the element %d ",cfm->hdr.elmId.elmnt);
637 if(rlcDlCfg == DU_RLC_DL_CONFIGURED)
640 //Start configuration of MAC
647 DU_LOG("\nDU_APP : Config confirm NOK from RLC DL");
652 /**************************************************************************
653 * @brief Function to send configs to MAC
657 * Function : duSendMacCfg
660 * Initiates Configs towards MAC layer
663 * @return ROK - success
666 ***************************************************************************/
670 duBuildMacUsapCfg(RLC_UL_INST);
671 duBuildMacUsapCfg(RLC_DL_INST);
676 /**************************************************************************
677 * @brief Function to fill gen config required by MAC
681 * Function : duBuildMacGenCfg
684 * Initiates general Configs towards MAC
687 * @return ROK - success
690 ***************************************************************************/
691 S16 duBuildMacGenCfg()
694 RgGenCfg *genCfg=NULLP;
697 DU_SET_ZERO(&pst, sizeof(Pst));
698 DU_SET_ZERO(&rgMngmt, sizeof(RgMngmt));
700 genCfg = &(rgMngmt.t.cfg.s.genCfg);
702 /*----------- Fill General Configuration Parameters ---------*/
703 genCfg->mem.region = MAC_MEM_REGION;
704 genCfg->mem.pool = MAC_POOL;
706 genCfg->numRguSaps = 2;
708 genCfg->lmPst.dstProcId = DU_PROC;
709 genCfg->lmPst.srcProcId = DU_PROC;
710 genCfg->lmPst.dstEnt = ENTDUAPP;
711 genCfg->lmPst.dstInst = 0;
712 genCfg->lmPst.srcEnt = ENTRG;
713 genCfg->lmPst.srcInst = macCfgInst;
714 genCfg->lmPst.prior = PRIOR0;
715 genCfg->lmPst.route = RTESPEC;
716 genCfg->lmPst.region = MAC_MEM_REGION;
717 genCfg->lmPst.pool = MAC_POOL;
718 genCfg->lmPst.selector = ODU_SELECTOR_LC;
721 rgMngmt.hdr.msgType = TCFG;
722 rgMngmt.hdr.msgLen = 0;
723 rgMngmt.hdr.entId.ent = ENTRG;
724 rgMngmt.hdr.entId.inst = (Inst)0;
725 rgMngmt.hdr.elmId.elmnt = STGEN;
726 rgMngmt.hdr.seqNmb = 0;
727 rgMngmt.hdr.version = 0;
728 rgMngmt.hdr.transId = 0;
730 rgMngmt.hdr.response.prior = PRIOR0;
731 rgMngmt.hdr.response.route = RTESPEC;
732 rgMngmt.hdr.response.mem.region = MAC_MEM_REGION;
733 rgMngmt.hdr.response.mem.pool = MAC_POOL;
734 rgMngmt.hdr.response.selector = ODU_SELECTOR_LC;
737 pst.selector = ODU_SELECTOR_LC;
738 pst.srcEnt = ENTDUAPP;
740 pst.dstInst = macCfgInst;
741 pst.dstProcId = DU_PROC;
742 pst.srcProcId = DU_PROC;
743 pst.region = duCb.init.region;
745 DU_LOG("\nDU_APP : MAC Gen Cfg Req sent");
747 /* Send the request to MAC */
748 cmPkLrgCfgReq(&pst, &rgMngmt);
753 /**************************************************************************
754 * @brief Function to fill USAP config required by MAC
758 * Function : duBuildMacUsapCfg
761 * Initiates USAP Configs towards MAC
763 * @param[in] SpId Specifies if RLC UL or RLC DL instance
764 * @return ROK - success
767 ***************************************************************************/
768 S16 duBuildMacUsapCfg(SpId sapId)
771 RgUpSapCfg *uSap = NULLP;
774 DU_SET_ZERO(&pst, sizeof(Pst));
775 DU_SET_ZERO(&rgMngmt, sizeof(RgMngmt));
777 uSap = &(rgMngmt.t.cfg.s.rguSap);
779 uSap->mem.region = MAC_MEM_REGION;
780 uSap->mem.pool = MAC_POOL;
783 uSap->procId = DU_PROC;
786 uSap->prior = PRIOR0;
787 uSap->route = RTESPEC;
788 uSap->selector = ODU_SELECTOR_LC ;
791 rgMngmt.hdr.msgType = TCFG;
792 rgMngmt.hdr.entId.ent = ENTRG;
793 rgMngmt.hdr.entId.inst = (Inst)0;
794 rgMngmt.hdr.elmId.elmnt = STRGUSAP;
795 rgMngmt.hdr.response.mem.region = MAC_MEM_REGION;
796 rgMngmt.hdr.response.mem.pool = MAC_POOL;
799 pst.selector = ODU_SELECTOR_LC;
800 pst.srcEnt = ENTDUAPP;
802 pst.dstInst = macCfgInst;
803 pst.dstProcId = DU_PROC;
804 pst.srcProcId = DU_PROC;
805 pst.region = duCb.init.region;
807 DU_LOG("\nDU_APP : MAC Rgu USap Cfg Req sent");
809 /* Send the request to MAC */
810 cmPkLrgCfgReq(&pst, &rgMngmt);
815 /**************************************************************************
816 * @brief Function to handle Config Confirm from MAC
820 * Function : duHdlMacCfgComplete
823 * Handles Gen Config Confirm from MAC
825 * @param[in] Pst *pst, Post structure of the primitive.
826 * @param[in] RgMngmt *cfm, Unpacked primitive info received from MAC
827 * @return ROK - success
830 ***************************************************************************/
831 S16 duHdlMacCfgComplete(Pst *pst, RgMngmt *cfm)
835 if (cfm->cfm.status == LCM_PRIM_OK)
837 switch (cfm->hdr.elmId.elmnt)
841 macCfg |= MAC_GEN_CFG;
846 macCfg |= MAC_SAP_CFG;
853 DU_LOG("\nDU_APP : MAC Cfg Cfm received for the element %d ",cfm->hdr.elmId.elmnt);
854 if(macCfg == MAC_CONFIGURED && numRlcMacSaps == MAX_MAC_SAP)
857 DU_LOG("\nDU_APP : Completed sending Configs");
859 duBindUnbindRlcToMacSap(RLC_DL_INST, ABND);
865 DU_LOG("\nDU_APP : Config confirm NOK from MAC");
871 /**************************************************************************
872 * @brief Function to bind/unbind RLC to MAC SAP
876 * Function : duBindUnbindRlcToMacSap
879 * Initiates Bind/Unbind from RLC to MAC
881 * @param[in] Inst Specifies if RLC UL or RLC DL instance
882 * @param[in] action Specifies if action is bind or unbind
883 * @return ROK - success
886 ***************************************************************************/
887 S16 duBindUnbindRlcToMacSap(U8 inst, U8 action)
889 KwCntrl *cntrl = NULLP;
893 TRC2(smBindKwToRguSap)
895 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
896 DU_SET_ZERO(&pst, sizeof(Pst));
900 DU_LOG("\nDU_APP : Cntrl Req to RLC inst %d to bind MAC sap", inst);
904 DU_LOG("\nDU_APP : Cntrl Req to RLC inst %d to unbind MAC sap", inst);
906 cntrl = &(kwMngmt.t.cntrl);
908 cntrl->action = action;
909 cntrl->subAction = DU_ZERO_VAL;
910 cntrl->s.sapCntrl.suId = macCfgInst;
911 cntrl->s.sapCntrl.spId = inst;
914 kwMngmt.hdr.msgType = TCNTRL;
915 kwMngmt.hdr.entId.ent = ENTKW;
916 kwMngmt.hdr.entId.inst = inst;
917 kwMngmt.hdr.elmId.elmnt = 186; /* ambiguous defines in lkw.h and lrg.h so direct hardcoded*/
918 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
919 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
920 kwMngmt.hdr.response.mem.pool = RLC_POOL;
923 pst.selector = ODU_SELECTOR_LC;
924 pst.srcEnt = ENTDUAPP;
926 pst.dstProcId = DU_PROC;
928 pst.srcProcId = DU_PROC;
929 pst.region = duCb.init.region;
931 cmPkLkwCntrlReq(&pst, &kwMngmt);
935 /*******************************************************************
937 * @brief Handles SCTP notifications
941 * Function : duSctpNtfyHdl
944 * Handles SCTP notification
946 * @params[in] Message Buffer
949 * @return ROK - success
952 * ****************************************************************/
954 S16 duSctpNtfyHdl(Buffer *mBuf, CmInetSctpNotification *ntfy)
956 if(f1Params.assocId == ntfy->u.assocChange.assocId)
958 if(BuildAndSendF1SetupReq() != ROK)
963 else if(ricParams.assocId == ntfy->u.assocChange.assocId)
965 if(BuildAndSendE2SetupReq() != ROK)
972 DU_LOG("\nDU_APP : Invalid assocId %d received", ntfy->u.assocChange.assocId);
978 /*******************************************************************
980 * @brief Fills Pst struct for ENTEGTP
984 * Function : duFillEgtpPst
987 * Fills Pst struct for ENTEGTP
990 * @return ROK - success
993 * ****************************************************************/
994 S16 duFillEgtpPst(Pst *pst, Event event)
996 cmMemset((U8 *)pst, 0, sizeof(Pst));
997 pst->srcEnt = (Ent)ENTDUAPP;
998 pst->srcInst = (Inst)DU_INST;
999 pst->srcProcId = DU_PROC;
1000 pst->dstEnt = (Ent)ENTEGTP;
1001 pst->dstInst = (Inst)EGTP_INST;
1002 pst->dstProcId = pst->srcProcId;
1004 pst->selector = ODU_SELECTOR_LC;
1011 /*******************************************************************
1013 * @brief Function to configure EGTP
1017 * Function : duBuildEgtpCfgReq
1020 * Function to configure EGTP
1023 * @return ROK - success
1026 * ****************************************************************/
1028 S16 duBuildEgtpCfgReq()
1033 DU_LOG("\nDU_APP : Sending EGTP config request");
1035 cmMemset((U8 *)&egtpCfg, 0, sizeof(EgtpConfig));
1036 cmMemcpy((U8 *)&egtpCfg, (U8 *)&duCfgParam.egtpParams, (PTR)sizeof(EgtpConfig));
1038 duFillEgtpPst(&pst, EVTCFGREQ);
1039 packEgtpCfgReq(&pst, egtpCfg);
1044 /*******************************************************************
1046 * @brief Function to configure EGTP
1050 * Function : duBuildEgtpCfgReq
1053 * Function to configure EGTP
1056 * @return ROK - success
1059 * ****************************************************************/
1060 S16 duHdlEgtpCfgComplete(CmStatus cfm)
1064 if(cfm.status == LCM_PRIM_OK)
1066 DU_LOG("\nDU_APP : EGTP configuraton complete");
1068 duSendEgtpSrvOpenReq();
1073 DU_LOG("\nDU_APP : EGTP configuraton failed");
1080 /*******************************************************************
1082 * @brief Sends server open request to EGTP
1086 * Function : duSendEgtpSrvOpenReq
1089 * Sends server open request to EGTP
1092 * @return ROK - success
1095 * ****************************************************************/
1097 S16 duSendEgtpSrvOpenReq()
1101 DU_LOG("\nDU_APP : Sending EGTP server open request");
1103 duFillEgtpPst(&pst, EVTSRVOPENREQ);
1104 packEgtpSrvOpenReq(&pst);
1109 /*******************************************************************
1111 * @brief Handles server open confirmation
1115 * Function : duHdlEgtpSrvOpenComplete
1118 * Handles server open confirmation
1121 * @return ROK - success
1124 *****************************************************************/
1126 S16 duHdlEgtpSrvOpenComplete(CmStatus cfm)
1130 if(cfm.status == LCM_PRIM_OK)
1132 DU_LOG("\nDU_APP : EGTP server opened successfully");
1134 duSendEgtpTnlMgmtReq(EGTP_TNL_MGMT_ADD, EGTP_LCL_TEID, EGTP_REM_TEID);
1139 DU_LOG("\nDU_APP : EGTP server opening failed");
1146 /*******************************************************************
1148 * @brief Sends tunnel management request
1152 * Function : duSendEgtpTnlMgmtReq
1155 * Builds and sends tunnel management request to EGTP
1157 * @params[in] Action
1158 * Local tunnel endpoint id
1159 * Remote tunnel endpoint id
1160 * @return ROK - success
1163 * ****************************************************************/
1165 S16 duSendEgtpTnlMgmtReq(U8 action, U32 lclTeid, U32 remTeid)
1170 tnlEvt.action = action;
1171 tnlEvt.lclTeid = lclTeid;
1172 tnlEvt.remTeid = remTeid;
1174 DU_LOG("\nDU_APP : Sending EGTP tunnel management request");
1176 duFillEgtpPst(&pst, EVTTNLMGMTREQ);
1177 packEgtpTnlMgmtReq(&pst, tnlEvt);
1182 /*******************************************************************
1184 * @brief Handles Tunnel management confirm
1188 * Function : duHdlEgtpTnlMgmtCfm
1191 * Handles tunnel management confirm received from Egtp
1193 * @params[in] Tunnel Event
1194 * @return ROK - success
1197 * ****************************************************************/
1198 S16 duHdlEgtpTnlMgmtCfm(EgtpTnlEvt tnlEvtCfm)
1202 if(tnlEvtCfm.cfmStatus.status == LCM_PRIM_OK)
1204 DU_LOG("\nDU_APP : Tunnel management confirm OK");
1207 duSendUeCreateReqToRlc();
1209 duSendEgtpTestData();
1214 DU_LOG("\nDU_APP : Tunnel management failed");
1221 S16 duSendEgtpDatInd(Buffer *mBuf)
1225 /* Fill EGTP header */
1226 egtpMsg.msgHdr.msgType = EGTPU_MSG_GPDU;
1227 egtpMsg.msgHdr.nPdu.pres = FALSE;
1228 egtpMsg.msgHdr.seqNum.pres = FALSE;
1229 egtpMsg.msgHdr.extHdr.udpPort.pres = FALSE;
1230 egtpMsg.msgHdr.extHdr.pdcpNmb.pres = FALSE;
1231 egtpMsg.msgHdr.teId = 1;
1234 egtpHdlDatInd(egtpMsg);
1241 /*******************************************************************
1243 * @brief Simulate UL Data for intial test
1247 * Function : duSendEgtpTestData
1250 * Simulate UL data for initial test
1253 * @return ROK - success
1256 * ****************************************************************/
1257 S16 duSendEgtpTestData()
1259 char data[30] = "This is EGTP data from DU";
1264 if(SGetMsg(DU_APP_MEM_REGION, DU_POOL, &mBuf) == ROK)
1266 if(SAddPstMsgMult((Data *)data, datSize, mBuf) != ROK)
1268 DU_LOG("\nDU_APP : SAddPstMsgMult failed");
1275 DU_LOG("\nDU_APP : Failed to allocate memory");
1279 /* filling IPv4 header */
1284 SFndLenMsg(mBuf, &mLen);
1286 cmMemset((U8 *)&ipv4Hdr, 0, sizeof(CmIpv4Hdr));
1287 ipv4Hdr.length = CM_IPV4_HDRLEN + mLen;
1288 ipv4Hdr.hdrVer = 0x45;
1290 ipv4Hdr.srcAddr = CM_INET_NTOH_U32(duCfgParam.egtpParams.localIp.ipV4Addr);
1291 ipv4Hdr.destAddr = CM_INET_NTOH_U32(duCfgParam.egtpParams.destIp.ipV4Addr);
1293 /* Packing IPv4 header into buffer */
1295 Data revPkArray[CM_IPV4_HDRLEN];
1296 Data pkArray[CM_IPV4_HDRLEN];
1298 /* initialize locals */
1300 cmMemset(revPkArray, 0, CM_IPV4_HDRLEN);
1301 cmMemset(pkArray, 0, CM_IPV4_HDRLEN);
1303 /* Pack Header Version */
1304 pkArray[cnt++] = ipv4Hdr.hdrVer;
1307 pkArray[cnt++] = ipv4Hdr.tos;
1309 pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.length);
1310 pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.length);
1313 pkArray[cnt++] = (Data) GetHiByte(ipv4Hdr.id);
1314 pkArray[cnt++] = (Data) GetLoByte(ipv4Hdr.id);
1317 pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.off);
1318 pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.off);
1321 pkArray[cnt++] = ipv4Hdr.ttl;
1324 pkArray[cnt++] = ipv4Hdr.proto;
1327 pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.chkSum);
1328 pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.chkSum);
1330 /* Pack Source Address */
1331 pkArray[cnt++] = (Data)GetHiByte(GetHiWord(ipv4Hdr.srcAddr));
1332 pkArray[cnt++] = (Data)GetLoByte(GetHiWord(ipv4Hdr.srcAddr));
1333 pkArray[cnt++] = (Data)GetHiByte(GetLoWord(ipv4Hdr.srcAddr));
1334 pkArray[cnt++] = (Data)GetLoByte(GetLoWord(ipv4Hdr.srcAddr));
1336 /* Pack Destination Address */
1337 pkArray[cnt++] = (Data)GetHiByte(GetHiWord(ipv4Hdr.destAddr));
1338 pkArray[cnt++] = (Data)GetLoByte(GetHiWord(ipv4Hdr.destAddr));
1339 pkArray[cnt++] = (Data)GetHiByte(GetLoWord(ipv4Hdr.destAddr));
1340 pkArray[cnt++] = (Data)GetLoByte(GetLoWord(ipv4Hdr.destAddr));
1342 for (idx = 0; idx < CM_IPV4_HDRLEN; idx++)
1343 revPkArray[idx] = pkArray[CM_IPV4_HDRLEN - idx -1];
1345 /* this function automatically reverses revPkArray */
1346 ret = SAddPreMsgMult(revPkArray, (MsgLen)cnt, mBuf);
1348 duSendEgtpDatInd(mBuf);
1352 #endif /* EGTP_TEST */
1355 /**************************************************************************
1356 * @brief Function to send configs to SCH
1360 * Function : duSendSchCfg
1363 * Sends general config to Scheduler via MAC layer
1366 * @return ROK - success
1369 ***************************************************************************/
1373 RgSchInstCfg *cfg = NULLP;
1376 DU_SET_ZERO(&pst, sizeof(Pst));
1377 DU_SET_ZERO(&rgMngmt, sizeof(RgMngmt));
1379 cfg = &(rgMngmt.t.cfg.s.schInstCfg);
1381 /* Filling of Instance Id */
1382 cfg->instId = DEFAULT_CELLS + 1;
1383 /* Filling of Gen config */
1384 cfg->genCfg.mem.region = MAC_MEM_REGION;
1385 cfg->genCfg.mem.pool = MAC_POOL;
1386 cfg->genCfg.tmrRes = 10;
1389 cfg->genCfg.forceCntrlSrbBoOnPCel = FALSE;
1390 cfg->genCfg.isSCellActDeactAlgoEnable = TRUE;
1392 cfg->genCfg.startCellId = 1;
1393 cfg->genCfg.lmPst.dstProcId = DU_PROC;
1394 cfg->genCfg.lmPst.srcProcId = DU_PROC;
1395 cfg->genCfg.lmPst.dstEnt = ENTDUAPP;
1396 cfg->genCfg.lmPst.dstInst = DU_INST;
1397 cfg->genCfg.lmPst.srcEnt = ENTRG;
1398 cfg->genCfg.lmPst.srcInst = DEFAULT_CELLS + 1;
1399 cfg->genCfg.lmPst.prior = PRIOR0;
1400 cfg->genCfg.lmPst.route = RTESPEC;
1401 cfg->genCfg.lmPst.region = MAC_MEM_REGION;
1402 cfg->genCfg.lmPst.pool = MAC_POOL;
1403 cfg->genCfg.lmPst.selector = ODU_SELECTOR_LC;
1406 rgMngmt.hdr.msgType = TCFG;
1407 rgMngmt.hdr.entId.ent = ENTRG;
1408 rgMngmt.hdr.entId.inst = DU_INST;
1409 rgMngmt.hdr.elmId.elmnt = STSCHINST;
1410 rgMngmt.hdr.response.mem.region = MAC_MEM_REGION;
1411 rgMngmt.hdr.response.mem.pool = MAC_POOL;
1414 pst.selector = ODU_SELECTOR_LC;
1415 pst.srcEnt = ENTDUAPP;
1417 pst.dstProcId = DU_PROC;
1418 pst.srcProcId = DU_PROC;
1419 pst.srcInst = DU_INST;
1421 pst.region = duCb.init.region;
1422 pst.event = (Event) EVTMACSCHGENCFGREQ;
1424 DU_LOG("\nDU_APP : MAC Sch Cfg sent");
1426 /* Send the request to MAC */
1427 cmPkLrgSchCfgReq(&pst, &rgMngmt);
1433 /**************************************************************************
1434 * @brief Function to configure SCTP params and
1435 * responsible for F1 and E2 interfaces
1439 * Function : duLayerConfigComplete
1442 * Configures SCTP Params and responsible for handling
1443 * F1 and E2 interface.
1446 * @return ROK - success
1449 ***************************************************************************/
1450 S16 duLayerConfigComplete()
1454 DU_LOG("\nDU_APP : Configuring all Layer is complete");
1456 if((ret = duSctpCfgReq(duCfgParam.sctpParams)) != ROK)
1458 DU_LOG("\nDU_APP : Failed configuring Sctp Params");
1461 if((ret = duSctpAssocReq(F1_INTERFACE)) != ROK)
1463 DU_LOG("\nDU_APP : Failed to send AssocReq F1");
1466 if((ret = duSctpAssocReq(E2_INTERFACE)) != ROK)
1468 DU_LOG("\nDU_APP : Failed to send AssocReq E2");
1475 /**************************************************************************
1476 * @brief Function to handle SCH Config Confirm from MAC
1480 * Function : duHdlSchCfgComplete
1483 * Handles Scheduler Gen Config Confirm from MAC
1485 * @param[in] Pst *pst, Post structure of the primitive.
1486 * @param[in] RgMngmt *cfm, Unpacked primitive info received from MAC
1487 * @return ROK - success
1490 ***************************************************************************/
1491 S16 duHdlSchCfgComplete(Pst *pst, RgMngmt *cfm)
1493 if (cfm->cfm.status == LCM_PRIM_OK)
1495 switch (cfm->hdr.elmId.elmnt)
1499 DU_LOG("\nDU_APP : Received SCH CFG CFM at DU APP");
1506 duLayerConfigComplete();
1507 duBuildEgtpCfgReq();
1511 /*******************************************************************
1513 * @brief Sends Slot indication to EGTP
1517 * Function : duSendEgtpSlotInd
1520 * Sends Slot indication to EGTP
1523 * @return ROK - success
1526 * ****************************************************************/
1527 S16 duSendEgtpSlotInd()
1531 duFillEgtpPst(&pst, EVTSLOTIND);
1532 packEgtpSlotInd(&pst);
1538 /**************************************************************************
1539 * @brief Function to fill and send MacCellconfig
1543 * Function : duBuildAndSendMacCellCfg
1546 * Initiates MAC Configs towards MAC
1549 * @return ROK - success
1552 ***************************************************************************/
1553 S16 duBuildAndSendMacCellCfg()
1556 DU_SET_ZERO(&pst, sizeof(Pst));
1557 MacCellCfg *duMacCellCfg = NULLP;
1559 DU_ALLOC_SHRABL_BUF(duMacCellCfg, sizeof(MacCellCfg));
1560 if(duMacCellCfg == NULLP)
1565 /* store the address in the duCb so that we can free on confirm msg */
1566 duCb.duMacCellCfg = duMacCellCfg;
1568 /* copy the mac config structure from duCfgParams */
1569 memcpy(duMacCellCfg,&duCfgParam.macCellCfg,sizeof(MacCellCfg));
1572 FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_CONFIG_REQ);
1574 /* Send MAC cell config to MAC */
1575 return (*packMacCellCfgOpts[pst.selector])(&pst, duMacCellCfg);
1578 /**************************************************************************
1579 * @brief Function to Handle MAC cell config confirm
1583 * Function : duHandleMacCellCfgCfm
1586 * Initiates general Configs towards MAC
1589 * @return ROK - success
1592 ***************************************************************************/
1593 uint8_t duHandleMacCellCfgCfm(Pst *pst, MacCellCfgCfm *macCellCfgCfm)
1595 uint8_t actvCellIdx = 0;
1598 if(macCellCfgCfm->rsp == ROK)
1600 for(actvCellIdx = 0 ; actvCellIdx <duCb.numActvCells ; actvCellIdx++)
1602 if(macCellCfgCfm->cellId == duCb.actvCellLst[actvCellIdx]->cellId)
1604 duCb.duMacCellCfg = NULLP;
1605 /* Build and send GNB-DU config update */
1606 ret = BuildAndSendDUConfigUpdate();
1608 /* TODO: Trigger cell start req once cell up slot ind is received*/
1609 /* Build and Send Cell Start Req to MAC */
1610 ret = duBuildAndSendMacCellStartReq();
1617 DU_LOG("\nMac cell cfg failed");
1623 /*******************************************************************
1625 * @brief Handles slot indication from MAC
1629 * Function : duHandleSlotInd
1632 * Handles slot indication from MAC
1634 * @params[in] Post structure pointer
1636 * @return ROK - success
1639 * ****************************************************************/
1640 uint8_t duHandleSlotInd(Pst *pst, SlotIndInfo *slotInfo)
1643 DU_LOG("\nDU APP : Slot Indication received");
1645 if(slotInfo->cellId <=0 || slotInfo->cellId > MAX_NUM_CELL)
1647 DU_LOG("\nDU APP : Invalid Cell Id %d", slotInfo->cellId);
1649 if(!duCb.actvCellLst[slotInfo->cellId-1]->firstSlotIndRcvd)
1651 duCb.actvCellLst[slotInfo->cellId-1]->firstSlotIndRcvd = true;
1652 if((duCb.actvCellLst[slotInfo->cellId-1] != NULL) && \
1653 (duCb.actvCellLst[slotInfo->cellId-1]->cellStatus == \
1654 ACTIVATION_IN_PROGRESS))
1656 DU_LOG("\nDU APP : 5G-NR Cell %d is UP", slotInfo->cellId);
1657 duCb.actvCellLst[slotInfo->cellId-1]->cellStatus = ACTIVATED;
1662 /* TODO : Slot Indication to be moved out of EGTP_TEST when
1663 * data path is established */
1665 duSendEgtpSlotInd();
1668 if((pst->selector == ODU_SELECTOR_LWLC) || (pst->selector == ODU_SELECTOR_TC))
1669 DU_FREE_SHRABL_BUF(MAC_MEM_REGION, pst->pool, slotInfo, sizeof(SlotIndInfo));
1674 /*******************************************************************
1676 * @brief Builds and sends cell start request to MAC
1680 * Function : duBuildAndSendMacCellStartReq
1683 * Builds and sends cell start request to MAC
1686 * @return ROK - success
1689 * ****************************************************************/
1690 uint8_t duBuildAndSendMacCellStartReq()
1693 MacCellStartInfo *cellStartInfo = NULL;
1695 DU_LOG("\nDU APP : Building and Sending cell start request to MAC");
1697 /* Send Cell Start Request to MAC */
1698 DU_ALLOC_SHRABL_BUF(cellStartInfo, sizeof(MacCellStartInfo));
1701 DU_LOG("\nDU APP : Memory alloc failed while building cell start request");
1705 for(uint8_t id = 0; id < MAX_NUM_CELL; id++)
1707 if(duCb.actvCellLst[id])
1709 duCb.actvCellLst[id]->firstSlotIndRcvd = FALSE;
1710 cellStartInfo->cellId = duCb.actvCellLst[id]->cellInfo.nrEcgi.cellId;
1713 FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_START_REQ);
1715 return (*packMacCellStartReqOpts[pst.selector])(&pst, cellStartInfo);
1721 /*******************************************************************
1723 * @brief Builds and sends cell stop request to MAC
1727 * Function : duBuildAndSendMacCellStopReq
1730 * Builds and sends cell stop request to MAC
1733 * @return ROK - success
1736 * ****************************************************************/
1737 uint8_t duBuildAndSendMacCellStopReq()
1740 MacCellStopInfo *cellStopInfo = NULL;
1742 DU_LOG("\nDU APP : Building and Sending cell stop request to MAC");
1744 /* Send Cell Stop Request to MAC */
1745 DU_ALLOC_SHRABL_BUF(cellStopInfo, sizeof(MacCellStopInfo));
1748 DU_LOG("\nDU APP : Memory alloc failed while building cell stop request");
1751 cellStopInfo->cellId = duCb.actvCellLst[0]->cellId;
1754 FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_STOP_REQ);
1756 return (*packMacCellStopReqOpts[pst.selector])(&pst, cellStopInfo);
1759 /*******************************************************************
1761 * @brief Handles stop indication from MAC
1765 * Function : duHandleStopInd
1768 * Handles stop indication from MAC
1770 * @params[in] Post structure pointer
1771 * @return ROK - success
1774 * ****************************************************************/
1775 uint8_t duHandleStopInd(Pst *pst, MacCellStopInfo *cellStopId)
1777 if(cellStopId->cellId <=0 || cellStopId->cellId > MAX_NUM_CELL)
1779 DU_LOG("\nDU APP : Invalid Cell Id %d", cellStopId->cellId);
1781 if(duCb.actvCellLst[cellStopId->cellId-1] != NULL)
1783 if(duCb.actvCellLst[cellStopId->cellId-1]->firstSlotIndRcvd)
1785 duCb.actvCellLst[cellStopId->cellId-1]->firstSlotIndRcvd = false;
1786 if((duCb.actvCellLst[cellStopId->cellId-1]->cellStatus == \
1789 DU_LOG("\nDU APP : 5G-NR Cell %d is DOWN", cellStopId->cellId);
1790 duCb.actvCellLst[cellStopId->cellId-1]->cellStatus = DELETION_IN_PROGRESS;
1794 if((pst->selector == ODU_SELECTOR_LWLC) || (pst->selector == ODU_SELECTOR_TC))
1795 DU_FREE_SHRABL_BUF(MAC_MEM_REGION, pst->pool, cellStopId, sizeof(MacCellStopInfo));
1800 /*******************************************************************
1802 * @brief Handles slot indication from MAC
1806 * Function : duHandleUlCcchInd
1809 * Handles UL CCCH indication from MAC
1811 * @params[in] Post structure pointer
1812 * UL CCCH Ind pointer
1813 * @return ROK - success
1816 * ****************************************************************/
1817 uint8_t duHandleUlCcchInd(Pst *pst, UlCcchIndInfo *ulCcchIndInfo)
1820 DU_LOG("\nDU APP : UL CCCH Indication received");
1822 return (duProcUlCcchInd(ulCcchIndInfo));
1826 /**********************************************************************
1828 **********************************************************************/