Initial commit
[o-du/l2.git] / src / 5gnrmac / rg_sch_hdfdd.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:     LTE-MAC layer
22  
23      Type:     C source file
24  
25      Desc:     C source code for HD-FDD functions
26  
27      File:     rg_sch_hdfdd.c
28  
29 **********************************************************************/
30
31 /** @file rg_sch_hdfdd.c
32 @brief This module handles the  Periodic CQI/PMI/RI, SRS, SR and Half Duplex 
33        functionality 
34 */
35 #ifdef LTEMAC_HDFDD
36 static const char* RLOG_MODULE_NAME="MAC";
37 static int RLOG_MODULE_ID=4096;
38 static int RLOG_FILE_ID=165;
39 #endif
40
41 /* header include files -- defines (.h) */
42 #include "envopt.h"        /* environment options */
43 #include "envdep.h"        /* environment dependent */
44 #include "envind.h"        /* environment independent */
45 #include "gen.h"           /* general layer */
46 #include "ssi.h"           /* system service interface */
47 #include "cm_hash.h"       /* common hash list */
48 #include "cm_llist.h"      /* common linked list library */
49 #include "cm_err.h"        /* common error */
50 #include "cm_lte.h"        /* common LTE */
51 #include "lrg.h"
52 #include "rgr.h"
53 #include "tfu.h"
54 #include "rg_env.h"
55 #include "rg_sch_inf.h"
56 #include "rg_sch_err.h"
57 #include  "rgr.h"
58 #include  "rgm.h"
59 #include "rg_sch.h"
60 #include "rg_sch_cmn.h"
61 #include "rl_interface.h"
62 #include "rl_common.h"
63
64 /* header/extern include files (.x) */
65 #include "gen.x"           /* general layer typedefs */
66 #include "ssi.x"           /* system services typedefs */
67 #include "cm5.x"           /* common timers */
68 #include "cm_hash.x"       /* common hash list */
69 #include "cm_lib.x"        /* common library */
70 #include "cm_llist.x"      /* common linked list */
71 #include "cm_mblk.x"       /* memory management */
72 #include "cm_tkns.x"       /* common tokens */
73 #include "cm_lte.x"        /* common tokens */
74 #include "tfu.x"           /* RGU types */
75 #include "lrg.x"           /* layer management typedefs for MAC */
76 #include "rgr.x"           /* layer management typedefs for MAC */
77 #include "rgm.x"           /* layer management typedefs for MAC */
78 #include "rg_sch_inf.x"    /* typedefs for Scheduler */
79 #include "rg_sch.x"        /* typedefs for Scheduler */
80 #include "rg_sch_cmn.x"
81
82
83 #ifdef LTEMAC_HDFDD
84 #ifdef __cplusplus
85 extern "C" {
86 #endif /* __cplusplus */
87
88
89 /* @details
90  *
91  *     Function : rgSCHHdFddUeCfg 
92  *
93  *     Invoking Module Processing:
94  *      - This shall be invoked by SCH_GOM at UE Re/configuration. 
95  *        
96  *     Processing Steps:
97  *     - For UE-specific Half Duplex  
98  *      - Allocate the memory and place the UE in cellCb->hdUeLstCp 
99  *        - Update subframes information state to defualt
100  *        - Update subframes information sfn to defualt
101  *     - Return ROK
102  *
103  *  @param[in]  RgSchCellCb  *cell
104  *  @param[in]  RgSchUeCb    *ue
105  *  @param[in]  Bool         *hdFddEnbl
106  *
107  *  @RETVALUE S16
108  *      -# ROK
109  *      -# RFAILED
110 */ 
111
112 #ifdef ANSI
113 PUBLIC S16 rgSCHHdFddUeCfg 
114 (
115 RgSchCellCb  *cellCb,
116 RgSchUeCb *ueCb,
117 Bool hdFddEnbl
118 )
119 #else /* ANSI */
120 PUBLIC S16 rgSCHHdFddUeCfg (cellCb, ueCb, hdFddEnbl)
121 RgSchCellCb  *cellCb;
122 RgSchUeCb *ueCb;
123 Bool hdFddEnbl;
124 #endif /* ANSI */
125 {
126    U8 sfi;
127    TRC3(rgSCHHdFddUeCfg)
128
129    RLOG_ARG2(L_DEBUG,DBG_CELLID,cellCb->cellId,
130                "rgSCHHdFddUeCfg(): UeId =%d hdFddEnbl=%d",
131                ueCb->ueId, hdFddEnbl);
132    if(ueCb->hdFddEnbld == TRUE)
133    {
134       if (hdFddEnbl == FALSE)
135       {
136          /* Do not allow switch from HD-FDD to FD-FDD configuration */
137          RLOG_ARG1(L_ERROR,DBG_CELLID,cellCb->cellId,
138                "rgSCHHdFddUeCfg(): HD-FDD  to FD-FDD Configuration is not allowed"
139                "CRNTI:%d",ueCb->ueId);
140       }
141       else
142       {
143          /* If already enabled then it can be second reconfiguration */
144          RLOG_ARG1(L_ERROR,DBG_CELLID,cellCb->cellId,
145                   "rgSCHHdFddUeCfg(): HD-FDD already enabled for this UE"
146                   "CRNTI:%d",ueCb->ueId);
147       }
148       RETVALUE(RFAILED);
149    }
150
151 #ifdef LTEMAC_SPS
152    /* Check is SPS enabled for this UE */
153    if(hdFddEnbl == TRUE &&
154        (ueCb->ul.ulSpsCfg.isUlSpsEnabled == TRUE ||
155         ueCb->dl.dlSpsCfg.isDlSpsEnabled == TRUE))
156    {
157       RLOG_ARG1(L_ERROR,DBG_CELLID,cellCb->cellId,
158       "rgSCHHdFddUeCfg(): Could'nt do HDFDD cfg, SPS already configured"
159                "CRNTI:%d",ueCb->ueId);
160       RETVALUE(RFAILED);
161    }
162 #endif
163
164    ueCb->hdFddEnbld = hdFddEnbl;
165    if( hdFddEnbl == TRUE)
166    {
167       rgSCHUtlAllocSBuf(cellCb->instIdx,(Data **) &ueCb->hdFddCb,
168              sizeof(RgSchUeHdFddCb));
169       if (ueCb->hdFddCb != NULLP)
170       {
171          for (sfi = 0; sfi < RG_SCH_HDFDD_NUMSFINFO; sfi++)
172          {
173             ueCb->hdFddCb->subfrm[sfi].subFrmDir = RG_SCH_HDFDD_NOSCHD;
174             ueCb->hdFddCb->subfrm[sfi].sfn      = RG_SCH_HDFDD_INVSFN;
175          }
176          /* Add this UE to list maintained in CellCb */
177          /* cmLListAdd2Tail(&cellCb->hdFddLst,&ueCb->hdFddCb->hdFddLstEnt); */
178       }
179       else
180       {
181          RLOG_ARG1(L_ERROR,DBG_CELLID,cellCb->cellId,
182                "rgSCHHdFddUeCfg(): Could not allocate memory for hd-fdd ueCb"
183                "CRNTI:%d",ueCb->ueId);
184          RETVALUE(RFAILED);
185       }
186    }
187    RETVALUE(ROK);
188 }/*rgSCHHdFddUeCfg*/
189
190
191 /* @brief Frees Half Duplex  related data structures
192  *
193  * @details
194  *
195  *     Function : rgSCHHdFddUeDel
196  *
197  *     Invoking Module Processing:
198  *      - This shall be invoked by SCH_GOM at Ue deletion.
199  *
200  *     Processing Steps:
201  *       - if Half Duplex is enabled
202  *       - if (ueCb->hdFddCb != NULL)
203  *        - Remove ue from  cellCb->hdUeLstCp;
204  *        - Dellocate memory 
205  *       - else
206  *        - Nothing to do
207  *      - Return ROK
208  *  @param[in]  RgSchCellCb  *cell
209  *  @param[in]  RgSchUeCb    *ue
210  *
211  *  @RETVALUE( S16
212  *      -# ROK
213 *
214 */
215 #ifdef ANSI
216 PUBLIC S16 rgSCHHdFddUeDel 
217 (
218 RgSchCellCb *cellCb,
219 RgSchUeCb   *ueCb
220 )
221 #else /* ANSI */
222 PUBLIC S16 rgSCHHdFddUeDel(cellCb, ueCb)
223 RgSchCellCb *cellCb;
224 RgSchUeCb   *ueCb;
225 #endif /* ANSI */
226 {
227  TRC3(rgSCHHdFddUeDel)
228
229    RLOG_ARG2(L_DEBUG,DBG_CELLID,cellCb->cellId,
230              " rgSCHHdFddUeDel(): UeId =%d hdFdd=%x",
231              ueCb->ueId, ueCb->hdFddEnbld);
232
233
234     if (ueCb->hdFddCb)
235     {
236        /* ccpu00117052 - MOD - Passing double pointer
237        for proper NULLP assignment*/
238        rgSCHUtlFreeSBuf(cellCb->instIdx, (Data **)(&(ueCb->hdFddCb)),
239              sizeof(RgSchUeHdFddCb));   
240        ueCb->hdFddEnbld = FALSE;
241     }
242
243     RETVALUE(ROK);
244 } /* rgSCHHdFddUeDel */
245
246
247
248 #ifdef TFU_UPGRADE
249 /* @brief Mark the subframes as uplink for HD FDD if CQI/RI or SRS or RI is
250  * expecting .
251  *
252  * @details
253  *
254  *     Function: rgSCHCmnHdFddPtUlMrk 
255  *     Purpose:  Updation of Periodic CQI/PMI, SRS and SR tranmission
256  *               instance updates
257  *               for HD FDD UEs
258  *  @param[in]  RgSchCellCb *cell
259  *  @RETVALUE   None
260  */
261
262 #ifdef ANSI
263 PUBLIC Void rgSCHCmnHdFddPtUlMrk 
264 (
265 RgSchCellCb *cellCb
266 )
267 #else /* ANSI */
268 PUBLIC Void rgSCHCmnHdFddPtUlMrk (cellCb)
269 RgSchCellCb *cellCb;
270 #endif /* ANSI */
271 {
272    U16                    sfn; /* System Frame Number */
273    U32                    pti; /* Index into Periodic table */
274    U16                    sfi; /* Index into HDFDD state table */
275    CmLListCp              *cqiLst;
276    CmLListCp              *srsLst;
277    CmLListCp              *srLst;
278    CmLListCp              *riLst;
279    CmLList                *cqiNode;
280    CmLList                *srsNode;
281    CmLList                *srNode;
282    CmLList                *riNode;
283    CmLteTimingInfo        timeInfo;
284    RgSchUePCqiCb          *cqiCb = NULLP;
285    RgSchUePCqiCb          *riCb = NULLP;
286
287    TRC3(rgSCHCmnHdFddPtUlMrk)
288
289    timeInfo = cellCb->crntTime;
290
291    /* Determine indexes */
292    pti = RG_SCH_HDFDD_GETPTI(timeInfo);
293    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_HDFDD_DELTA);
294    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_HDFDD_DELTA);
295
296    /* Get PT entries for */
297    cqiLst = &cellCb->pCqiSrsSrLst[pti].cqiLst;
298    srsLst = &cellCb->pCqiSrsSrLst[pti].srsLst;
299    srLst  = &cellCb->pCqiSrsSrLst[pti].srLst;
300    riLst  = &cellCb->pCqiSrsSrLst[pti].riLst;
301
302    /* Get first node in each list */
303    CM_LLIST_FIRST_NODE(cqiLst, cqiNode);
304    CM_LLIST_FIRST_NODE(srsLst, srsNode);
305    CM_LLIST_FIRST_NODE(riLst,  riNode);
306    CM_LLIST_FIRST_NODE(srLst,  srNode);
307
308    /* Mark corresponding the subframe as uplink control */
309    while ((NULLP != cqiNode ) &&
310          (NULLP != srsNode  ) &&
311          (NULLP != srNode   )  &&
312          (NULLP != riNode   ))
313    {
314      cqiCb = (RgSchUePCqiCb *)(cqiNode->node);
315      RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)(cqiCb->servCellInfo->ue),
316                      RG_SCH_HDFDD_UL, sfn, sfi);
317       /* SRS Transmission instances */
318       RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)srsNode->node,
319                      RG_SCH_HDFDD_UL, sfn, sfi);
320       /* SR Transmission instances */
321       RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)srNode->node,
322                      RG_SCH_HDFDD_UL, sfn, sfi);
323       /* RI Transmission instances */
324      riCb = (RgSchUePCqiCb *)(riNode->node);
325      RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)riCb->servCellInfo->ue,
326                      RG_SCH_HDFDD_UL, sfn, sfi);
327
328       /* Get next UeCb for all lists */
329       CM_LLIST_NEXT_NODE(cqiLst, cqiNode);
330       CM_LLIST_NEXT_NODE(srsLst, srsNode);
331       CM_LLIST_NEXT_NODE(srLst, srNode);
332       CM_LLIST_NEXT_NODE(riLst, riNode);
333    }
334
335    while ( NULLP != cqiNode)
336    {
337       /* CQI/PMI Transmission instances */
338       cqiCb = (RgSchUePCqiCb *)(cqiNode->node);
339       RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)(cqiCb->servCellInfo->ue),
340                      RG_SCH_HDFDD_UL, sfn, sfi);
341       CM_LLIST_NEXT_NODE(cqiLst, cqiNode);
342    }
343    while( NULLP != srsNode)
344    {
345       /* SRS Transmission instances */
346       RG_SCH_HDFDD_VLDTANDMARK(((RgSchUeCb*)srsNode->node),
347                      RG_SCH_HDFDD_UL, sfn, sfi);
348       CM_LLIST_NEXT_NODE(srsLst, srsNode);
349    }
350    while( NULLP != srNode)
351    {
352       /* SR Transmission instances */
353       RG_SCH_HDFDD_VLDTANDMARK(((RgSchUeCb*)srNode->node),
354                      RG_SCH_HDFDD_UL, sfn, sfi);
355       CM_LLIST_NEXT_NODE(srLst, srNode);
356    }
357    while( NULLP != riNode)
358    {
359       /* RI Transmission instances */
360      riCb = (RgSchUePCqiCb *)(riNode->node);
361      RG_SCH_HDFDD_VLDTANDMARK((RgSchUeCb*)riCb->servCellInfo->ue,
362                      RG_SCH_HDFDD_UL, sfn, sfi);
363      CM_LLIST_NEXT_NODE(riLst, riNode);
364    }
365
366    RETVOID;
367 } /* rgSCHCmnHdFddPtUlMrk */
368 #endif /* ifdef TFU_UPGRADE */
369
370
371
372 /* @brief Decides whether UE can be allowed for DL in given subframe
373  *
374  * @details
375  *
376  *     Function : rgSCHCmnHdFddChkUlAllow 
377  *
378  *     Invoking Module Processing:
379  *      - This shall be invoked by schedulars before allocating  UL grants .
380  *
381  *     Processing Steps:
382  *       - if Half Duplex is enabled
383  *       - If ue->sf[reqsf].state is "DONWLINK"
384  *            set alloweUlSch=FALSE
385  *       - else
386  *            set alloweUlSch=TRUE
387  *        This function Marking for BCCH/PCCH occasions is also done
388  *      - Return ROK
389  *  @param[in]  RgSchCellCb  *cell
390  *  @param[in]  RgSchUeCb    *ue
391  *
392  *  @RETVALUE   None
393  *
394  */
395 #ifdef ANSI
396 PUBLIC Void rgSCHCmnHdFddChkUlAllow
397
398  RgSchCellCb *cellCb,
399  RgSchUeCb   *ueCb,
400  U8          *allow
401 )
402 #else /* ANSI */
403 PUBLIC Void rgSCHCmnHdFddChkUlAllow ( cellCb, ueCb, allow)
404 RgSchCellCb *cellCb;
405 RgSchUeCb   *ueCb;
406 U8          *allow;
407 #endif /* ANSI */
408 {
409    U16              sfn;
410    U16              sfi;
411    CmLteTimingInfo  timeInfo;
412    RgSchDlSf        *sf = NULLP; /* Dl subframe info */
413    U8               ulOffset
414
415    TRC3(rgSCHCmnHdFddChkUlAllow)
416    
417    RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId, 
418             " rgSCHCmnHdFddChkUlAllow: ueId=%d ", ueCb->ueId);
419
420    *allow = FALSE;
421
422    timeInfo = cellCb->crntTime;
423
424    ulOffset = RGSCH_PDCCH_PUSCH_DELTA - 
425           TFU_CRCIND_ULDELTA + RGSCH_PDCCH_PUSCH_DELTA;
426    RG_SCH_ADD_TO_CRNT_TIME(cellCb->crntTime, timeInfo, ulOffset);
427
428    /* Set default value */
429    *allow = FALSE;
430
431    /* Validate condition 1 */
432    /* For (curretn time + DL_DELTA)th sf */
433
434    /* Also get subframe pointer to fetch Common Ch allocation */
435    sf = rgSCHUtlSubFrmGet(cellCb, timeInfo);
436
437    sfn = timeInfo.sfn;
438    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
439
440    /* Validate condition 2 */
441    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
442    {
443          /* Common channel scheduled */
444          /* Mark the BCCH/PCCH occasion */
445          RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, sfn, sfi);
446          RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
447             "rgSCHCmnHdFddChkUlAllow: Already marked for Cmn DL, ueId = %d ",
448             ueCb->ueId);
449    }
450    if ((ueCb->hdFddCb->subfrm[sfi].sfn == sfn) &&
451          (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLDATA ||
452           ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLCNTRL))
453    {
454       /* Downlink scheduled */
455       *allow = FALSE;
456       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
457                "rgSCHCmnHdFddChkUlAllow: Already marked for DL, ueId = %d ",
458                ueCb->ueId);
459       RETVOID;
460    }
461
462    /* Validate condition 3 */
463    /* For (curretn time + DL_DELTA + HRQ_DELTA)th sf
464       - i.e. next HARQ Feedback occasion */
465    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
466    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
467    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
468        ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL)
469    {
470       /* No place for HARQ feedback */
471       *allow = FALSE;
472       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
473          "rgSCHCmnHdFddChkUlAllow: No Place for HARQ, ueId = %d ",
474          ueCb->ueId);
475       RETVOID;
476
477    }
478    /* Validate condition 4 */
479    /* For (curretn time + DL_DELTA - HRQ_DELTA)th sf
480       - i.e. previous HARQ Feedback occasion */
481    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (-RG_SCH_CMN_HARQ_INTERVAL));
482    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (-RG_SCH_CMN_HARQ_INTERVAL));
483    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
484        ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL)
485    {
486       *allow = FALSE;
487       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
488                " rgSCHCmnHdFddChkUlAllow: No Place for UL grant, ueId = %d ",
489                ueCb->ueId);
490       RETVOID;
491
492    }
493    /* Validate condition 5 */
494    /* For (curretn time + DL_DELTA - 1)th sf -i.e. Guard time */
495    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (-RG_SCH_HDFDD_GRDTIM_DUR));
496    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (-RG_SCH_HDFDD_GRDTIM_DUR));
497    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
498        (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLDATA))
499    {
500       /* This subframe may be a switching gaurd time */
501       *allow = FALSE;
502       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
503              " rgSCHCmnHdFddChkUlAllow: No Place for Guard time, ueId = %d ",
504              ueCb->ueId);
505       RETVOID;
506
507    }
508    /* Adition guard time rule check: Above check is only for PDSCH, lets check
509       is there is any BCCH/PCCH data scheduled */
510    RG_SCH_ADD_TO_CRNT_TIME(cellCb->crntTime, timeInfo, 
511                       (ulOffset - RG_SCH_HDFDD_GRDTIM_DUR));
512    /* Also get subframe pointer to fetch Common Ch allocation */
513    sf = rgSCHUtlSubFrmGet(cellCb, timeInfo);
514    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
515    {
516       /* Common channel scheduled */
517       /* Mark the BCCH/PCCH occasion */
518       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, timeInfo.sfn, sfi);
519       *allow = FALSE;
520       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
521          "rgSCHCmnHdFddChkUlAllow: Already marked for Cmn DL, ueId = %d ",
522          ueCb->ueId);
523       RETVOID;
524
525    }
526
527    /* All validation done. Safe to for UL */
528    *allow = TRUE;
529    RETVOID;
530 } /* rgSCHCmnHdFddChkUlAllow */
531
532
533  /* @brief Decides whether UE can be allowed for UL in given subframe
534  *
535  * @details
536  *
537  *     Function : rgSCHCmnHdFddChkDlAllow
538  *
539  *     Invoking Module Processing:
540  *      - This shall be invoked by schedulars before allocating for DL.
541  *
542  *     Processing Steps:
543  *          Condition 1:  subframe n + DL_DELTA should not be uplink
544  *          Condition 2:  subframe n+ DL_DELTA + 1 should meet guard time
545  *                        creation rule. For more
546  *                        information refer to section "2.25.7.1 Guard time
547  *                        creation rule"
548  *          Condition 3:  subframe n + DL_DELTA + HRQ_DELTA should not be
549  *                        downlink so that downlink data (HARQ Feedback)
550  *                        can be received in next 4 subframe. {n + 7} Above
551  *                        conditions have to
552  *                        be validated by taking SFN number into consideration.
553  *          if all conditions are met then *allow is set to TRUE or lese to
554  *          FALSE.
555  *          if hd-fdd is not anabled for this UE, then *allow is always TRUE.
556  *   
557  *   Returns None
558  *  @param[in]  RgSchCellCb  *cellCb
559  *  @param[in]  RgSchUeCb    *ueCb
560  *  @param[in]  CmLteTimingInfo    *timeInfo
561  *  @param[out] U8 *allow -- TRUE is allowed or FALSE if no allowedi.
562  *                   Valdity of this pointer is not done in this function
563  *
564  */
565 #ifdef ANSI
566 PUBLIC Void rgSCHCmnHdFddChkDlAllow 
567 (
568 RgSchCellCb *cellCb,
569 RgSchUeCb *ueCb,
570 Bool *allow /* Valdity of this pointer is not done in this function */
571 )
572 #else /* ANSI */
573 PUBLIC Void rgSCHCmnHdFddChkDlAllow ( cellCb, ueCb, allow)
574 RgSchCellCb *cellCb;
575 RgSchUeCb *ueCb;
576 Bool *allow; /* Valdity of this pointer is not done in this function */
577 #endif /* ANSI */
578 {
579    U16     sfn;
580    U16     sfi;
581    RgSchDlSf *sf = NULLP; /* Dl subframe info */
582    CmLteTimingInfo timeInfo;
583    CmLteTimingInfo tempTimeInfo;
584
585    TRC3(rgSCHCmnHdFddChkDlAllow)
586
587    *allow = FALSE;
588
589    timeInfo = cellCb->crntTime;
590    RGSCH_INCR_SUB_FRAME(timeInfo, RG_SCH_CMN_DL_DELTA);
591
592    RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
593             "rgSCHCmnHdFddDlSchAll (): ueId=%d ", ueCb->ueId);
594
595    /* Also get subframe pointer to fetch Common Ch allocation */
596    sf = rgSCHUtlSubFrmGet(cellCb, timeInfo);
597
598    /* Validate condition 1 */
599    /* For (curretn time + DL_DELTA)th sf */
600    sfn = timeInfo.sfn;
601    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
602
603    if ((ueCb->hdFddCb->subfrm[sfi].sfn == sfn) &&
604         (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL))
605    {
606       /* Uplink scheduled */
607       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
608                "rgSCHCmnHdFddChkDlAllow: sf is UL, ueId=%d ", ueCb->ueId);
609       *allow = FALSE;
610       RETVOID;
611    }
612
613    /* It is not validation, but BCCH/PCCH marking is done here */
614    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
615    {
616       /* Common channel scheduled */
617       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, sfn, sfi); /* NOT_HIT */
618    }
619
620    /* Validate condition 2 */
621    /* For (curretn time + DL_DELTA + 1)th sf -i.e. Guard time */
622    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
623    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
624    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
625           (ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_UL))
626    {
627       /* This subframe may be a switching guard time */
628       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
629               " rgSCHCmnHdFddChkDlAllow: Guard time rule not met, ueId=%d ",
630               ueCb->ueId);
631       *allow = FALSE;
632       RETVOID;
633    }
634
635    /* Validate condition 3 */
636    /* For (curretn time + DL_DELTA + HRQ_DELTA)th sf - i.e. next HARQ
637       Feedback occasion */
638
639    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
640    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
641
642    /* First check for any Common channel info is scheduled */
643    RG_SCH_ADD_TO_CRNT_TIME(timeInfo, tempTimeInfo, RG_SCH_CMN_HARQ_INTERVAL)
644    /* Also get subframe pointer to fetch Common Ch allocation */
645    sf = rgSCHUtlSubFrmGet(cellCb, tempTimeInfo);
646    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
647    {
648          /* Common channel scheduled */
649       /* Do the marking for this subframe */
650       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, tempTimeInfo.sfn, sfi);
651       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
652               "rgSCHCmnHdFddChkDlAllow: Possible systemInfo, ueId=%d ",
653               ueCb->ueId);
654    }
655
656    /* Check for actual validation condition 3 */
657    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
658        ueCb->hdFddCb->subfrm[sfi].subFrmDir != RG_SCH_HDFDD_UL)
659    {
660       /* No place for HARQ feedback */
661       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,  
662             "rgSCHCmnHdFddChkDlAllow: No place for HARQ feedback, ueId=%d ",
663             ueCb->ueId);
664       *allow = FALSE;
665
666       /* Mark this sf as DLCNTRL */
667       ueCb->hdFddCb->subfrm[sfi].subFrmDir =RG_SCH_HDFDD_DLCNTRL;
668       RETVOID;
669    }
670
671
672    /* If we are here then, subframe at HARQth location can be UL.
673       But check if Guard violation is done */
674    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL-1);
675    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL-1);
676    /* check for any Common channel info is scheduled */
677    RG_SCH_ADD_TO_CRNT_TIME(timeInfo, tempTimeInfo, (RG_SCH_CMN_HARQ_INTERVAL-1))
678    /* Also get subframe pointer to fetch Common Ch allocation */
679    sf = rgSCHUtlSubFrmGet(cellCb, tempTimeInfo);
680    if (RG_SCH_HDFDD_ISCMN_SCHED(sf))
681    {
682          /* Common channel scheduled */
683       /* Do the marking for this subframe */
684       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, tempTimeInfo.sfn, sfi);
685       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,
686               "rgSCHCmnHdFddChkDlAllow: (GT) Possible systemInfo, ueId=%d ",
687               ueCb->ueId);
688    }
689
690    if (ueCb->hdFddCb->subfrm[sfi].sfn == sfn &&
691        ueCb->hdFddCb->subfrm[sfi].subFrmDir == RG_SCH_HDFDD_DLDATA)
692    {
693       /* No place for HARQ feedback */
694       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,
695             "rgSCHCmnHdFddChkDlAllow: (GT) No place for HARQ feedback,"
696              "ueId=%d ",ueCb->ueId);
697
698       *allow = FALSE;
699       RETVOID;
700    }
701    /* First check for any Common channel info is scheduled */
702
703    *allow = TRUE;
704    /* All validation done. Safe to for DL */
705    RETVOID;
706 } /* rgSCHCmnHdFddChkDlAllow */
707
708
709
710 /* @brief Decides whether NACK can be sent in a given subrame
711  *
712  * @details
713  *
714  *     Function : rgSCHCmnHdFddChkNackAllow
715  *
716  *     Invoking Module Processing:
717  *      - This shall be invoked by schedulars.
718  *
719  *  @param[in]  RgSchUeCb    *ue
720  *
721  *  @RETVALUE None
722  *
723  */
724
725 #ifdef ANSI
726 PUBLIC Void rgSCHCmnHdFddChkNackAllow
727 (
728 RgSchCellCb *cellCb,
729 RgSchUeCb   *ueCb,
730 CmLteTimingInfo  timeInfo,
731 Bool *sndNACK
732 )
733 #else /* ANSI */
734 PUBLIC Void rgSCHCmnHdFddChkNackAllow(cellCb, ueCb, timeInfo, sndNACK)
735 RgSchCellCb *cellCb;
736 RgSchUeCb   *ueCb;
737 CmLteTimingInfo  timeInfo;
738 Bool *sndNACK;
739 #endif /* ANSI */
740 {
741    RgSchDlSf *sf;
742    CmLteTimingInfo  tempTimeInfo;
743
744    TRC3(rgSCHCmnHdFddChkNackAllow)
745
746    /* Information in timeInfo contains (n+DL_DELTA) th subframe info*/
747
748    *sndNACK = FALSE;
749
750    /* Determine SFN and sf index for current subframe.
751       Note: Round function used as example */
752    tempTimeInfo = timeInfo;
753    RGSCH_INCR_SUB_FRAME(tempTimeInfo, RG_SCH_CMN_HARQ_INTERVAL);
754
755    /* Also get subframe pointer to fetch Common Ch allocation */
756    sf = rgSCHUtlSubFrmGet(cellCb, tempTimeInfo);
757
758    /* Check is this subframe has any Common Channel info scheduled */
759    if(RG_SCH_HDFDD_ISCMN_SCHED(sf))
760    {
761       /* Yes, Cannot send NACK */
762       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,
763                "rgSCHCmnHdFddChkNackAllow: Cannot send NACK, ueId = %d ",
764                ueCb->ueId);
765       *sndNACK = FALSE;
766    }
767    else
768    {
769       /* safe, Send NACK */
770       RLOG_ARG1(L_DEBUG,DBG_CELLID,cellCb->cellId,
771                "rgSCHCmnHdFddChkNackAllow: NACk can be sent, ueId = %d ",
772                ueCb->ueId);
773       *sndNACK = TRUE;
774    }
775
776    RETVOID;
777 } /* rgSCHCmnHdFddChkNackAllow */
778
779
780
781
782  /* @brief makes final marking for HD-FDD UL allocations
783  *
784  * @details
785  *
786  *     Function : rgSCHCmnHdFddUpdULMark
787  *
788  *     Invoking Module Processing:
789  *      - This shall be invoked by schedulars at the time of UL allocation
790  *        finalization.
791  *
792  *     Processing Steps:
793  *   
794  *  @param[in]  RgSchCellCb  *cellCb
795  *  @param[in]  RgSchUeCb    *ueCb
796  *  @param[in]  CmLteTimingInfo    *timeInfo
797  *  @param[out] U8 *allow -- TRUE is allowed or FALSE if no allowedi.
798  *             Valdity of this pointer is not done in this function.
799  *
800  *  @RETVALUE None
801  */
802 #ifdef ANSI
803 PUBLIC Void rgSCHCmnHdFddUpdULMark
804 (
805 RgSchCellCb *cellCb,
806 RgSchUeCb   *ueCb
807 )
808 #else /* ANSI */
809 PUBLIC Void rgSCHCmnHdFddUpdULMark ( cellCb, ueCb)
810 RgSchCellCb *cellCb;
811 RgSchUeCb   *ueCb;
812 #endif /* ANSI */
813 {
814
815    U16 sfn;
816    U16 sfi;
817    CmLteTimingInfo  timeInfo;
818    U8   ulOffset;
819
820    TRC3(rgSCHCmnHdFddUpdULMark)
821
822
823    ulOffset = RGSCH_PDCCH_PUSCH_DELTA - 
824               TFU_CRCIND_ULDELTA + RGSCH_PDCCH_PUSCH_DELTA;
825    RG_SCH_ADD_TO_CRNT_TIME(cellCb->crntTime, timeInfo, ulOffset)
826
827
828    /* Mark (n + UL_DELTA)th subframe as UL */
829    sfn = timeInfo.sfn;
830    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
831
832    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_UL, sfn, sfi);
833
834    /* Mark (n + UL_DELTA + HARQ_DELTA)th subframe as DL */
835    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
836    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
837    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
838
839    /* Mark (n + UL_DELTA - HARQ_DELTA)th subframe as DL */
840    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (0-RG_SCH_CMN_HARQ_INTERVAL));
841    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (0-RG_SCH_CMN_HARQ_INTERVAL));
842    if (ueCb->hdFddCb->subfrm[sfi].subFrmDir != RG_SCH_HDFDD_DLDATA)
843    {
844       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
845    }
846
847    /* Mark (n + UL_DELTA - 1)th subframe as DL_CNTRL */
848    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, -RG_SCH_HDFDD_GRDTIM_DUR);
849    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, -RG_SCH_HDFDD_GRDTIM_DUR);
850    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
851
852    /* Remove marking for older subframes */
853
854    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, (S16)(ulOffset * -1));
855    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, (ulOffset * -1));
856    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_NOSCHD, RG_SCH_HDFDD_INVSFN, sfi);
857
858    RETVOID;
859 } /* rgSCHCmnHdFddUpdULMark */
860
861
862
863
864  /* @brief makes final marking for HD-FDD DL allocations
865  *
866  * @details
867  *
868  *     Function : rgSCHCmnHdFddUpdDLMark
869  *
870  *     Invoking Module Processing:
871  *      - This shall be invoked by schedulars at the time of DL allocation
872  *          finalization.
873  *
874  *     Processing Steps:
875  *   
876  *  @param[in]  RgSchCellCb  *cellCb
877  *  @param[in]  RgSchUeCb    *ueCb
878  *  @param[in]  CmLteTimingInfo    *timeInfo
879  *  @param[out] U8 *allow -- TRUE is allowed or FALSE if no allowed.
880  *                Valdity of this pointer is not done in this function
881  *
882  *  @RETVALUE None
883  */
884
885 #ifdef ANSI
886 PUBLIC Void rgSCHCmnHdFddUpdDLMark
887 (
888 RgSchCellCb *cellCb,
889 RgSchUeCb   *ueCb
890 )
891 #else /* ANSI */
892 PUBLIC Void rgSCHCmnHdFddUpdDLMark (cellCb, ueCb)
893 RgSchCellCb *cellCb;
894 RgSchUeCb   *ueCb;
895 #endif /* ANSI */
896 {
897
898    U16 sfn;
899    U16 sfi;
900    CmLteTimingInfo  timeInfo;
901
902    TRC3(rgSCHCmnHdFddUpdDLMark)
903
904    timeInfo = cellCb->crntTime;
905    RGSCH_INCR_SUB_FRAME(timeInfo, RG_SCH_CMN_DL_DELTA);
906
907    /* Mark (n + DL_DELTA)th subframe as DL */
908    sfn = timeInfo.sfn;
909    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, 0);
910
911    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLDATA, sfn, sfi);
912
913    /* Mark (n + 1)th subframe as DL_CNTRL */
914    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
915    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_HDFDD_GRDTIM_DUR);
916    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
917
918    /* Mark (n + DL_DELTA + HARQ_DELTA )th subframe as UL */
919    RG_SCH_HDFDD_GETSFN(sfn, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
920    RG_SCH_HDFDD_GETSFI(sfi, timeInfo, RG_SCH_CMN_HARQ_INTERVAL);
921    RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_UL, sfn, sfi);
922
923    /* Mark (n + DL_DELTA + HARQ_DELTA - 1)th subframe
924       as DL control for Guard period */
925    RG_SCH_HDFDD_GETSFN(sfn, timeInfo,
926           (RG_SCH_CMN_HARQ_INTERVAL - RG_SCH_HDFDD_GRDTIM_DUR));
927    RG_SCH_HDFDD_GETSFI(sfi, timeInfo,
928          (RG_SCH_CMN_HARQ_INTERVAL - RG_SCH_HDFDD_GRDTIM_DUR));
929    if (ueCb->hdFddCb->subfrm[sfi].subFrmDir != RG_SCH_HDFDD_UL)
930    {
931       RG_SCH_HDFDD_MARKSTATE(ueCb, RG_SCH_HDFDD_DLCNTRL, sfn, sfi);
932    }
933
934    RETVOID;
935 } /* rgSCHCmnHdFddUpdDLMark */
936
937
938  /* @brief determines effective SFN
939  *
940  * @details
941  *
942  *     Function : rgSCHHdFddGetSfn
943  *
944  *     Invoking Module Processing:
945  *       Any HD-FDD module can invoke this function.
946  *
947  *     Processing Steps:
948  *   
949  *  @param[out]  *sfn U32
950  *  @param[in]  timeInfo timing information subframe of interest 
951  *  @param[in]  offsest  Offest with w.r.t which SFN has to be determined
952  *
953  *  @RETVALUE None
954  */
955
956 #ifdef ANSI
957 PUBLIC Void rgSCHHdFddGetSfn
958 (
959  U16 *sfn,
960  CmLteTimingInfo  timeInfo,
961  S16 offset
962 )
963 #else /* ANSI */
964 PUBLIC Void rgSCHHdFddGetSfn (sfn, timeInfo, offset)
965  U16 *sfn;
966  CmLteTimingInfo  timeInfo;
967  S16 offset;
968 #endif /* ANSI */
969 {
970    U16 tempSfn;
971    S16 tempSfCount;
972
973    TRC3(rgSCHHdFddGetSfn)
974    if(((S16)(timeInfo.subframe) + offset) >= RGSCH_NUM_SUB_FRAMES)
975    {
976       /* Increament to number of times of SFNs that can be possible
977          with this offset */
978       tempSfn = (timeInfo.sfn +
979                 ((timeInfo.subframe + offset) / RGSCH_NUM_SUB_FRAMES))
980                 & (RGSCH_MAX_SFN -1); /* Mod with MAX SFN supported */
981    }
982    else
983    {
984       if(((S16)(timeInfo.subframe) + offset) < 0)
985       {
986          /* If negative, then definitely at least previous SFN */
987          tempSfn = (timeInfo.sfn - 1) & (RGSCH_MAX_SFN -1);
988
989          /* Now find how many more times we need to decreament */
990          tempSfCount = timeInfo.subframe + offset;
991          RG_SCH_HDFDD_ROLLSFN(tempSfCount, tempSfn);
992       }
993       else
994       {
995          /* No change in sfn */
996          tempSfn = timeInfo.sfn;
997       }
998    }
999    *sfn = tempSfn;
1000
1001    RETVOID;
1002 } /* End of rgSCHHdFddGetSfn */
1003
1004
1005 #ifdef __cplusplus
1006 }
1007  /* extern C */
1008 #endif /* __cplusplus */
1009
1010 #endif /* LTEMAC_HDFDD */
1011
1012
1013
1014
1015 /**********************************************************************
1016  
1017          End of file
1018 **********************************************************************/