U8, U16, U32 data type changes
[o-du/l2.git] / src / 5gnrsch / rg_sch_pwr.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 power control functionality
26  
27      File:     rg_sch_pwr.c
28  
29 **********************************************************************/
30
31 /** @file rg_sch_pwr.c
32 @brief This module handles schedulers' power control functionality
33 */
34
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_MODULE_ID=4096;
37 static int RLOG_FILE_ID=188;
38 /* header include files -- defines (.h) */
39 #include "common_def.h"
40 #include "lrg.h"
41 #include "rgr.h"
42 #include "rgm.h"
43 #include "tfu.h"
44 #include "rg_env.h"
45 #include "rg_sch_inf.h"
46 #include "rg_sch_err.h"
47 #include "rg_sch.h"
48 #include "rg_sch_cmn.h"
49
50 /* header/extern include files (.x) */
51 #include "tfu.x"           /* RGU types */
52 #include "lrg.x"           /* layer management typedefs for MAC */
53 #include "rgr.x"           /* layer management typedefs for MAC */
54 #include "rgm.x"           /* layer management typedefs for MAC */
55 #include "rg_sch_inf.x"    /* typedefs for Scheduler */
56 #include "rg_sch.x"        /* typedefs for Scheduler */
57 #include "rg_sch_cmn.x"
58 #include "rl_interface.h"
59 #include "rl_common.h"
60
61
62 /* Current specs have 23 dBm as max tx power capability for UEs */
63 #define RG_SCH_PWR_UE_MAX_PWR    23
64
65 #define RG_SCH_REF_PCMAX         0xFF
66
67 #define RG_SCH_CMN_GET_UL_UE(_ue,_cell) (&(((RgSchCmnUe *)((_ue->cellInfo[_ue->cellIdToCellIdxMap\
68                [RG_SCH_CELLINDEX(_cell)]])->sch))->ul))
69 #define RG_SCH_PWR_GETUEPWR(_ue, _cell) &(((RgSchCmnUe *)((_ue->cellInfo[_ue->cellIdToCellIdxMap\
70                [RG_SCH_CELLINDEX(_cell)]])->sch))->ul.ulPwrCb)
71 #define RG_SCH_PWR_GETCELLPWR(cell) &((RgSchCmnCell *)((cell)->sc.sch))->ul.ulPwrCb
72
73
74 typedef S8 RgSchCmnUlPwrCqiToPwrTbl[RG_SCH_CMN_UL_NUM_CQI];
75
76 PRIVATE RgSchCmnUlPwrCqiToPwrTbl rgSchPwrCqiToPwrTbl;
77
78 /* This table maps a given number of RBs (given by array index)
79  * to the power in dB that these many RBs map to. */
80 CONSTANT uint8_t rgSchPwrRbToPwrTbl[111] = { 0,    /* First entry is dummy */
81    0,  3,  4,  6,  7,  7,  8,  9,  9,  10,
82    10, 10, 11, 11, 11, 12, 12, 12, 12, 13,
83    13, 13, 13, 13, 14, 14, 14, 14, 14, 14,
84    15, 15, 15, 15, 15, 15, 15, 15, 16, 16,
85    16, 16, 16, 16, 16, 16, 16, 16, 17, 17,
86    17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
87    17, 18, 18, 18, 18, 18, 18, 18, 18, 18,
88    18, 18, 18, 18, 18, 18, 18, 19, 19, 19,
89    19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
90    19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
91    20, 20, 20, 20, 20, 20, 20, 20, 20, 20
92 };
93
94
95 /* This table maps power (in dB) to number of RBs */
96 /* The array size comes from max power in rgSchPwrRbToPwrTbl */
97 CONSTANT uint8_t rgSchPwrToRbTbl[20+1] = {
98   1, 1, 2, 2, 3, 4, 5, 6, 7, 9, 11,
99   13, 17, 21, 26, 33, 41, 52, 65, 82, 103 
100 };
101
102
103
104 PRIVATE S8 rgSCHPwrGetCqiPwr ARGS((
105          uint8_t                  cqi
106          ));
107 PRIVATE S8 rgSCHPwrGetCqiPwrForUe ARGS((
108          RgSchCellCb          *cell,
109          RgSchUeCb          *ue,
110          uint8_t                  cqi
111          ));
112 PRIVATE S8 rgSCHPwrCalcEfficncyPwr ARGS((
113          uint32_t                 eff
114          ));
115 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi ARGS((
116          uint8_t                  crntCqi,
117          uint8_t                  trgCqi,
118          RgSchUeCb           *ue,
119          RgSchCellCb         *cell
120          ));
121 PRIVATE Void rgSCHPwrGetPuschTpc ARGS((
122          uint8_t                  isAcc,
123          S8                  delta,
124          S8                  availPwr,
125          uint8_t                 *tpc,
126          S8                 *tpcDelta
127          ));
128 PRIVATE uint8_t rgSCHPwrGetMaxRb ARGS((
129          RgSchCellCb          *cell,
130          S8                  pwr
131          ));
132 PRIVATE uint8_t rgSCHPwrRbToPwr ARGS((
133          RgSchCellCb          *cell,
134          uint8_t                  numRb
135          ));
136 PRIVATE Void rgSCHPwrSchedPucchRnti ARGS((
137          RgSchCellCb          *cell,
138          RgSchCmnTpcRntiCb    *cb,
139          RgSchPdcch           *pdcch,
140          RgSchDlSf            *dlSf,
141          Bool                 *sched
142          ));
143 PRIVATE Void rgSCHPwrPuschCntrl ARGS((
144          RgSchCellCb          *cell,
145          RgSchUeCb            *ue
146          ));
147 PRIVATE Void rgSCHPwrPucchCntrl ARGS((
148          RgSchCellCb *cell,
149          RgSchUeCb   *ue
150          ));
151 PRIVATE Void rgSCHPwrSchedPuschRnti ARGS((
152          RgSchCellCb          *cell,
153          RgSchCmnTpcRntiCb    *cb,
154          RgSchPdcch           *pdcch,
155          RgSchUlSf            *ulSf,
156          Bool                 *sched
157          ));
158 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe ARGS((
159          RgSchUeCb            *ue,
160          uint8_t                   *tpc,
161          S8                   *delta
162          ));
163 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe ARGS((
164          RgSchUeCb            *ue,
165          uint8_t                   *tpc,
166          S8                   *delta
167          ));
168 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe ARGS((
169          RgSchUeCb            *ue,
170          uint8_t                   *tpc,
171          S8                   *delta
172          ));
173 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe ARGS((
174          RgSchUeCb            *ue,
175          uint8_t                   *tpc,
176          S8                   *delta
177          ));
178 PRIVATE Void rgSCHPwrGetAcc1bitTpc ARGS((
179          S8                    remPwr,
180          uint8_t                   *tpc,
181          S8                   *delta
182          ));
183 PRIVATE Void rgSCHPwrGetAcc2bitTpc ARGS((
184          S8                   remPwr,
185          uint8_t                  *tpc,
186          S8                  *delta
187          ));
188 PRIVATE Void rgSCHPwrGetAbsTpc ARGS((
189          S8                   remPwr,
190          uint8_t                  *tpc,
191          S8                  *delta
192          ));
193 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe  ARGS((
194          RgSchCellCb          *cell,
195          RgSchUeCb            *ue,
196          S8                    delta
197          ));
198 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe  ARGS((
199          RgSchCellCb          *cell,
200          RgSchUeCb            *ue,
201          S8                    delta
202          ));
203 PRIVATE Bool rgSCHPwrIsDlUeSched ARGS((
204          RgSchCellCb            *cell,
205          RgSchUeCb            *ue,
206          RgSchDlSf            *sf
207          ));
208 PRIVATE Bool rgSCHPwrIsUlUeSched ARGS((
209          RgSchCellCb          *cell,
210          RgSchUeCb            *ue,
211          RgSchUlSf            *sf
212          ));
213 PRIVATE Void rgSCHPwrOnSchedPucchTpc ARGS((
214          RgSchCellCb           *cell,
215          RgSchUeCb             *ue,
216          S8                     delta
217          ));
218 PRIVATE Void rgSCHPwrOnSchedPuschTpc ARGS((
219          RgSchCellCb           *cell,
220          RgSchUeCb             *ue
221          ));
222 PRIVATE S16 rgSCHPwrApplyUePwrCfg  ARGS((
223          RgSchCellCb          *cell,
224          RgSchUeCb            *ue,
225          RgrUeUlPwrCfg        *pwrCfg
226          ));
227 PRIVATE Void rgSCHPwrUeResetPucch ARGS((
228          RgSchCellCb          *cell,
229          RgSchUeCb            *ue
230          ));
231 PRIVATE Void rgSCHPwrUeResetPusch ARGS((
232          RgSchCellCb          *cell,
233          RgSchUeCb            *ue
234          ));
235 PRIVATE Void rgSCHPwrOnPuschPwrUpd ARGS((
236          RgSchCellCb          *cell,
237          RgSchUeCb            *ue
238          ));
239 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst  ARGS((
240          RgSchCellCb          *cell,
241          CmLteRnti             rnti,
242          Bool                  isFmt3a
243          ));
244 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst  ARGS((
245          RgSchCellCb          *cell,
246          CmLteRnti             rnti,
247          Bool                  isFmt3a
248          ));
249 PRIVATE Void rgSCHPwrInitTpcRntiCb  ARGS((
250          RgSchCmnTpcRntiCb    *cb,
251          CmLteRnti             rnti,
252          Bool                  isFmt3a
253          ));
254 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb ARGS((
255          RgSchCellCb *cell,
256          CmLteRnti   tpcRnti
257          ));
258 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb ARGS((
259          RgSchCellCb *cell,
260          CmLteRnti   tpcRnti
261          ));
262 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb ARGS((
263          RgSchCellCb           *cell,
264          RgSchCmnTpcRntiCb     *cb,
265          RgSchUeCb             *ue
266          ));
267 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb ARGS((
268          RgSchCellCb           *cell,
269          RgSchCmnTpcRntiCb     *cb,
270          RgSchUeCb             *ue
271          ));
272 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb ARGS((
273          RgSchCellCb           *cell,
274          RgSchCmnTpcRntiCb     *cb,
275          RgSchUeCb             *ue
276          ));
277 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb ARGS((
278          RgSchCellCb           *cell,
279          RgSchCmnTpcRntiCb     *cb,
280          RgSchUeCb             *ue
281          ));
282 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb ARGS((
283          RgSchCellCb           *cell,
284          RgSchCmnTpcRntiCb     *cb
285          ));
286 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb ARGS((
287          RgSchCellCb           *cell,
288          RgSchCmnTpcRntiCb     *cb,
289          RgSchUeCb             *ue
290          ));
291 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb ARGS((
292          RgSchCellCb           *cell,
293          RgSchCmnTpcRntiCb     *cb
294          ));
295 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb ARGS((
296          RgSchCmnTpcRntiCb     *cb,
297          RgSchUeCb             *ue
298          ));
299 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb ARGS((
300          RgSchCellCb           *cell,
301          RgSchCmnTpcRntiCb     *cb,
302          RgSchUeCb             *ue
303          ));
304 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb ARGS((
305          RgSchCellCb           *cell,
306          RgSchCmnTpcRntiCb     *cb,
307          RgSchUeCb             *ue
308          ));
309 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb ARGS((
310          RgSchCellCb           *cell,
311          RgSchCmnTpcRntiCb     *cb,
312          RgSchUeCb             *ue
313          ));
314 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb ARGS((
315          RgSchCellCb           *cell,
316          RgSchCmnTpcRntiCb     *cb,
317          RgSchUeCb             *ue
318          ));
319 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb ARGS((
320          RgSchCellCb           *cell,
321          RgSchCmnTpcRntiCb     *cb
322          ));
323 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb ARGS((
324          RgSchCellCb           *cell,
325          RgSchCmnTpcRntiCb     *cb
326          ));
327 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx ARGS((
328          RgSchCmnTpcRntiCb     *cb,
329          uint8_t                     idx
330          ));
331 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx ARGS((
332          RgSchCmnTpcRntiCb     *cb,
333          uint8_t                     idx
334          ));
335 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx ARGS((
336          RgSchCmnTpcRntiCb     *cb,
337          uint8_t                     idx
338          ));
339 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx ARGS((
340          RgSchCmnTpcRntiCb     *cb,
341          uint8_t                     idx
342          ));
343 PRIVATE S16 rgSCHPwrChkTpcRntiIdx ARGS((
344          RgSchCmnTpcRntiCb     *cb,
345          uint8_t                     idx
346          ));
347 PRIVATE S8 rgSCHPwrGetPhValFromPhr ARGS((
348          uint8_t                    phr
349          ));
350 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax ARGS((
351          uint8_t                    pCMax
352          ));
353
354 /* local defines */
355
356
357 /**
358  * @brief Does power related initialisation (not cell specific).
359  *        
360  *
361  * @details
362  *
363  *     Function : rgSCHPwrInit
364  *
365  *     Processing Steps:
366  *      - This shall precompute coding efficiency to power
367  *        mappings (assuming beta of 1).
368  *
369  *  @return  Void
370  **/
371 #ifdef ANSI
372 Void rgSCHPwrInit
373 (
374 Void
375 )
376 #else
377 Void rgSCHPwrInit()
378 #endif
379 {
380    uint8_t             idx;
381
382    rgSchPwrCqiToPwrTbl[0] = 0;  /* This should never be used anyway */
383    for (idx = 1; idx < RG_SCH_CMN_UL_NUM_CQI; ++idx)
384    {
385       rgSchPwrCqiToPwrTbl[idx] = rgSCHPwrCalcEfficncyPwr(rgSchCmnUlCqiTbl[idx].eff);
386    }
387    return;
388 }
389
390 /***********************************************************
391  *
392  *     Func : rgSCHPwrGetCqiPwr
393  *
394  *     Desc : Returns power corresponding to coding efficiency
395  *            when beta pusch is assumed 1.
396  *
397  *     Ret  : uint8_t
398  *
399  *     Notes:
400  *
401  *     File :
402  *
403  **********************************************************/
404 #ifdef ANSI
405 PRIVATE S8 rgSCHPwrGetCqiPwr
406 (
407 uint8_t                  cqi
408 )
409 #else
410 PRIVATE S8 rgSCHPwrGetCqiPwr(cqi)
411 uint8_t                  cqi;
412 #endif
413 {
414
415    return (rgSchPwrCqiToPwrTbl[cqi]);
416 }  /* rgSCHPwrGetCqiPwr */
417
418 /***********************************************************
419  *
420  *     Func : rgSCHPwrGetCqiPwrForUe
421  *
422  *     Desc : If MCS control is enabled for UE, returns
423  *            power corresponding to CQI, else 0.
424  *
425  *     Ret  : uint8_t
426  *
427  *     Notes:
428  *
429  *     File :
430  *
431  **********************************************************/
432 #ifdef ANSI
433 PRIVATE S8 rgSCHPwrGetCqiPwrForUe
434 (
435 RgSchCellCb        *cell,
436 RgSchUeCb          *ue,
437 uint8_t                  cqi
438 )
439 #else
440 PRIVATE S8 rgSCHPwrGetCqiPwrForUe(cell, ue, cqi)
441 RgSchCellCb        *cell;
442 RgSchUeCb          *ue;
443 uint8_t                  cqi;
444 #endif
445 {
446    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
447
448    if (!uePwr->deltaMcsEnbld)
449    {
450       return (0);
451    }
452    return (rgSCHPwrGetCqiPwr(cqi));
453 }  /* rgSCHPwrGetCqiPwrForUe */
454
455 /***********************************************************
456  *
457  *     Func : rgSCHPwrCalcEfficncyPwr
458  *
459  *     Desc : Computes power corresponding to a coding
460  *            efficiency.
461  *
462  *     Ret  : uint8_t
463  *
464  *     Notes: Assumes beta pusch to be 1
465  *
466  *     File :
467  *
468  **********************************************************/
469 #ifdef ANSI
470 PRIVATE S8 rgSCHPwrCalcEfficncyPwr
471 (
472 uint32_t                 eff
473 )
474 #else
475 PRIVATE S8 rgSCHPwrCalcEfficncyPwr(eff)
476 uint32_t                 eff;
477 #endif
478 {
479    F64          ks = 1.25; /* or F64 */
480    F64          tmp = cmPow(2, ks*eff/1024) - 1;
481
482    if (tmp <= 0)
483       return (0);
484    return ((S8)(10 * cmLog10(tmp)));
485 }  /* rgSCHPwrCalcEfficncyPwr */
486
487
488 /**
489  * @brief Returns TPC to be sent in UL allocation
490  *
491  * @details
492  *
493  *     Function : rgSCHPwrPuschTpcForUe
494  *
495  *     Invoking Module Processing:
496  *      - After allocation for UE, this function shall
497  *        be invoked to retrieve TPC.
498  *      - This assumes that rgSCHPwrGetMaxUlRb() was
499  *        invoked prior to final allocation for UE.
500  *        
501  *     Processing Steps:
502  *     - Just return TPC that was determined
503  *       earlier.
504  *     - After this, do necessary updates.
505  *
506  *  @param[in]  RgSchCellCb  *cell
507  *  @param[in]  RgSchUeCb    *ue
508  *  @return  uint8_t
509  **/
510 #ifdef ANSI
511 uint8_t rgSCHPwrPuschTpcForUe
512 (
513 RgSchCellCb *cell,
514 RgSchUeCb   *ue
515 )
516 #else
517 uint8_t rgSCHPwrPuschTpcForUe(cell, ue)
518 RgSchCellCb *cell;
519 RgSchUeCb   *ue;
520 #endif
521 {
522    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue,cell);
523
524    UNUSED(cell);
525
526    rgSCHPwrOnSchedPuschTpc(cell, ue);
527    return (uePwr->puschTpc);
528 }
529
530 /**
531  * @brief Handles Pusch power control for DCI format 0
532  *
533  * @details
534  *
535  *     Function : rgSCHPwrGetMaxUlRb
536  *
537  *     Invoking Module Processing:
538  *      - This shall be invoked to determine maximum
539  *        number of UL RBs for scheduling.
540  *      - This is expected to be invoked every time
541  *        priority to attempt at UE allocation. Later
542  *        TPC retrieval depends on it.
543  *
544  *     Processing Steps:
545  *     - Returns maximum allowed UL RBs to be granted
546  *       after invoking Pusch power control.
547  *
548  *  @param[in]  RgSchCellCb  *cell
549  *  @param[in]  RgSchUeCb    *ue
550  *  @return  Void
551  **/
552 #ifdef ANSI
553 uint8_t rgSCHPwrGetMaxUlRb
554 (
555 RgSchCellCb *cell,
556 RgSchUeCb   *ue
557 )
558 #else
559 uint8_t rgSCHPwrGetMaxUlRb(cell, ue)
560 RgSchCellCb *cell;
561 RgSchUeCb   *ue;
562 #endif
563 {
564    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
565
566    rgSCHPwrPuschCntrl(cell, ue); /* This stores tpc, delta and maxRb
567                                   * in uePwr */
568    return (uePwr->maxUlRbs);
569 }
570
571 /**
572  * @brief Handles Pusch power control for DCI format 0
573  *
574  * @details
575  *
576  *     Function : rgSCHPwrPuschCntrl
577  *
578  *     Invoking Module Processing:
579  *      - This shall be invoked to determine TPC
580  *      and maximum number of UL RBs for scheduling
581  *      (through DCI format 0).
582  *
583  *     Processing Steps:
584  *     - 'remPuschPwr' is the final delta power that the UE
585  *       should apply to get to target CQI.
586  *     - The available headroom (availPwr) is determined.
587  *     - Power command is given by considering remPuschPwr and
588  *       availPwr.
589  *     - After factoring in the power command into availPwr, the
590  *       maximum number of RBs that can be supported is determined
591  *       assuming that UE is going to use transmission efficiency
592  *       corresponding to current CQI.
593  *     - The results determined in this function are stored
594  *       in the UE power control block.
595  *     - [Not doing anything of power control of msg3
596  *        retransmissions now]
597  *
598  *  @param[in]  RgSchCellCb  *cell
599  *  @param[in]  RgSchUeCb    *ue
600  *  @return  Void
601  **/
602 #ifdef ANSI
603 PRIVATE Void rgSCHPwrPuschCntrl
604 (
605 RgSchCellCb *cell,
606 RgSchUeCb   *ue
607 )
608 #else
609 PRIVATE Void rgSCHPwrPuschCntrl(cell, ue)
610 RgSchCellCb *cell;
611 RgSchUeCb   *ue;
612 #endif
613 {
614    RgSchCmnUlUe       *ueUl    = RG_SCH_CMN_GET_UL_UE(ue, cell);
615    RgSchCmnUeUlPwrCb  *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
616    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
617    S8                  delta;
618 #ifdef TFU_UPGRADE
619    uint8_t                  cqi     = ueUl->validUlCqi;
620    S32                 tmp;
621 #else
622    uint8_t                  cqi     = ueUl->crntUlCqi[0];
623 #endif
624    Bool                isAcc   = uePwr->isAccumulated;
625    uint8_t                  tpc;
626    S8                  availPwr;
627    uint8_t                  maxRb;
628
629    UNUSED(cell);
630
631    if (!uePwr->isPhrAvail)
632    {
633       availPwr = 60; /* setting a large value so that availPwr does
634                       * not constrain delta */
635    }
636    else
637    {
638       availPwr = uePwr->maxUePwr - uePwr->pwrPerRb;
639       availPwr -= rgSCHPwrGetCqiPwrForUe(cell, ue, cqi);
640    }
641    delta = uePwr->remPuschPwr;
642    rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, &tpc, &delta);
643    availPwr -= delta;
644
645    maxRb = rgSCHPwrGetMaxRb(cell,availPwr);
646
647    /* Store the results in ue power control block to be used later */
648    if(maxRb < cellUl->sbSize)
649    {
650        maxRb = cellUl->sbSize;
651 #ifdef TFU_UPGRADE
652        if(uePwr->maxPwrDeltaByPhr < 0)
653        {
654           tmp = ueUl->validUlCqi;
655           tmp = tmp + uePwr->maxPwrDeltaByPhr;
656           if (tmp < 1 )
657           {
658               ueUl->validUlCqi = 1;
659           }
660           else
661           {
662               ueUl->validUlCqi = tmp;
663           }
664        }
665 #endif
666    }
667    RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
668          "UEID:%d Output Max Rb (%d), phVal (%d) AvailPwr (%d) ",
669          ue->ueId, maxRb, uePwr->phVal, availPwr);
670    RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
671          "UEID:%d pwrPerRb %d remPuschPwr %d", 
672          ue->ueId,
673          uePwr->pwrPerRb,
674          uePwr->remPuschPwr);
675    uePwr->delta   = delta;
676    uePwr->maxUlRbs = maxRb;
677    uePwr->puschTpc = tpc;
678    return;
679 }
680
681 /**
682  * @brief Returns TPC to be sent in DL allocation
683  *
684  * @details
685  *
686  *     Function : rgSCHPwrPucchTpcForUe
687  *
688  *     Invoking Module Processing:
689  *      - After DL allocation for UE, this function shall
690  *        be invoked to obtain TPC.
691  *
692  *     Processing Steps:
693  *     - Do Pucch power control processing
694  *       and return TPC
695  *
696  *  @param[in]  RgSchCellCb  *cell
697  *  @param[in]  RgSchUeCb    *ue
698  *  @return  uint8_t
699  **/
700 #ifdef ANSI
701 uint8_t rgSCHPwrPucchTpcForUe
702 (
703 RgSchCellCb *cell,
704 RgSchUeCb   *ue
705 )
706 #else
707 uint8_t rgSCHPwrPucchTpcForUe(cell, ue)
708 RgSchCellCb *cell;
709 RgSchUeCb   *ue;
710 #endif
711 {
712    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
713
714    rgSCHPwrPucchCntrl(cell, ue);
715    return (uePwr->pucchTpc);
716 }
717
718 /***********************************************************
719  *
720  *     Func : rgSCHPwrGetDelta2FrmCqi
721  *
722  *     Desc : Get power to be applied to achieve
723  *            target CQI (the power returned is
724  *            twice is actual power)
725  *
726  *     Ret  : S8
727  *
728  *     Notes:
729  *
730  *     File :
731  *
732  **********************************************************/
733 #ifdef ANSI
734 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi
735 (
736 uint8_t                  crntCqi,
737 uint8_t                  trgCqi,
738 RgSchUeCb           *ue,
739 RgSchCellCb         *cell
740
741 )
742 #else
743 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi(crntCqi, trgCqi)
744 uint8_t                  crntCqi;
745 uint8_t                  trgCqi;
746 RgSchUeCb           *ue;
747 RgSchCellCb         *cell;
748 #endif
749 {
750    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
751  
752    if (uePwr->isPhrAvail)
753    {
754       //uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb - uePwr->remPuschPwr;
755       uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb;
756    }
757    else
758    {
759       uePwr->maxPwrDeltaByPhr = 0;         
760    }
761    
762    if (uePwr->maxPwrDeltaByPhr < 0 && (trgCqi - crntCqi) * 
763          RG_SCH_UL_CQI_DB_STEP_2 > 0)
764    {
765       return (0);
766    }
767    return (RGSCH_MIN(uePwr->maxPwrDeltaByPhr, 
768            (trgCqi - crntCqi) * RG_SCH_UL_CQI_DB_STEP_2));
769 }  /* rgSCHPwrGetDelta2FrmCqi */
770
771 /***********************************************************
772  *
773  *     Func : rgSCHPwrGetPuschTpc
774  *
775  *     Desc : Based on whether accumulation is enabled or
776  *            not, this returns an applicable power delta
777  *            to be applied based on the input delta.
778  *
779  *     Ret  : S8
780  *
781  *     Notes:
782  *
783  *     File :
784  *
785  **********************************************************/
786 #ifdef ANSI
787 PRIVATE Void rgSCHPwrGetPuschTpc
788 (
789 uint8_t                  isAcc,
790 S8                  delta,
791 S8                  availPwr,
792 uint8_t                 *tpc,
793 S8                 *tpcDelta
794 )
795 #else
796 PRIVATE Void rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, tpc, tpcDelta)
797 uint8_t                  isAcc;
798 S8                  delta;
799 S8                  availPwr;
800 uint8_t                 *tpc;
801 S8                 *tpcDelta;
802 #endif
803 {
804
805    delta = RGSCH_MIN(delta, availPwr);
806
807    /* As of now, the functions below possibly cause delta
808     * to be breached by 1 only. So calling these as is. */
809    if (isAcc)
810    {
811       rgSCHPwrGetAcc2bitTpc(delta, tpc, tpcDelta);
812    }
813    else
814    {
815       rgSCHPwrGetAbsTpc(delta, tpc, tpcDelta);
816    }
817    return;
818 }  /* rgSCHPwrGetPuschTpc */
819
820 /***********************************************************
821  *
822  *     Func : rgSCHPwrGetMaxRb
823  *
824  *     Desc : Get the maximum number of RBs that can be
825  *            expected to be supported by the passed
826  *            power headroom.
827  *
828  *     Ret  : uint8_t
829  *
830  *     Notes:
831  *
832  *     File :
833  *
834  **********************************************************/
835 #ifdef ANSI
836 PRIVATE uint8_t rgSCHPwrGetMaxRb
837 (
838 RgSchCellCb        *cell,
839 S8                  pwr
840 )
841 #else
842 PRIVATE uint8_t rgSCHPwrGetMaxRb(cell, pwr)
843 RgSchCellCb        *cell;
844 S8                  pwr;
845 #endif
846 {
847    RgSchCmnUlCell  *cellUl;
848
849    cellUl    = RG_SCH_CMN_GET_UL_CELL(cell);
850    if (pwr <= 0)
851    {
852       /* Give 4 RBS so that UE can report changed power status*/
853       /* [ccpu00119916] Mod -return 0th index of rgSchPwrToRbTbl when pwr <=0
854        *  Change the Macros from RGSCH_MAX_DL_BW to RGSCH_MAX_UL_BW*/
855       return (rgSchPwrToRbTbl[0]);
856    }
857    if (pwr > rgSchPwrRbToPwrTbl[cellUl->maxUlBwPerUe])
858    {
859       return (cellUl->maxUlBwPerUe);
860    }
861    return (RGSCH_MIN(cellUl->maxUlBwPerUe,rgSchPwrToRbTbl[(uint8_t)pwr]));
862 }  /* rgSCHPwrGetMaxRb */
863
864 /***********************************************************
865  *
866  *     Func : rgSCHPwrRbToPwr
867  *
868  *     Desc : Get the power corresponding to number of RBs
869  *
870  *     Ret  : uint8_t
871  *
872  *     Notes:
873  *
874  *     File :
875  *
876  **********************************************************/
877 #ifdef ANSI
878 PRIVATE uint8_t rgSCHPwrRbToPwr
879 (
880 RgSchCellCb          *cell,
881 uint8_t                  numRb
882 )
883 #else
884 PRIVATE uint8_t rgSCHPwrRbToPwr(cell,numRb)
885 RgSchCellCb          *cell;
886 uint8_t                  numRb;
887 #endif
888 {
889 #ifndef NO_ERRCLS
890    RgSchCmnUlCell  *cellUl;
891 #endif
892 #if (ERRCLASS & ERRCLS_DEBUG)
893    cellUl    = RG_SCH_CMN_GET_UL_CELL(cell);
894    if (numRb > cellUl->maxUlBwPerUe)
895    {
896       numRb = cellUl->maxUlBwPerUe;
897    }
898 #endif
899    return (rgSchPwrRbToPwrTbl[numRb]);
900 }  /* rgSCHPwrRbToPwr */
901
902
903 /**
904  * @brief Handles Pucch power control for DCI formats 1A/1B/1D/1/2A/2 
905  *
906  * @details
907  *
908  *     Function : rgSCHPwrPucchCntrl
909  *
910  *     Processing Steps:
911  *     - Determine 2 bit TPC to be sent using remPucchPwr.
912  *     - Update remPucchPwr appropriately
913  *
914  *  @param[in]  RgSchCellCb  *cell
915  *  @param[in]  RgSchUeCb    *ue
916  *  @return  Void
917  **/
918 #ifdef ANSI
919 PRIVATE Void rgSCHPwrPucchCntrl
920 (
921 RgSchCellCb *cell,
922 RgSchUeCb   *ue
923 )
924 #else
925 PRIVATE Void rgSCHPwrPucchCntrl(cell, ue)
926 RgSchCellCb *cell;
927 RgSchUeCb   *ue;
928 #endif
929 {
930    S8                     delta;
931    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
932
933    rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, &uePwr->pucchTpc, &delta);
934    rgSCHPwrOnSchedPucchTpc(cell, ue, delta);
935    return;
936 }
937
938 /**
939  * @brief Handles group power control for DCI formats 3/3A for Pucch and Pusch
940  *
941  * @details
942  *
943  *     Function : rgSCHPwrGrpCntrlPucch
944  *
945  *     Invoking Module Processing:
946  *      - This shall be invoked to do group power control for
947  *        all TPC RNTIs for which it is deemed necessary to
948  *        do the same (group power control).
949  *      - This function should only be invoked after all UEs
950  *        have been scheduled for uplink (re)transmissions
951  *        requiring DL DCI format in the passed subframe.
952  *
953  *     Processing Steps:
954  *     - For Pucch group power control
955  *       - For each TPC-Pucch-RNTI in the pucchGrpPwr List and 
956  *         TPC-Pusch-RNTI in the puschGrpPwr List,
957  *          - Request for PDCCH, skip if not available
958  *          - Form DCI format 3/3A information depending
959  *            on the format type of the TPC-RNTI and add it to the sub-frame.
960  *          - For each Ue in ueLst of TPC RNTI Cb
961  *             - if (fmtType == 3A)
962  *              - if((Ue not scheduled DL dci formats)
963  *                     && (remPwr >= 2 || remPwr <= -2))
964  *                  - Determine TPC. Set puschTpc/pucchTpc.
965  *                  - remPwr -= TPC
966  *                  - if (remPwr >= -1 && remPwr <= 1)
967  *                    - If already added, remove from toBeSchdLst
968  *              - else
969  *                  - Toggle the remainig power value
970  *             - else if (fmtType == 3)
971  *              - if((Ue not scheduled DL dci formats)
972  *                    && (remPwr))
973  *                  - Determine TPC. Set puschTpc/pucchTpc.
974  *                  - remPwr -= TPC
975  *                  - if (!remPwr)
976  *                    - If already added, remove from toBeSchdLst
977  *          - if (!toBeSchdUeCnt)
978  *             - Remove the tpcRntiCb frm pucchGrpPwr/puschGrpPwr List
979  *          - else, Move the tpcRntiCb to end of the list (not doing
980  *             this)
981  *
982  *  @param[in]  RgSchCellCb  *cell
983  *  @param[in]  RgSchDlSf    *dlSf
984  *  @return  Void
985  **/
986 #ifdef ANSI
987 Void rgSCHPwrGrpCntrlPucch
988 (
989 RgSchCellCb *cell,
990 RgSchDlSf   *dlSf
991 )
992 #else
993 Void rgSCHPwrGrpCntrlPucch(cell, dlSf)
994 RgSchCellCb *cell;
995 RgSchDlSf   *dlSf;
996 #endif
997 {
998    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
999    CmLListCp             *lst;
1000    CmLList               *lnk;
1001    RgSchPdcch            *pdcch;
1002
1003    lst = &cellPwr->pucchGrpPwr;
1004    lnk = lst->first;
1005    while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
1006    {
1007       RgSchCmnTpcRntiCb      *cb = (RgSchCmnTpcRntiCb *)lnk->node;
1008       Bool                    sched;
1009       lnk = lnk->next;
1010       rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, &sched);
1011       if (!sched)
1012       {
1013          rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
1014       }
1015       /* TPC RNTI would not have been removed if needs to
1016        * be scheduled again */
1017    }
1018
1019    return;
1020 }
1021
1022 /**
1023  * @brief Handles group power control for DCI formats 3/3A for Pusch and Pusch
1024  *
1025  * @details
1026  *
1027  *     Function : rgSCHPwrGrpCntrlPusch
1028  *
1029  *     Invoking Module Processing:
1030  *      - This shall be invoked to do group power control for
1031  *        all TPC RNTIs for which it is deemed necessary to
1032  *        do the same (group power control).
1033  *      - This function should only be invoked after all UEs
1034  *        have been scheduled for uplink (re)transmissions
1035  *        requiring DCI format 0 in the passed subframe.
1036  *
1037  *     Processing Steps:
1038  *     - For Pusch group power control
1039  *       - For each TPC-Pusch-RNTI in the puschGrpPwr List and 
1040  *          - Request for PDCCH, skip if not available
1041  *          - Form DCI format 3/3A information depending
1042  *            on the format type of the TPC-RNTI and add it to the sub-frame.
1043  *          - For each Ue in ueLst of TPC RNTI Cb
1044  *             - if (fmtType == 3A)
1045  *              - if (Ue not scheduled for dci format 0) and
1046  *                (remPwr >= 2 || remPwr <= -2))
1047  *                  - Determine TPC. Set puschTpc/puschTpc.
1048  *                  - remPwr -= TPC
1049  *                  - if (remPwr >= -1 && remPwr <= 1)
1050  *                    - If already added, remove from toBeSchdLst
1051  *              - else
1052  *                  - Toggle the remainig power value
1053  *             - else if (fmtType == 3)
1054  *              - if((Ue not scheduled for dci format 0) && (remPwr))
1055  *                  - Determine TPC. Set puschTpc.
1056  *                  - remPwr -= TPC
1057  *                  - if (!remPwr)
1058  *                    - If already added, remove from toBeSchdLst
1059  *          - if (!toBeSchdUeCnt)
1060  *             - Remove the tpcRntiCb frm puschGrpPwr/puschGrpPwr List
1061  *          - else, Move the tpcRntiCb to end of the list (not doing
1062  *            this now)
1063  *
1064  *  @param[in]  RgSchCellCb  *cell
1065  *  @param[in]  RgSchDlSf    *sf
1066  *  @return  Void
1067  **/
1068 #ifdef ANSI
1069 Void rgSCHPwrGrpCntrlPusch
1070 (
1071 RgSchCellCb *cell,
1072 RgSchDlSf   *dlSf,
1073 RgSchUlSf   *ulSf
1074 )
1075 #else
1076 Void rgSCHPwrGrpCntrlPusch(cell, dlSf, ulSf)
1077 RgSchCellCb *cell;
1078 RgSchDlSf   *dlSf;
1079 RgSchUlSf   *ulSf;
1080 #endif
1081 {
1082    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
1083    CmLListCp             *lst;
1084    CmLList               *lnk;
1085    RgSchPdcch            *pdcch;
1086
1087    lst = &cellPwr->puschGrpPwr;
1088    lnk = lst->first;
1089    while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
1090    {
1091       RgSchCmnTpcRntiCb      *cb = (RgSchCmnTpcRntiCb *)lnk->node;
1092       Bool                    sched;
1093       lnk = lnk->next;
1094       rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, &sched);
1095       if (!sched)
1096       {
1097          rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
1098       }
1099       /* TPC RNTI would not have been removed if needs to
1100        * be scheduled again */
1101    }
1102
1103    return;
1104 }
1105
1106 /***********************************************************
1107  *
1108  *     Func : rgSCHPwrSchedPucchRnti
1109  *
1110  *     Desc : Schedule TPC RNTI to be sent out
1111  *
1112  *     Ret  : Void
1113  *
1114  *     Notes:
1115  *
1116  *     File :
1117  *
1118  **********************************************************/
1119 #ifdef ANSI
1120 PRIVATE Void rgSCHPwrSchedPucchRnti
1121 (
1122 RgSchCellCb          *cell,
1123 RgSchCmnTpcRntiCb    *cb,
1124 RgSchPdcch           *pdcch,
1125 RgSchDlSf            *dlSf,
1126 Bool                 *sched
1127 )
1128 #else
1129 PRIVATE Void rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, sched)
1130 RgSchCellCb          *cell;
1131 RgSchCmnTpcRntiCb    *cb;
1132 RgSchPdcch           *pdcch;
1133 RgSchDlSf            *dlSf;
1134 Bool                 *sched;
1135 #endif
1136 {
1137    CmLListCp         *lst;
1138    CmLList           *lnk;
1139    uint8_t                *tpcCmds;
1140    uint8_t                 tpc;
1141    S8                 delta;
1142    Bool               atleastOne;
1143
1144    pdcch->rnti = cb->tpcRnti;
1145
1146    if (cb->isFmt3a)
1147    {
1148       /* Go through all UEs for format 3A case */
1149       lst = &cb->cfgdUes;
1150       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1151       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1152       pdcch->dci.u.format3AInfo.isPucch = TRUE;
1153
1154       tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1155       /* No need to memset zero initially as every TPC is going
1156        * to be filled up for every configured UE */
1157       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1158       {
1159          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1160          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1161
1162          if ( ue->isDrxEnabled == TRUE && 
1163                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1164          {
1165             /* UE is in its DRX time. So we cannot give command
1166              * to this UE.
1167              */
1168             continue;
1169          }
1170
1171          if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1172          {
1173             /* UE already scheduled in downlink with PDCCH
1174              * carrying PUCCH pwr cmd. So don't care about
1175              * giving command to this UE. */
1176             continue;
1177          }
1178          rgSCHPwrGetPucchFmt3aTpcForUe(ue, &tpc, &delta);
1179          tpcCmds[uePwr->pucchIdx] = tpc;
1180          atleastOne = TRUE;
1181          rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1182       }
1183    }
1184    else
1185    {
1186       /* Go through to-be-scheduled UEs for format 3 case */
1187       lst = &cb->toBeSchdUes;
1188       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1189       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1190       tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1191       pdcch->dci.u.format3Info.isPucch = TRUE;
1192
1193       /* Fill TPC 1 (corresponding to no power change) initially */
1194       memset(tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1195
1196       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1197       {
1198          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1199          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1200
1201          if ( ue->isDrxEnabled == TRUE && 
1202                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1203          {
1204             /* UE is in its DRX time. So we cannot give command
1205              * to this UE.
1206              */
1207             continue;
1208          }
1209
1210          if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1211          {
1212             /* UE already scheduled in downlink with PDCCH
1213              * carrying PUCCH pwr cmd. So don't care about
1214              * giving command to this UE. */
1215             continue;
1216          }
1217          rgSCHPwrGetPucchFmt3TpcForUe(ue, &tpc, &delta);
1218          tpcCmds[uePwr->pucchIdx] = tpc;
1219          atleastOne = TRUE;
1220          rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1221       }
1222    }
1223
1224    *sched = atleastOne;
1225
1226    /* Check if no more UEs in TPC RNTI, and then remove
1227     * this TPC RNTI from scheduled list */
1228     if (cb->toBeSchdUes.count == 0)
1229     {
1230        rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
1231     }
1232
1233    return;
1234 }  /* rgSCHPwrSchedPucchRnti */
1235
1236 /***********************************************************
1237  *
1238  *     Func : rgSCHPwrSchedPuschRnti
1239  *
1240  *     Desc : Schedule TPC RNTI to be sent out
1241  *
1242  *     Ret  : Void
1243  *
1244  *     Notes:
1245  *
1246  *     File :
1247  *
1248  **********************************************************/
1249 #ifdef ANSI
1250 PRIVATE Void rgSCHPwrSchedPuschRnti
1251 (
1252 RgSchCellCb          *cell,
1253 RgSchCmnTpcRntiCb    *cb,
1254 RgSchPdcch           *pdcch,
1255 RgSchUlSf            *ulSf,
1256 Bool                 *sched
1257 )
1258 #else
1259 PRIVATE Void rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, sched)
1260 RgSchCellCb          *cell;
1261 RgSchCmnTpcRntiCb    *cb;
1262 RgSchPdcch           *pdcch;
1263 RgSchUlSf            *ulSf;
1264 Bool                 *sched;
1265 #endif
1266 {
1267    CmLListCp         *lst;
1268    CmLList           *lnk;
1269    uint8_t                *tpcCmds;
1270    uint8_t                 tpc;
1271    S8                 delta;
1272    Bool               atleastOne;
1273
1274    pdcch->rnti = cb->tpcRnti;
1275
1276    if (cb->isFmt3a)
1277    {
1278       /* Go through all UEs for format 3A case */
1279       lst = &cb->cfgdUes;
1280       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1281       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1282       pdcch->dci.u.format3AInfo.isPucch = FALSE;
1283       tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1284       /* No need to memset zero initially as every TPC is going
1285        * to be filled up for every configured UE */
1286       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1287       {
1288          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1289          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1290          if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1291          {
1292             /* UE already scheduled in uplink with DCI
1293              * format 0. So don't care about giving
1294              * command to this UE. */
1295             continue;
1296          }
1297
1298          if ( ue->isDrxEnabled == TRUE && 
1299                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1300          {
1301             /* UE is in its DRX time. So we cannot give command
1302              * to this UE.
1303              */
1304             continue;
1305          }
1306
1307          rgSCHPwrGetPuschFmt3aTpcForUe(ue, &tpc, &delta);
1308          tpcCmds[uePwr->puschIdx] = tpc;
1309          atleastOne = TRUE;
1310          rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1311       }
1312    }
1313    else
1314    {
1315       /* Go through to-be-scheduled UEs for format 3 case */
1316       lst = &cb->toBeSchdUes;
1317       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1318       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1319       pdcch->dci.u.format3Info.isPucch = FALSE;
1320       tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1321
1322       /* Fill TPC 1 (corresponding to no power change) initially */
1323       memset(tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1324
1325       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1326       {
1327          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1328          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1329          if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1330          {
1331             /* UE already scheduled in uplink with DCI
1332              * format 0. So don't care about giving
1333              * command to this UE. */
1334             continue;
1335          }
1336
1337          if ( ue->isDrxEnabled == TRUE && 
1338                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1339          {
1340             /* UE is in its DRX time. So we cannot give command
1341              * to this UE.
1342              */
1343             continue;
1344          }
1345
1346          rgSCHPwrGetPuschFmt3TpcForUe(ue, &tpc, &delta);
1347          tpcCmds[uePwr->puschIdx] = tpc;
1348          atleastOne = TRUE;
1349          rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1350       }
1351    }
1352
1353    *sched = atleastOne;
1354
1355    /* Check if no more UEs in TPC RNTI, and then remove
1356     * this TPC RNTI from scheduled list */
1357     if (cb->toBeSchdUes.count == 0)
1358     {
1359        rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
1360     }
1361
1362    return;
1363 }  /* rgSCHPwrSchedPuschRnti */
1364
1365 /***********************************************************
1366  *
1367  *     Func : rgSCHPwrGetPucchFmt3TpcForUe
1368  *
1369  *     Desc : Gets 2 bit TPC cmd for PUCCH
1370  *
1371  *     Ret  : Void
1372  *
1373  *     Notes:
1374  *
1375  *     File :
1376  *
1377  **********************************************************/
1378 #ifdef ANSI
1379 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe
1380 (
1381 RgSchUeCb            *ue,
1382 uint8_t                   *tpc,
1383 S8                   *delta
1384 )
1385 #else
1386 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe(ue, tpc, delta)
1387 RgSchUeCb            *ue;
1388 uint8_t                   *tpc;
1389 S8                   *delta;
1390 #endif
1391 {
1392    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1393
1394    rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, tpc, delta);
1395    return;
1396 }  /* rgSCHPwrGetPucchFmt3TpcForUe */
1397
1398 /***********************************************************
1399  *
1400  *     Func : rgSCHPwrGetPucchFmt3aTpcForUe
1401  *
1402  *     Desc : Gets 1 bit TPC cmd for PUCCH
1403  *
1404  *     Ret  : Void
1405  *
1406  *     Notes:
1407  *
1408  *     File :
1409  *
1410  **********************************************************/
1411 #ifdef ANSI
1412 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe
1413 (
1414 RgSchUeCb            *ue,
1415 uint8_t                   *tpc,
1416 S8                   *delta
1417 )
1418 #else
1419 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe(ue, tpc, delta)
1420 RgSchUeCb            *ue;
1421 uint8_t                   *tpc;
1422 S8                   *delta;
1423 #endif
1424 {
1425    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1426
1427    rgSCHPwrGetAcc1bitTpc(uePwr->remPucchPwr, tpc, delta);
1428    return;
1429 }  /* rgSCHPwrGetPucchFmt3aTpcForUe */
1430
1431 /***********************************************************
1432  *
1433  *     Func : rgSCHPwrGetPuschFmt3TpcForUe
1434  *
1435  *     Desc : Gets 2 bit TPC cmd for PUCCH
1436  *
1437  *     Ret  : Void
1438  *
1439  *     Notes:
1440  *
1441  *     File :
1442  *
1443  **********************************************************/
1444 #ifdef ANSI
1445 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe
1446 (
1447 RgSchUeCb            *ue,
1448 uint8_t                   *tpc,
1449 S8                   *delta
1450 )
1451 #else
1452 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe(ue, tpc, delta)
1453 RgSchUeCb            *ue;
1454 uint8_t                   *tpc;
1455 S8                   *delta;
1456 #endif
1457 {
1458    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1459    S8                     adj = RGSCH_MIN(uePwr->remPuschPwr, uePwr->phVal);
1460
1461    rgSCHPwrGetAcc2bitTpc(adj, tpc, delta);
1462    return;
1463 }  /* rgSCHPwrGetPuschFmt3TpcForUe */
1464
1465 /***********************************************************
1466  *
1467  *     Func : rgSCHPwrGetPuschFmt3aTpcForUe
1468  *
1469  *     Desc : Gets 1 bit TPC cmd for PUCCH
1470  *
1471  *     Ret  : Void
1472  *
1473  *     Notes:
1474  *
1475  *     File :
1476  *
1477  **********************************************************/
1478 #ifdef ANSI
1479 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe
1480 (
1481 RgSchUeCb            *ue,
1482 uint8_t                   *tpc,
1483 S8                   *delta
1484 )
1485 #else
1486 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe(ue, tpc, delta)
1487 RgSchUeCb            *ue;
1488 uint8_t                   *tpc;
1489 S8                   *delta;
1490 #endif
1491 {
1492    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1493
1494    /* Don't attempt to look at headroom now, power
1495     * adjustment is small anyway */
1496    rgSCHPwrGetAcc1bitTpc(uePwr->remPuschPwr, tpc, delta);
1497    return;
1498 }  /* rgSCHPwrGetPuschFmt3aTpcForUe */
1499
1500 /***********************************************************
1501  *
1502  *     Func : rgSCHPwrGetAcc1bitTpc
1503  *
1504  *     Desc : Gets 1 bit TPC cmd
1505  *
1506  *     Ret  : Void
1507  *
1508  *     Notes:
1509  *
1510  *     File :
1511  *
1512  **********************************************************/
1513 #ifdef ANSI
1514 PRIVATE Void rgSCHPwrGetAcc1bitTpc
1515 (
1516 S8                    remPwr,
1517 uint8_t                   *tpc,
1518 S8                   *delta
1519 )
1520 #else
1521 PRIVATE Void rgSCHPwrGetAcc1bitTpc(remPwr, tpc, delta)
1522 S8                    remPwr;
1523 uint8_t                   *tpc;
1524 S8                   *delta;
1525 #endif
1526 {
1527    /*
1528     * TPC   delta
1529     *  0     -1
1530     *  1      1
1531     */
1532    if (remPwr <= 0)
1533    {
1534       *delta = -1;
1535       *tpc = 0;
1536    }
1537    else
1538    {
1539       *delta = 1;
1540       *tpc = 1;
1541    }
1542    return;
1543 }  /* rgSCHPwrGetAcc1bitTpc */
1544
1545 /***********************************************************
1546  *
1547  *     Func : rgSCHPwrGetAcc2bitTpc
1548  *
1549  *     Desc : Allocate PDCCH for group power control
1550  *
1551  *     Ret  : Void
1552  *
1553  *     Notes:
1554  *
1555  *     File :
1556  *
1557  **********************************************************/
1558 #ifdef ANSI
1559 PRIVATE Void rgSCHPwrGetAcc2bitTpc
1560 (
1561 S8                   remPwr,
1562 uint8_t                  *tpc,
1563 S8                  *delta
1564 )
1565 #else
1566 PRIVATE Void rgSCHPwrGetAcc2bitTpc(remPwr, tpc, delta)
1567 S8                   remPwr;
1568 uint8_t                  *tpc;
1569 S8                  *delta;
1570 #endif
1571 {
1572    /*
1573     * TPC   delta
1574     *  0     -1
1575     *  1      0
1576     *  2      1
1577     *  3      3
1578     */
1579    uint8_t            tpcs[3]   = {1, 2, 2};
1580    uint8_t            deltas[3] = {0, 1, 1};
1581    if (remPwr <= -1)
1582    {
1583       *tpc   = 0;
1584       *delta = -1;
1585    }
1586    else if (remPwr >= 3)
1587    {
1588       *tpc   = 3;
1589       *delta = 3;
1590    }
1591    else
1592    {
1593       *tpc   = tpcs[(uint8_t)remPwr];
1594       *delta = deltas[(uint8_t)remPwr];
1595    }
1596    return;
1597 }  /* rgSCHPwrGetAcc2bitTpc */
1598
1599 /***********************************************************
1600  *
1601  *     Func : rgSCHPwrGetAbsTpc
1602  *
1603  *     Desc : Allocate PDCCH for group power control
1604  *
1605  *     Ret  : Void
1606  *
1607  *     Notes:
1608  *
1609  *     File :
1610  *
1611  **********************************************************/
1612 #ifdef ANSI
1613 PRIVATE Void rgSCHPwrGetAbsTpc
1614 (
1615 S8                   remPwr,
1616 uint8_t                  *tpc,
1617 S8                  *delta
1618 )
1619 #else
1620 PRIVATE Void rgSCHPwrGetAbsTpc(remPwr, tpc, delta)
1621 S8                   remPwr;
1622 uint8_t                  *tpc;
1623 S8                  *delta;
1624 #endif
1625 {
1626    /*
1627     * TPC   delta
1628     *  0     -4
1629     *  1     -1
1630     *  2      1
1631     *  3      4
1632     */
1633    if (remPwr <= -3)
1634    {
1635       *tpc = 0;
1636       *delta = -4;
1637    }
1638    else if (remPwr < 1)
1639    {
1640       *tpc = 1;
1641       *delta = -1;
1642    }
1643    else if (remPwr < 4)
1644    {
1645       *tpc = 2;
1646       *delta = 1;
1647    }
1648    else
1649    {
1650       *tpc = 3;
1651       *delta = 4;
1652    }
1653    return;
1654 }  /* rgSCHPwrGetAbsTpc */
1655
1656 /***********************************************************
1657  *
1658  *     Func : rgSCHPwrOnPucchGrpPwrForUe
1659  *
1660  *     Desc : Processing on sending TPC for UE through group power
1661  *            control. Apart from updating remPwr, this only takes
1662  *            care of possibly removing UE from scheduled
1663  *            list in TPC RNTI.
1664  *            It does not take care of possibly removing TPC RNTI
1665  *            from scheduled list in cell. This is done
1666  *            in the caller after TPC for all UEs has been
1667  *            determined. (This is where it differs
1668  *            from the usual OnSendingPu[cs]ch TPC]
1669  *
1670  *     Ret  : ROK/RFAILED
1671  *
1672  *     Notes:
1673  *
1674  *     File :
1675  *
1676  **********************************************************/
1677 #ifdef ANSI
1678 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe 
1679 (
1680 RgSchCellCb          *cell,
1681 RgSchUeCb            *ue,
1682 S8                    delta
1683 )
1684 #else
1685 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta)
1686 RgSchCellCb          *cell;
1687 RgSchUeCb            *ue;
1688 S8                    delta;
1689 #endif
1690 {
1691    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1692    Bool                   rmvUe = FALSE;
1693
1694    UNUSED(cell);
1695
1696    uePwr->remPucchPwr -= delta;
1697
1698    /* UE was already scheduled for PUCCH group power
1699     * control which is why we came here. Don't
1700     * again check for this. */
1701
1702    /* UE was scheduled for pucch grp pwr, sent TPC may
1703     * possibly cause it to be removed. */
1704       if (!uePwr->remPucchPwr)
1705       {
1706          rmvUe = TRUE;
1707       }
1708    if (rmvUe)
1709    {
1710       rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
1711       /* Not removing TPC RNTI from scheduled list,
1712        * this will happen in the caller once this
1713        * function is called for every UE scheduled. */
1714    }
1715    return;
1716 }
1717
1718 /***********************************************************
1719  *
1720  *     Func : rgSCHPwrOnPuschGrpPwrForUe
1721  *
1722  *     Desc : Processing on sending TPC for UE through group power
1723  *            control. Apart from updating remPwr, this only takes
1724  *            care of possibly removing UE from scheduled
1725  *            list in TPC RNTI.
1726  *            It does not take care of possibly removing TPC RNTI
1727  *            from scheduled list in cell. This is done
1728  *            in the caller after TPC for all UEs has been
1729  *            determined. (This is where it differs
1730  *            from the usual OnSendingPu[cs]ch TPC]
1731  *
1732  *     Ret  : ROK/RFAILED
1733  *
1734  *     Notes:
1735  *
1736  *     File :
1737  *
1738  **********************************************************/
1739 #ifdef ANSI
1740 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe 
1741 (
1742 RgSchCellCb          *cell,
1743 RgSchUeCb            *ue,
1744 S8                    delta
1745 )
1746 #else
1747 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta)
1748 RgSchCellCb          *cell;
1749 RgSchUeCb            *ue;
1750 S8                    delta;
1751 #endif
1752 {
1753    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1754    Bool                   rmvUe = FALSE;
1755
1756    UNUSED(cell);
1757
1758    uePwr->delta = delta;
1759    uePwr->remPuschPwr -= delta;
1760    if (uePwr->isPhrAvail)
1761    {
1762       uePwr->phVal -= uePwr->delta;
1763       uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
1764    }
1765
1766    /* UE was already scheduled for PUSCH group power
1767     * control which is why we came here. Don't
1768     * again check for this. */
1769
1770    /* UE was scheduled for pusch grp pwr, sent TPC may
1771     * possibly cause it to be removed. */
1772
1773       if (!uePwr->remPuschPwr)
1774       {
1775          rmvUe = TRUE;
1776       }
1777
1778    if (rmvUe)
1779    {
1780       rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
1781       /* Not removing TPC RNTI from scheduled list,
1782        * this will happen in the caller once this
1783        * function is called for every UE scheduled. */
1784    }
1785    return;
1786 }
1787
1788 /***********************************************************
1789  *
1790  *     Func : rgSCHPwrIsDlUeSched
1791  *
1792  *     Desc : Check if UE is scheduled in the passed DL SF
1793  *
1794  *     Ret  : Void
1795  *
1796  *     Notes:
1797  *
1798  *     File :
1799  *
1800  **********************************************************/
1801 #ifdef ANSI
1802 PRIVATE Bool rgSCHPwrIsDlUeSched
1803 (
1804 RgSchCellCb            *cell,
1805 RgSchUeCb            *ue,
1806 RgSchDlSf            *sf
1807 )
1808 #else
1809 PRIVATE Bool rgSCHPwrIsDlUeSched(cell, ue, sf)
1810 RgSchCellCb            *cell;
1811 RgSchUeCb            *ue;
1812 RgSchDlSf            *sf;
1813 #endif
1814 {
1815    RgSchDlHqEnt          *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1816    RgSchDlHqProcCb      *proc    = rgSCHDhmLastSchedHqProc(hqEnt);
1817
1818    if (proc == NULLP)
1819    {
1820       return (FALSE);
1821    }
1822
1823    /*
1824     * The following subframe check is assumed enough, since
1825     * scheduled procs stay for a short time (until feedback
1826     * arrives), which typically is expected to have a
1827     * turnaround time of less than 8 subframes. So
1828     * we are probably never going to come across cases
1829     * where a process stays in the list for more than
1830     * 10 subframes, which would have otherwise caused
1831     * the check to succeed for a possibly older process.
1832     */
1833    if ((proc->tbInfo[0].timingInfo.slot == sf->sfNum) ||
1834        (proc->tbInfo[1].timingInfo.slot == sf->sfNum))
1835    {
1836       /*
1837        * Later, if a proc can be scheduled without having an
1838        * associated PDCCH, need to also check if PDCCH exists.
1839        * This is because for power, what matters is whether
1840        * TPC is going out for UE at this time or not, at least
1841        * that is what this function was introduced for.
1842        * Checking for PDCCH would have to be in common proc
1843        * the way things are now.
1844        */
1845       return (TRUE);
1846    }
1847    else
1848    {
1849       return (FALSE);
1850    }
1851 }  /* rgSCHPwrIsDlUeSched */
1852
1853 /***********************************************************
1854  *
1855  *     Func : rgSCHPwrIsUlUeSched
1856  *
1857  *     Desc : Check if UE is scheduled in the passed UL SF
1858  *
1859  *     Ret  : Void
1860  *
1861  *     Notes:
1862  *
1863  *     File :
1864  *
1865  **********************************************************/
1866 #ifdef ANSI
1867 PRIVATE Bool rgSCHPwrIsUlUeSched
1868 (
1869 RgSchCellCb          *cell,
1870 RgSchUeCb            *ue,
1871 RgSchUlSf            *sf
1872 )
1873 #else
1874 PRIVATE Bool rgSCHPwrIsUlUeSched(cell, ue, sf)
1875 RgSchCellCb          *cell;
1876 RgSchUeCb            *ue;
1877 RgSchUlSf            *sf;
1878 #endif
1879 {
1880    RgSchCmnUlCell      *cmnCell = RG_SCH_CMN_GET_UL_CELL(cell);
1881    RgSchUlHqProcCb     *proc = rgSCHUhmGetUlHqProc(cell, ue, cmnCell->schdHqProcIdx);
1882
1883    UNUSED(sf);
1884
1885 #if (ERRCLASS & ERRCLS_DEBUG)
1886    if( proc == NULLP )
1887    {
1888       return  (FALSE);
1889    }
1890 #endif  
1891
1892    if (proc->alloc)
1893    {
1894       return (TRUE);
1895    }
1896    else
1897    {
1898       return (FALSE);
1899    }
1900 }  /* rgSCHPwrIsUlUeSched */
1901
1902 /**
1903  * @brief Handles Pucch power delta indication recieved from PHY
1904  *
1905  * @details
1906  *
1907  *     Function : rgSCHPwrPucchDeltaInd
1908  *
1909  *     Invoking Module Processing:
1910  *      - This shall be invoked on reception of Pucch power 
1911  *        delta indication from PHY.
1912  *        
1913  *     Processing Steps:
1914  *     - Update the remPucchPwr 
1915  *       ue->remPucchPwr = pwrDelta
1916  *     - If (ue->tpcPucchRntiCb)
1917  *       - If (fmtType = 3A)
1918  *          - if (remPucchPwr >= 2 || remPucchPwr <= -2 )
1919  *             - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1920  *               - Add tpcPucchRntiCb to the pucchGrpPwr list.
1921  *             - If not added, add to toBeSchdLst
1922  *          - else
1923  *             - If already added, remove from toBeSchdLst
1924  *       - else If (fmtType == 3) 
1925  *          - if (remPucchPwr)
1926  *             - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1927  *               - Add tpcPucchRntiCb to the pucchGrpPwr list.
1928  *             - If not added, add to toBeSchdLst
1929  *          - else
1930  *             - If already added, remove from toBeSchdLst
1931  *
1932  *  @param[in]  RgSchCellCb  *cell
1933  *  @param[in]  RgSchUeCb    *ue
1934  *  @param[in]  uint8_t           pwrDelta
1935  *  @return  Void
1936  **/
1937 #ifdef ANSI
1938 Void rgSCHPwrPucchDeltaInd
1939 (
1940 RgSchCellCb *cell,
1941 RgSchUeCb   *ue,
1942 S8          pwrDelta
1943 )
1944 #else
1945 Void rgSCHPwrPucchDeltaInd(cell, ue, pwrDelta)
1946 RgSchCellCb *cell;
1947 RgSchUeCb   *ue;
1948 S8          pwrDelta;
1949 #endif
1950 {
1951    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1952    RgSchCmnTpcRntiCb     *cb;
1953    Bool                   toAdd;
1954
1955    uePwr->remPucchPwr = pwrDelta;
1956    
1957    if ((cb = uePwr->tpcPucchRntiCb) == NULLP)
1958    {
1959       return;
1960    }
1961
1962    toAdd = FALSE;
1963
1964    if (0 != uePwr->remPucchPwr)
1965       {
1966          toAdd = TRUE;
1967       }
1968
1969
1970    if (toAdd)
1971    {
1972       rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue);
1973    }
1974    else
1975    {
1976       rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
1977    }
1978
1979    return;
1980 }
1981
1982 /**
1983  * @brief Does processing after TPC for Pucch has been sent
1984  *
1985  * @details
1986  *
1987  *     Function : rgSCHPwrOnSchedPucchTpc
1988  *
1989  *     Invoking Module Processing:
1990  *      - It shall be invoked after it is determined that PDCCH for UE
1991  *        is finalised to go out, and thus TPC for PUCCH is being
1992  *        sent out.
1993  *
1994  *     Processing Steps:
1995  *     - Update remPucchPwr with the delta
1996  *     - Do group power control related processing
1997  *
1998  *  @param[in]  RgSchCellCb       *cell
1999  *  @param[in]  RgSchUeCb         *ue
2000  *  @param[in]  S8                 delta
2001  *  @return  Void
2002  **/
2003 #ifdef ANSI
2004 PRIVATE Void rgSCHPwrOnSchedPucchTpc
2005 (
2006 RgSchCellCb           *cell,
2007 RgSchUeCb             *ue,
2008 S8                     delta
2009 )
2010 #else
2011 PRIVATE Void rgSCHPwrOnSchedPucchTpc(cell, ue, delta)
2012 RgSchCellCb           *cell;
2013 RgSchUeCb             *ue;
2014 S8                     delta;
2015 #endif
2016 {
2017    /* Similar to rgSCHPwrPucchDeltaInd.. not reusing
2018     * that since we use the fact that UE could only have
2019     * improved its remPwr as part of power control. */
2020    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2021    Bool                   rmvUe = FALSE;
2022
2023    uePwr->remPucchPwr -= delta;
2024
2025    if (uePwr->schdPucchGrpLnk.node == NULLP)
2026    {
2027       return;
2028    }
2029
2030    /* UE was scheduled for TPC, sent TPC may
2031     * possibly cause it to be removed. */
2032
2033       if (!uePwr->remPucchPwr)
2034       {
2035          rmvUe = TRUE;
2036       }
2037
2038    if (rmvUe)
2039    {
2040       rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2041       if (uePwr->tpcPucchRntiCb->toBeSchdUes.count == 0)
2042       {
2043          rgSCHPwrRmvSchdPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb);
2044       }
2045    }
2046    return;
2047 }
2048
2049
2050 /**
2051  * @brief Does processing after TPC for Pusch has been sent
2052  *
2053  * @details
2054  *
2055  *     Function : rgSCHPwrOnSchedPuschTpc
2056  *
2057  *     Processing Steps:
2058  *      - If accumulative
2059  *        - Update remPuschPwr with the delta
2060  *        - Do group power related processing if applicable
2061  *       
2062  *  @param[in]  RgSchCellCb       *cell
2063  *  @param[in]  RgSchUeCb         *ue
2064  *  @return  Void
2065  **/
2066 #ifdef ANSI
2067 PRIVATE Void rgSCHPwrOnSchedPuschTpc
2068 (
2069 RgSchCellCb           *cell,
2070 RgSchUeCb             *ue
2071 )
2072 #else
2073 PRIVATE Void rgSCHPwrOnSchedPuschTpc(cell, ue)
2074 RgSchCellCb           *cell;
2075 RgSchUeCb             *ue;
2076 #endif
2077 {
2078    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2079    Bool                   rmvUe = FALSE;
2080
2081    /* Don't do anything for the case of absolute TPC commands */
2082    if (!uePwr->isAccumulated)
2083    {
2084       return;
2085    }
2086
2087    uePwr->remPuschPwr -= uePwr->delta;
2088    if (uePwr->isPhrAvail)
2089    {
2090       uePwr->phVal -= uePwr->delta;
2091       uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
2092    }
2093
2094    if (uePwr->schdPuschGrpLnk.node == NULLP)
2095    {
2096       return;
2097    }
2098
2099    /* UE was scheduled for pusch TPC, sent TPC may
2100     * possibly cause it to be removed. */
2101
2102       if (!uePwr->remPuschPwr)
2103       {
2104          rmvUe = TRUE;
2105       }
2106
2107    if (rmvUe)
2108    {
2109       rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2110    }
2111
2112    return;
2113 }
2114
2115 /**
2116  * @brief Handles PHR updation for the UE
2117  *
2118  * @details
2119  *
2120  *     Function : rgSCHPwrUpdExtPhr
2121  *  @param[in]  RgSchCellCb         *cell
2122  *  @param[in]  RgSchUeCb           *ue
2123  *  @param[in]  RgInfExtPhrCEInfo   *extPhr
2124  *  @param[in]  RgSchCmnAllocRecord  allocInfo
2125  *  @return  Void
2126  **/
2127 #ifdef ANSI
2128 Void rgSCHPwrUpdExtPhr
2129 (
2130 RgSchCellCb           *cell,
2131 RgSchUeCb             *ue,
2132 RgInfExtPhrCEInfo     *extPhr,
2133 RgSchCmnAllocRecord   *allocInfo
2134 )
2135 #else
2136 Void rgSCHPwrUpdExtPhr(cell, ue, extPhr, allocInfo)
2137 RgSchCellCb           *cell;
2138 RgSchUeCb             *ue;
2139 RgInfExtPhrCEInfo     *extPhr;
2140 RgSchCmnAllocRecord   *allocInfo;
2141 #endif
2142 {
2143    uint8_t idx;
2144    RgInfExtPhrSCellInfo  *servCellPhr;
2145    S8                     pCMax;
2146
2147    for (idx = 0; idx < extPhr->numServCells; idx++)
2148    {
2149       servCellPhr = &extPhr->servCellPhr[idx];
2150
2151       if (RG_SCH_REF_PCMAX == servCellPhr->pCmax)
2152       {
2153          pCMax = RG_SCH_CMN_PWR_USE_CFG_MAX_PWR;
2154       }
2155       else
2156       {
2157          pCMax = rgSCHPwrGetPCMaxValFromPCMax(servCellPhr->pCmax);
2158       }
2159       rgSCHPwrUpdPhr(ue->cellInfo[servCellPhr->sCellIdx]->cell,
2160             ue, servCellPhr->phr, allocInfo, pCMax);
2161    }
2162    return;
2163 }
2164
2165 /**
2166  * @brief Handles PHR updation for the UE
2167  *
2168  * @details
2169  *
2170  *     Function : rgSCHPwrUpdPhr
2171  *
2172  *     Invoking Module Processing:
2173  *      - This shall be invoked on reception of PHR from MAC to SCH. It shall
2174  *      pass the information of number of RBs, coding efficiency and TPC for 
2175  *      the Pusch transmission for which PHR has been reported.
2176  *
2177  *     Processing Steps:
2178  *     - Compute power per RB using the PHR report
2179  *        - ue_transmit_pwr = ue_max_pwr - PHR
2180  *        - if isDeltaMcs = TRUE
2181  *          - ue_transmit_pwr - 
2182  *            [10log(phr_num_rb) + 10log(2^ (1.25 * phr_coding_effeciency) -1)
2183  *            + phr_tpc(if absolute TPC)] = pwrPerRB
2184  *        - else
2185  *          - ue_transmit_pwr - [10log(phr_num_rb) + phr_tpc(if absolute TPC)]
2186  *            = pwrPerRB
2187  *        (Use the number of RBs and efficiency used by UE which caused the PHR
2188  *         report to happen)
2189  *     - Adjust PHR according to last allocation (take into account
2190  *       number of RBs granted in the last allocation)
2191  *     - Update the PHR report in the control block
2192  *     - Set isPhrAvail = TRUE
2193  *     - Do group power control related processing if applicable
2194  *
2195  *  @param[in]  RgSchCellCb         *cell
2196  *  @param[in]  RgSchUeCb           *ue
2197  *  @param[in]  uint8_t                   phr
2198  *  @param[in]  RgSchCmnAllocRecord  allocInfo
2199  *  @param[in]  uint8_t                   maxUePwr
2200  *  @return  Void
2201  **/
2202 #ifdef ANSI
2203 Void rgSCHPwrUpdPhr
2204 (
2205 RgSchCellCb           *cell,
2206 RgSchUeCb             *ue,
2207 uint8_t                     phr,
2208 RgSchCmnAllocRecord   *allocInfo,
2209 S8                     maxUePwr 
2210 )
2211 #else
2212 Void rgSCHPwrUpdPhr(cell, ue, phr, allocInfo, maxUePwr)
2213 RgSchCellCb           *cell;
2214 RgSchUeCb             *ue;
2215 uint8_t                     phr;
2216 RgSchCmnAllocRecord   *allocInfo;
2217 S8                     maxUePwr;
2218 #endif
2219 {
2220    RgSchCmnUeUlPwrCb     *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
2221    uint8_t                     rbPwr;
2222    uint8_t                     effPwr;
2223    RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2224
2225    uePwr->phVal = rgSCHPwrGetPhValFromPhr(phr);
2226   
2227    if (maxUePwr == RG_SCH_CMN_PWR_USE_CFG_MAX_PWR)
2228    {
2229       maxUePwr = uePwr->maxUePwr;
2230    }
2231    rbPwr = rgSCHPwrRbToPwr(cell,allocInfo->numRb);
2232    effPwr = rgSCHPwrGetCqiPwrForUe(cell, ue, allocInfo->cqi);
2233    uePwr->pwrPerRb = maxUePwr - uePwr->phVal - rbPwr - effPwr;
2234    /*if (!uePwr->isAccumulated)
2235    {
2236       uePwr->pwrPerRb -= rgSCHPwrGetDeltaFrmAbsTpc(allocInfo->tpc);
2237    }*/
2238
2239    /* Let headroom reflect remaining power according to last
2240     * allocated number of RBs. Intermediate TPCs not yet
2241     * taken care of (for accumulated case, it is anyway
2242     * not applicable for absolute commands). */
2243    uePwr->phVal -= (rgSCHPwrRbToPwr(cell, cellUl->sbSize)) - rbPwr;
2244    uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
2245    uePwr->isPhrAvail = TRUE;
2246
2247    rgSCHPwrOnPuschPwrUpd(cell, ue);
2248
2249    RLOG_ARG4(L_DEBUG,DBG_UEID,ue->ueId,
2250          "Output: Reported PHR[%d] cqi[%u] allocRb[%u] uePwr->pwrPerRb[%d]",
2251             uePwr->phVal,
2252             allocInfo->cqi,
2253             allocInfo->numRb,  
2254             uePwr->pwrPerRb); 
2255    return;
2256 }
2257
2258 /**
2259  * @brief Handles UL CQI indication
2260  *
2261  * @details
2262  *
2263  *     Function : rgSCHPwrUlCqiInd
2264  *
2265  *     Invoking Module Processing:
2266  *      - This shall be invoked when uplink CQI indication
2267  *        is receiving from PHY for a UE.
2268  *
2269  *     Processing Steps:
2270  *     - Update remPuschPwr.
2271  *     - Possibly schedule for group power control.
2272  *
2273  *  @param[in]  RgSchCellCb         *cell
2274  *  @param[in]  RgSchUeCb           *ue
2275  *  @param[in]  uint8_t                   numRb
2276  *  @return  Void
2277  **/
2278 #ifdef ANSI
2279 Void rgSCHPwrUlCqiInd
2280 (
2281 RgSchCellCb           *cell,
2282 RgSchUeCb             *ue
2283 )
2284 #else
2285 Void rgSCHPwrUlCqiInd(cell, ue)
2286 RgSchCellCb           *cell;
2287 RgSchUeCb             *ue;
2288 #endif
2289 {
2290    RgSchCmnUlUe          *ueUl    = RG_SCH_CMN_GET_UL_UE(ue, cell);
2291    RgSchCmnUeUlPwrCb     *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
2292 #ifdef TFU_UPGRADE 
2293    S32  tmp;
2294 #endif
2295
2296    /*
2297     * For absolute power cmd case, we could look at the time
2298     * at which CQI was received, determine if there was a
2299     * PUSCH TPC cmd for that time (this could come from
2300     * group power control too), and (if this
2301     * CQI report is indeed based on the the PUSCH tx)
2302     * then factor in that cmd here. Not doing
2303     * this as of now.
2304     */
2305
2306    /* See how much power needs to be adjusted based on cqi
2307     * differential */
2308    uePwr->remPuschPwr = 
2309 #ifdef TFU_UPGRADE
2310       rgSCHPwrGetDelta2FrmCqi(ueUl->validUlCqi, uePwr->trgCqi, ue, cell);
2311 #else
2312       rgSCHPwrGetDelta2FrmCqi(ueUl->crntUlCqi[0], uePwr->trgCqi, ue, cell);
2313 #endif
2314
2315    rgSCHPwrOnPuschPwrUpd(cell, ue);
2316 #ifdef TFU_UPGRADE
2317    if(uePwr->maxPwrDeltaByPhr < 0)
2318    {
2319       tmp = ueUl->validUlCqi;
2320       tmp = tmp + uePwr->maxPwrDeltaByPhr;
2321       if (tmp < 1 )
2322       {
2323          ueUl->validUlCqi = 1;
2324       }
2325       else
2326       {
2327          ueUl->validUlCqi = tmp;
2328       }
2329    }
2330 #endif 
2331
2332    return;
2333 }
2334
2335 /**
2336  * @brief Updates the stored last number of RBs allocated
2337  *
2338  * @details
2339  *
2340  *     Function : rgSCHPwrRecordRbAlloc
2341  *
2342  *     Invoking Module Processing:
2343  *      - This shall be invoked when uplink allocation is made for
2344  *        a UE.
2345  *      - Note: If outstanding TPCs are considered at the time
2346  *        of PHR report, the last numRb would also be known
2347  *        and then this API would not be needed. 
2348  *
2349  *     Processing Steps:
2350  *     - Adjust PHR according to now allocated number of RBs
2351  *     - Store the number of RBs
2352  *
2353  *  @param[in]  RgSchCellCb         *cell
2354  *  @param[in]  RgSchUeCb           *ue
2355  *  @param[in]  uint8_t                   numRb
2356  *  @return  Void
2357  **/
2358 #ifdef ANSI
2359 Void rgSCHPwrRecordRbAlloc
2360 (
2361 RgSchCellCb           *cell,
2362 RgSchUeCb             *ue,
2363 uint8_t                     numRb
2364 )
2365 #else
2366 Void rgSCHPwrRecordRbAlloc(cell, ue, numRb)
2367 RgSchCellCb           *cell;
2368 RgSchUeCb             *ue;
2369 uint8_t                     numRb;
2370 #endif
2371 {
2372    RgSchCmnUeUlPwrCb     *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
2373    UNUSED(cell);
2374    return; 
2375
2376    if (uePwr->isPhrAvail)
2377    {
2378       uePwr->phVal += rgSCHPwrRbToPwr(cell,numRb) - rgSCHPwrRbToPwr(cell,uePwr->numRb);
2379       uePwr->phVal = RGSCH_MIN(40, uePwr->phVal);
2380    }
2381    uePwr->numRb = numRb;
2382    return;
2383 }
2384
2385 /**
2386  * @brief Handles power related configuration for a cell
2387  *
2388  * @details
2389  *
2390  *     Function : rgSCHPwrCellCfg
2391  *
2392  *     Invoking Module Processing:
2393  *      - This shall be invoked during cell config
2394  *        
2395  *     Processing Steps:
2396  *      - Set pMax
2397  *      - Set target CQI
2398  *      - Update TPC-RNTI information for the cell for Pucch and Pusch.
2399  *      - For each TPC-Pucch-RNTI,
2400  *         - Call  rgSCHAddRntiToPucchRntiLst()
2401  *      - For each TPC-Pusch-RNTI,
2402  *         - Call  rgSCHAddRntiToPuschRntiLst()
2403  *      - Return ROK
2404  *
2405  *  @param[in]  RgSchCellCb  *cell
2406  *  @param[in]  RgrCellCfg   *cfg
2407  *  @return  S16
2408  *      -# ROK
2409  *      -# RFAILED
2410  **/
2411 #ifdef ANSI
2412 S16 rgSCHPwrCellCfg
2413 (
2414 RgSchCellCb          *cell,
2415 RgrCellCfg           *cfg
2416 )
2417 #else
2418 S16 rgSCHPwrCellCfg(cell, cfg)
2419 RgSchCellCb          *cell;
2420 RgrCellCfg           *cfg;
2421 #endif
2422 {
2423    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2424    CmLteRnti              rnti;
2425    CmLteRnti              startRnti;
2426    uint16_t                    size;
2427    Bool                   isFmt3a;
2428
2429    /* Right now, all UEs have fixed maximum power capability. So
2430     * we store cell wide pMax as minimum of configured pMax and
2431     * UE's max power */
2432    cellPwr->pMax = RGSCH_MIN(cfg->pMax, RG_SCH_PWR_UE_MAX_PWR);
2433
2434    /* trgUlCqi already validated by common */
2435    cellPwr->trgUlCqi = cfg->trgUlCqi.trgCqi;
2436
2437    /* Validate number of TPC RNTIs */
2438    if ((cfg->pwrCfg.pucchPwrFmt3.size + cfg->pwrCfg.pucchPwrFmt3a.size
2439             > RG_SCH_CMN_MAX_NUM_TPC_PUCCH_RNTI)
2440          || (cfg->pwrCfg.puschPwrFmt3.size + cfg->pwrCfg.puschPwrFmt3a.size
2441             > RG_SCH_CMN_MAX_NUM_TPC_PUSCH_RNTI))
2442    {
2443       return RFAILED;
2444    }
2445
2446    /* Now initialise TPC RNTIs */
2447
2448    /* Format 3 Pucch TPC RNTIs */
2449    isFmt3a = FALSE;
2450    startRnti = cfg->pwrCfg.pucchPwrFmt3.startTpcRnti;
2451    size = cfg->pwrCfg.pucchPwrFmt3.size;
2452    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2453    {
2454       rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2455    }
2456
2457    /* Format 3A Pucch TPC RNTIs */
2458    isFmt3a = TRUE;
2459    startRnti = cfg->pwrCfg.pucchPwrFmt3a.startTpcRnti;
2460    size = cfg->pwrCfg.pucchPwrFmt3a.size;
2461    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2462    {
2463       rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2464    }
2465
2466    /* Format 3 Pusch TPC RNTIs */
2467    isFmt3a = FALSE;
2468    startRnti = cfg->pwrCfg.puschPwrFmt3.startTpcRnti;
2469    size = cfg->pwrCfg.puschPwrFmt3.size;
2470    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2471    {
2472       rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2473    }
2474
2475    /* Format 3A Pusch TPC RNTIs */
2476    isFmt3a = TRUE;
2477    startRnti = cfg->pwrCfg.puschPwrFmt3a.startTpcRnti;
2478    size = cfg->pwrCfg.puschPwrFmt3a.size;
2479    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2480    {
2481       rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2482    }
2483
2484    return ROK;
2485 }
2486
2487 /**
2488  * @brief Handles power related re-configuration for a cell
2489  *
2490  * @details
2491  *
2492  *     Function : rgSCHPwrCellRecfg
2493  *
2494  *     Processing Steps:
2495  *     - NONE
2496  *
2497  *  @param[in]  RgSchCellCb  *cell
2498  *  @param[in]  RgrCellRecfg *recfg
2499  *  @return  S16
2500  *      -# ROK
2501  **/
2502 #ifdef ANSI
2503 S16 rgSCHPwrCellRecfg
2504 (
2505 RgSchCellCb          *cell,
2506 RgrCellRecfg         *recfg
2507 )
2508 #else
2509 S16 rgSCHPwrCellRecfg(cell, recfg)
2510 RgSchCellCb          *cell;
2511 RgrCellRecfg         *recfg;
2512 #endif
2513 {
2514    UNUSED(cell);
2515    UNUSED(recfg);
2516
2517    /* Not doing anything for power reconfig, so such structure
2518     * in RGR */
2519    return ROK;
2520 }
2521
2522 /**
2523  * @brief Frees power related data structures in cell
2524  *
2525  * @details
2526  *
2527  *     Function : rgSCHPwrCellDel
2528  *
2529  *     Processing Steps:
2530  *      - NONE
2531  *
2532  *  @param[in]  RgSchCellCb  *cell
2533  *  @return  Void
2534  **/
2535 #ifdef ANSI
2536 Void rgSCHPwrCellDel
2537 (
2538 RgSchCellCb *cell
2539 )
2540 #else
2541 Void rgSCHPwrCellDel(cell)
2542 RgSchCellCb *cell;
2543 #endif
2544 {
2545    UNUSED(cell);
2546
2547    /* There is no allocated memory, so do nothing */
2548    return;
2549 }
2550
2551
2552 #ifdef LTE_ADV
2553 /**
2554  * @brief Configures ULPC CB for a SCELL being added
2555  *
2556  * @details
2557  *
2558  *     Function : rgSCHPwrUeSCellCfg
2559  *
2560  *  @param[in]  RgSchCellCb  *cell
2561  *  @param[in]  RgSchUeCb    *ue
2562  *  @param[in]  RgrUeCfg     *cfg
2563  *  @return  S16
2564  *      -# ROK
2565  *      -# RFAILED
2566  **/
2567 #ifdef ANSI
2568 S16 rgSCHPwrUeSCellCfg
2569 (
2570 RgSchCellCb *cell,
2571 RgSchUeCb   *ue,
2572 RgrUeSecCellCfg  *sCellInfoCfg
2573 )
2574 #else
2575 S16 rgSCHPwrUeSCellCfg(cell, ue, sCellInfoCfg)
2576 RgSchCellCb *cell;
2577 RgSchUeCb   *ue;
2578 RgrUeSecCellCfg  *sCellInfoCfg;
2579 #endif
2580 {
2581    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2582    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2583    RgSchCmnUeUlPwrCb     *uePwrPCell = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2584    RgSchCmnUlUe          *ueUl        = RG_SCH_CMN_GET_UL_UE(ue, cell);
2585
2586    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
2587
2588
2589    uePwr->maxUePwr = cellPwr->pMax;
2590    uePwr->trgCqi   = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2591    uePwr->numRb    = 1;
2592
2593    uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2594
2595    uePwr->isPhrAvail  = FALSE;
2596    uePwr->phVal       = 40;
2597    uePwr->maxUlRbs    = RGSCH_MAX_DL_BW;
2598    uePwr->delta       = 0;
2599    uePwr->puschTpc    = 1;
2600    uePwr->remPuschPwr = 0;
2601
2602    /* Rest of the vars update and group power control related
2603     * config happens in the function below */
2604    uePwr->isAccumulated = sCellInfoCfg->ueSCellUlDedPwrCfg.isAccumulated;
2605    uePwr->deltaMcsEnbld = sCellInfoCfg->ueSCellUlDedPwrCfg.isDeltaMCSEnabled;
2606
2607    uePwr->trgCqi = uePwrPCell->trgCqi;
2608
2609    if (ueUl->maxUlCqi < uePwr->trgCqi)
2610    {
2611       uePwr->trgCqi = ueUl->maxUlCqi;
2612    }
2613    uePwr->p0UePusch = sCellInfoCfg->ueSCellUlDedPwrCfg.p0UePusch;
2614
2615    return ROK;
2616 }
2617 #endif
2618
2619 /**
2620  * @brief Handles power related configuration for a UE
2621  *
2622  * @details
2623  *
2624  *     Function : rgSCHPwrUeCfg
2625  *
2626  *     Processing Steps:
2627  *      - If Pusch group power configuration exists && accumulation enabled,
2628  *        - Fetch the TPC-Pusch-RNTI control block for the configured
2629  *        TPC-Pusch-RNTI. Call rgSCHGetRntiFrmPuschRntiLst(). If it does not
2630  *        exist, return RFAILED.
2631  *        - Add Ue to the ueLst of TPC-Pusch-RNTI control block.
2632  *        - Update tpcPuschRntiCb pointer in UE.
2633  *        - Update the puschIdx value.
2634  *      - If Pucch group power configuration exists && accumulation enabled,
2635  *        - Fetch the TPC-Pucch-RNTI control block for the configured
2636  *        TPC-Pucch-RNTI. Call rgSCHGetRntiFrmPucchRntiLst(). If it does not
2637  *        exist, return RFAILED.
2638  *        - Add Ue to the ueLst of TPC-Pucch-RNTI control block.
2639  *        - Update tpcPucchRntiCb pointer in UE.
2640  *        - Update the pucchIdx value.
2641  *      - Update isAccumulated and isDeltaMcs variables.
2642  *      - maxUlRbs = configured maximum UL bandwidth value per UE.
2643  *      - trgUlCqi = configured value, if any, else cell-wide default trg CQI value.
2644  *      - If format type is format 3A, update remaining power to +1
2645  *      - Update TPC-RNTI information for the cell for Pucch and Pusch.
2646  *      - Return ROK
2647  *
2648  *  @param[in]  RgSchCellCb  *cell
2649  *  @param[in]  RgSchUeCb    *ue
2650  *  @param[in]  RgrUeCfg     *cfg
2651  *  @return  S16
2652  *      -# ROK
2653  *      -# RFAILED
2654  **/
2655 #ifdef ANSI
2656 S16 rgSCHPwrUeCfg
2657 (
2658 RgSchCellCb *cell,
2659 RgSchUeCb   *ue,
2660 RgrUeCfg    *cfg
2661 )
2662 #else
2663 S16 rgSCHPwrUeCfg(cell, ue, cfg)
2664 RgSchCellCb *cell;
2665 RgSchUeCb   *ue;
2666 RgrUeCfg    *cfg;
2667 #endif
2668 {
2669    S16                    ret;
2670    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2671    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2672
2673    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
2674
2675    uePwr->maxUePwr = cellPwr->pMax;
2676    uePwr->trgCqi   = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2677    uePwr->numRb    = 1;
2678
2679    uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2680
2681    rgSCHPwrUeResetPucch(cell, ue);
2682    rgSCHPwrUeResetPusch(cell, ue);
2683
2684    /* Rest of the vars update and group power control related
2685     * config happens in the function below */
2686    ret = rgSCHPwrApplyUePwrCfg(cell, ue, &cfg->ueUlPwrCfg);
2687
2688    return (ret);
2689 }
2690
2691 /**
2692  * @brief Handles power related re-configuration for a UE
2693  *
2694  * @details
2695  *
2696  *     Function : rgSCHPwrUeRecfg
2697  *
2698  *     Invoking Module Processing:
2699  *      - This shall be invoked by SCH_GOM at UE re-configuration.
2700  *        
2701  *     Processing Steps:
2702  *      - If change in TPC-RNTI, update the pointer and the TPC RNTI Cb appropriately.
2703  *      - If accumulation disabled, remove the UE from TPC-RNTI lists of UE, if
2704  *      it exists.
2705  *      - If group power configuration disabled, remove the UE from TPC-RNTI lists of UE, if
2706  *      it exists.
2707  *
2708  *  @param[in]  RgSchCellCb  *cell
2709  *  @param[in]  RgSchUeCb    *ue
2710  *  @param[in]  RgrUeRecfg   *recfg
2711  *
2712  *  @return  S16
2713  *      -# ROK
2714  *      -# RFAILED
2715  **/
2716 #ifdef ANSI
2717 S16 rgSCHPwrUeRecfg
2718 (
2719 RgSchCellCb   *cell,
2720 RgSchUeCb     *ue,
2721 RgrUeRecfg    *recfg
2722 )
2723 #else
2724 S16 rgSCHPwrUeRecfg(cell, ue, recfg)
2725 RgSchCellCb *cell;
2726 RgSchUeCb   *ue;
2727 RgrUeRecfg  *recfg;
2728 #endif
2729 {
2730    S16                    ret;
2731    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
2732    RgrUeUlPwrCfg         *pwrCfg = &recfg->ueUlPwrRecfg;
2733
2734    if (pwrCfg->p0UePucch != uePwr->p0UePucch)
2735    {
2736       rgSCHPwrUeResetPucch(cell, ue);
2737    }
2738    if ((pwrCfg->isAccumulated != uePwr->isAccumulated)
2739          || (pwrCfg->p0UePusch != uePwr->p0UePusch))
2740    {
2741       rgSCHPwrUeResetPusch(cell, ue);
2742    }
2743    ret = rgSCHPwrApplyUePwrCfg(cell, ue, &recfg->ueUlPwrRecfg);
2744
2745    return (ret);
2746 }
2747
2748 /***********************************************************
2749  *
2750  *     Func : rgSCHPwrApplyUePwrCfg
2751  *
2752  *     Desc : Applies power config for UE. Meants to be
2753  *            used during both power config and reconfig.
2754  *
2755  *     Ret  : ROK/RFAILED
2756  *
2757  *     Notes:
2758  *
2759  *     File :
2760  *
2761  **********************************************************/
2762 #ifdef ANSI
2763 PRIVATE S16 rgSCHPwrApplyUePwrCfg 
2764 (
2765 RgSchCellCb          *cell,
2766 RgSchUeCb            *ue,
2767 RgrUeUlPwrCfg        *pwrCfg
2768 )
2769 #else
2770 PRIVATE S16 rgSCHPwrApplyUePwrCfg(cell, ue, pwrCfg)
2771 RgSchCellCb          *cell;
2772 RgSchUeCb            *ue;
2773 RgrUeUlPwrCfg        *pwrCfg;
2774 #endif
2775 {
2776    S16                    ret;
2777    RgSchCmnUlUe          *ueUl        = RG_SCH_CMN_GET_UL_UE(ue, cell);
2778    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
2779    RgSchCmnTpcRntiCb     *pucchRntiCb = NULLP;
2780    RgSchCmnTpcRntiCb     *puschRntiCb = NULLP;
2781    uint8_t                     pucchIdx    = 0;
2782    uint8_t                     puschIdx    = 0;
2783
2784    /* Validate Pucch group power control config */
2785    if (pwrCfg->uePucchPwr.pres)
2786    {
2787       pucchRntiCb =
2788          rgSCHPwrGetPucchRntiCb(cell, pwrCfg->uePucchPwr.tpcRnti);
2789       if (pucchRntiCb == NULLP)
2790       {
2791          return RFAILED;
2792       }
2793       pucchIdx = pwrCfg->uePucchPwr.idx;
2794       ret = rgSCHPwrChkPucchTpcRntiIdx(pucchRntiCb, pucchIdx);
2795       if (ret != ROK)
2796       {
2797          return (ret);
2798       }
2799    }
2800
2801    /* Validate Pusch group power control config */
2802    if (pwrCfg->uePuschPwr.pres)
2803    {
2804       puschRntiCb =
2805          rgSCHPwrGetPuschRntiCb(cell, pwrCfg->uePuschPwr.tpcRnti);
2806       if (puschRntiCb == NULLP)
2807       {
2808          return RFAILED;
2809       }
2810       puschIdx = pwrCfg->uePuschPwr.idx;
2811       ret = rgSCHPwrChkPuschTpcRntiIdx(puschRntiCb, puschIdx);
2812       if (ret != ROK)
2813       {
2814          return (ret);
2815       }
2816    }
2817
2818    /* Apply Pucch group power control config */
2819    if (pucchRntiCb)
2820    {
2821       if (uePwr->tpcPucchRntiCb != pucchRntiCb) /* This part for recfg */
2822       {
2823          if (uePwr->tpcPucchRntiCb)
2824          {
2825             rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2826          }
2827          uePwr->tpcPucchRntiCb = pucchRntiCb;
2828          rgSCHPwrAddUeToPucchTpcRntiCb(cell, pucchRntiCb, ue);
2829       }
2830       uePwr->pucchIdx = pucchIdx;
2831 #ifndef ALIGN_64BIT
2832       RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2833                "<GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2834                pucchRntiCb->cfgdUes.count,((uint32_t)pucchRntiCb->cfgdUes.first),
2835                ((uint32_t)pucchRntiCb->cfgdUes.last),ue->ueId);
2836       RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
2837                "UEID:%d isFmt3a(%u) ueNode(%ld)",
2838                ue->ueId,pucchRntiCb->isFmt3a,
2839                pucchRntiCb->schdLnk.node);
2840       RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2841                "toBeSchdUes(%ld %lu %lu) tpcRnti(%u)", 
2842                pucchRntiCb->toBeSchdUes.count, 
2843                ((uint32_t)pucchRntiCb->toBeSchdUes.first),
2844                ((uint32_t)pucchRntiCb->toBeSchdUes.last), 
2845                pucchRntiCb->tpcRnti);
2846 #else
2847       RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2848                "<GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2849                pucchRntiCb->cfgdUes.count,((uint64_t)pucchRntiCb->cfgdUes.first),
2850                ((uint64_t)pucchRntiCb->cfgdUes.last),ue->ueId);
2851       RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
2852                "UEID:%d isFmt3a(%u) ueNode(%ld)",
2853                ue->ueId,pucchRntiCb->isFmt3a,
2854                pucchRntiCb->schdLnk.node);
2855       RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2856                "toBeSchdUes(%ld %lu %lu) tpcRnti(%u)", 
2857                pucchRntiCb->toBeSchdUes.count, 
2858                ((uint64_t)pucchRntiCb->toBeSchdUes.first),
2859                ((uint64_t)pucchRntiCb->toBeSchdUes.last), 
2860                pucchRntiCb->tpcRnti);
2861
2862 #endif
2863    }
2864
2865    /* Apply Pusch group power control config */
2866    if (puschRntiCb)
2867    {
2868       if (uePwr->tpcPuschRntiCb != puschRntiCb) /* This part for recfg */
2869       {
2870          if (uePwr->tpcPuschRntiCb)
2871          {
2872             rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2873          }
2874          uePwr->tpcPuschRntiCb = puschRntiCb;
2875          rgSCHPwrAddUeToPuschTpcRntiCb(puschRntiCb, ue);
2876       }
2877       uePwr->puschIdx = puschIdx;
2878    }
2879
2880    /* Update vars */
2881    uePwr->isAccumulated = pwrCfg->isAccumulated;
2882    uePwr->deltaMcsEnbld = pwrCfg->isDeltaMCSEnabled;
2883    if (pwrCfg->trgCqi)
2884    {
2885       uePwr->trgCqi = pwrCfg->trgCqi;
2886    }
2887    if (ueUl->maxUlCqi < uePwr->trgCqi)
2888    {
2889       uePwr->trgCqi = ueUl->maxUlCqi;
2890    }
2891    uePwr->p0UePusch = pwrCfg->p0UePusch;
2892    uePwr->p0UePucch = pwrCfg->p0UePucch;
2893
2894    return ROK;
2895 }
2896
2897
2898 /**
2899  * @brief Deletes power related information for UE
2900  *
2901  * @details
2902  *
2903  *     Function : rgSCHPwrUeDel
2904  *
2905  *     Invoking Module Processing:
2906  *      - This shall be invoked by at the time of UE deletion.
2907  *        
2908  *     Processing Steps:
2909  *     - if (ue->tpcPucchRntiCb)
2910  *       - delete UE from tpcPucchRntiCb->ueLst
2911  *       - ue->tpcPucchRntiCb = NULLP
2912  *       - If in (ue->tpcPucchRntiCb->toBeSchdLst) 
2913  *         - remove from the list.
2914  *     - if (ue->tpcPuschRntiCb)
2915  *       - delete UE from tpcPuschRntiCb->ueLst
2916  *       - ue->tpcPuschRntiCb = NULLP
2917  *       - If in (ue->tpcPuschRntiCb->toBeSchdLst) 
2918  *         - remove from the list.
2919  *
2920  *  @param[in]  RgSchCellCb     *cell
2921  *  @param[in]  RgSchUeCb       *ue
2922  *  @return  Void
2923  **/
2924 #ifdef ANSI
2925 Void rgSCHPwrUeDel
2926 (
2927 RgSchCellCb           *cell,
2928 RgSchUeCb             *ue
2929 )
2930 #else
2931 Void rgSCHPwrUeDel(cell, ue)
2932 RgSchCellCb           *cell;
2933 RgSchUeCb             *ue;
2934 #endif
2935 {
2936    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2937
2938    if (uePwr->tpcPucchRntiCb)
2939    {
2940       rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2941       uePwr->tpcPucchRntiCb = NULLP;
2942    }
2943    if (uePwr->tpcPuschRntiCb)
2944    {
2945       rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2946       uePwr->tpcPuschRntiCb = NULLP;
2947    }
2948    return;
2949 }
2950
2951 /**
2952  * @brief Resets UE's power state
2953  *
2954  * @details
2955  *
2956  *     Function : rgSCHPwrUeReset
2957  *
2958  *     Invoking Module Processing:
2959  *      - This shall be invoked by at the time PDCCH order.
2960  *
2961  *     Processing Steps:
2962  *     - Reset PUSCH power state
2963  *     - Reset PUCCH power state
2964  *
2965  *  @param[in]  RgSchCellCb     *cell
2966  *  @param[in]  RgSchUeCb       *ue
2967  *  @return  Void
2968  **/
2969 #ifdef ANSI
2970 Void rgSCHPwrUeReset
2971 (
2972 RgSchCellCb           *cell,
2973 RgSchUeCb             *ue
2974 )
2975 #else
2976 Void rgSCHPwrUeReset(cell, ue)
2977 RgSchCellCb           *cell;
2978 RgSchUeCb             *ue;
2979 #endif
2980 {
2981
2982    rgSCHPwrUeResetPucch(cell, ue);
2983    rgSCHPwrUeResetPusch(cell, ue);
2984    return;
2985 }
2986
2987 /***********************************************************
2988  *
2989  *     Func : rgSCHPwrUeResetPucch
2990  *
2991  *     Desc : This function is called to reset UE
2992  *            to initial PUCCH power state.
2993  *
2994  *     Ret  : Void
2995  *
2996  *     Notes:
2997  *
2998  *     File :
2999  *
3000  **********************************************************/
3001 #ifdef ANSI
3002 PRIVATE Void rgSCHPwrUeResetPucch 
3003 (
3004 RgSchCellCb          *cell,
3005 RgSchUeCb            *ue
3006 )
3007 #else
3008 PRIVATE Void rgSCHPwrUeResetPucch(cell, ue)
3009 RgSchCellCb          *cell;
3010 RgSchUeCb            *ue;
3011 #endif
3012 {
3013    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
3014
3015    uePwr->pucchTpc    = 1;
3016    uePwr->remPucchPwr = 0;
3017    if (uePwr->tpcPucchRntiCb)
3018    {
3019       rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
3020    }
3021
3022    /* Stack Crash problem for TRACE5 changes. Added the line below */
3023   return;
3024  
3025 }
3026
3027 /***********************************************************
3028  *
3029  *     Func : rgSCHPwrUeResetPusch
3030  *
3031  *     Desc : This function is called to reset UE
3032  *            to initial PUSCH power state.
3033  *
3034  *     Ret  : Void
3035  *
3036  *     Notes:
3037  *
3038  *     File :
3039  *
3040  **********************************************************/
3041 #ifdef ANSI
3042 PRIVATE Void rgSCHPwrUeResetPusch 
3043 (
3044 RgSchCellCb          *cell,
3045 RgSchUeCb            *ue
3046 )
3047 #else
3048 PRIVATE Void rgSCHPwrUeResetPusch(cell, ue)
3049 RgSchCellCb          *cell;
3050 RgSchUeCb            *ue;
3051 #endif
3052 {
3053    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
3054
3055    uePwr->isPhrAvail  = FALSE;
3056    uePwr->phVal       = 40;
3057    uePwr->maxUlRbs    = RGSCH_MAX_DL_BW;
3058    uePwr->delta       = 0;
3059    uePwr->puschTpc    = 1;
3060    uePwr->remPuschPwr = 0;
3061    if (uePwr->tpcPuschRntiCb)
3062    {
3063       rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
3064    }
3065    return;
3066 }
3067
3068 /***********************************************************
3069  *
3070  *     Func : rgSCHPwrOnPuschPwrUpd
3071  *
3072  *     Desc : This function is called whenever 'remPuschPwr'
3073  *            is updated
3074  *
3075  *     Ret  : Void
3076  *
3077  *     Notes:
3078  *
3079  *     File :
3080  *
3081  **********************************************************/
3082 #ifdef ANSI
3083 PRIVATE Void rgSCHPwrOnPuschPwrUpd 
3084 (
3085 RgSchCellCb          *cell,
3086 RgSchUeCb            *ue
3087 )
3088 #else
3089 PRIVATE Void rgSCHPwrOnPuschPwrUpd(cell, ue)
3090 RgSchCellCb          *cell;
3091 RgSchUeCb            *ue;
3092 #endif
3093 {
3094    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3095    RgSchCmnTpcRntiCb     *cb;
3096    Bool                   toAdd;
3097
3098    if ((cb = uePwr->tpcPuschRntiCb) == NULLP)
3099    {
3100       return;
3101    }
3102
3103    /* Not checking for uwPwr->isPhrAvail as uePwr->phVal
3104     * is set to a large value initially */
3105    toAdd = FALSE;
3106
3107
3108    if ((uePwr->phVal != 0) && (uePwr->remPuschPwr != 0))
3109       {
3110          toAdd = TRUE;
3111       }
3112
3113
3114    if (toAdd)
3115    {
3116       rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue);
3117    }
3118    else
3119    {
3120       rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
3121    }
3122
3123    return;
3124 }
3125
3126
3127 /***********************************************************
3128  *
3129  *     Func : rgSCHPwrAddRntiToPucchRntiLst
3130  *
3131  *
3132  *     Desc : Adds RNTI to Pucch Rnti list and updates requisite
3133  *            information. 
3134  *
3135  *     Ret  : Void
3136  *
3137  *     Notes: Assumed that array bounds are checked
3138  *            in caller before adding.
3139  *
3140  *     File :
3141  *
3142  **********************************************************/
3143 #ifdef ANSI
3144 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst 
3145 (
3146 RgSchCellCb          *cell,
3147 CmLteRnti             rnti,
3148 Bool                  isFmt3a
3149 )
3150 #else
3151 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a)
3152 RgSchCellCb          *cell;
3153 CmLteRnti             rnti;
3154 Bool                  isFmt3a;
3155 #endif
3156 {
3157    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3158
3159    rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPucchRntiLst[cellPwr->tpcPucchRntiCnt++],
3160        rnti, isFmt3a);
3161    return;
3162 }
3163
3164 /***********************************************************
3165  *
3166  *     Func : rgSCHPwrAddRntiToPuschRntiLst
3167  *
3168  *
3169  *     Desc : Adds RNTI to Pusch Rnti list and updates requisite
3170  *            information. 
3171  *
3172  *     Ret  : Void
3173  *
3174  *     Notes: Assumed that array bounds are checked
3175  *            in caller before adding.
3176  *
3177  *     File :
3178  *
3179  **********************************************************/
3180 #ifdef ANSI
3181 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst 
3182 (
3183 RgSchCellCb          *cell,
3184 CmLteRnti             rnti,
3185 Bool                  isFmt3a
3186 )
3187 #else
3188 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a)
3189 RgSchCellCb          *cell;
3190 CmLteRnti             rnti;
3191 Bool                  isFmt3a;
3192 #endif
3193 {
3194    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3195
3196    rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPuschRntiLst[cellPwr->tpcPuschRntiCnt++], 
3197        rnti, isFmt3a);
3198    return;
3199 }
3200
3201 /***********************************************************
3202  *
3203  *     Func : rgSCHPwrInitTpcRntiCb
3204  *
3205  *
3206  *     Desc : Initialises a TPC RNTI CB
3207  *
3208  *     Ret  : Void
3209  *
3210  *     Notes:
3211  *
3212  *     File :
3213  *
3214  **********************************************************/
3215 #ifdef ANSI
3216 PRIVATE Void rgSCHPwrInitTpcRntiCb 
3217 (
3218 RgSchCmnTpcRntiCb    *cb,
3219 CmLteRnti             rnti,
3220 Bool                  isFmt3a
3221 )
3222 #else
3223 PRIVATE Void rgSCHPwrInitTpcRntiCb(cb, rnti, isFmt3a)
3224 RgSchCmnTpcRntiCb    *cb;
3225 CmLteRnti             rnti;
3226 Bool                  isFmt3a;
3227 #endif
3228 {
3229
3230    memset(cb, 0, sizeof(*cb));
3231    cb->tpcRnti = rnti;
3232    cb->isFmt3a = isFmt3a;
3233    /* Not initialising lists as memset 0 takes care of it */
3234    /* cb->schdLnk.node is set when this rnti is to be scheduled */
3235    return;
3236 }
3237
3238 /***********************************************************
3239  *
3240  *     Func : rgSCHPwrGetPucchRntiCb
3241  *
3242  *
3243  *     Desc : Gets TPC RNTI control block from Pucch rnti list 
3244  *
3245  *     Ret  : RgSchCmnTpcRntiCb * - Success
3246  *            NULLP - Fail
3247  *
3248  *     Notes:
3249  *
3250  *     File :
3251  *
3252  **********************************************************/
3253 #ifdef ANSI
3254 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb
3255 (
3256 RgSchCellCb *cell,
3257 CmLteRnti   tpcRnti
3258 )
3259 #else
3260 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb(cell, tpcRnti)
3261 RgSchCellCb *cell;
3262 CmLteRnti   tpcRnti;
3263 #endif
3264 {
3265    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3266    uint16_t                    idx;
3267
3268    if (!cellPwr->tpcPucchRntiCnt)
3269    {
3270       return (NULLP);
3271    }
3272    for (idx = 0; idx < cellPwr->tpcPucchRntiCnt; ++idx)
3273    {
3274       if (cellPwr->tpcPucchRntiLst[idx].tpcRnti == tpcRnti)
3275       {
3276          return (&cellPwr->tpcPucchRntiLst[idx]);
3277       }
3278    }
3279    return (NULLP);
3280 }
3281
3282 /***********************************************************
3283  *
3284  *     Func : rgSCHPwrGetPuschRntiCb
3285  *
3286  *
3287  *     Desc : Gets TPC RNTI control block from Pusch rnti list 
3288  *
3289  *     Ret  : RgSchCmnTpcRntiCb * - Success
3290  *            NULLP - Fail
3291  *
3292  *     Notes:
3293  *
3294  *     File :
3295  *
3296  **********************************************************/
3297 #ifdef ANSI
3298 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb
3299 (
3300 RgSchCellCb *cell,
3301 CmLteRnti   tpcRnti
3302 )
3303 #else
3304 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb(cell, tpcRnti)
3305 RgSchCellCb *cell;
3306 CmLteRnti   tpcRnti;
3307 #endif
3308 {
3309    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3310    uint16_t                    idx;
3311
3312    if (!cellPwr->tpcPuschRntiCnt)
3313    {
3314       return (NULLP);
3315    }
3316    for (idx = 0; idx < cellPwr->tpcPuschRntiCnt; ++idx)
3317    {
3318       if (cellPwr->tpcPuschRntiLst[idx].tpcRnti == tpcRnti)
3319       {
3320          return (&cellPwr->tpcPuschRntiLst[idx]);
3321       }
3322    }
3323    return (NULLP);
3324 }
3325
3326
3327 /***********************************************************
3328  *
3329  *     Func : rgSCHPwrAddUeToPucchTpcRntiCb
3330  *
3331  *
3332  *     Desc : Add UE to cfgd list of UEs in rnti cb
3333  *
3334  *     Ret  :
3335  *
3336  *     Notes:
3337  *
3338  *     File :
3339  *
3340  **********************************************************/
3341 #ifdef ANSI
3342 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb
3343 (
3344 RgSchCellCb           *cell,
3345 RgSchCmnTpcRntiCb     *cb,
3346 RgSchUeCb             *ue
3347 )
3348 #else
3349 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb(cell, cb, ue)
3350 RgSchCellCb           *cell;
3351 RgSchCmnTpcRntiCb     *cb;
3352 RgSchUeCb             *ue;
3353 #endif
3354 {
3355    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3356    UNUSED(cell);
3357
3358    cmLListAdd2Tail(&cb->cfgdUes, &uePwr->pucchGrpLnk);
3359    uePwr->pucchGrpLnk.node = (PTR)ue;
3360    return;
3361 }
3362
3363 /***********************************************************
3364  *
3365  *     Func : rgSCHPwrDelUeFrmPucchTpcRntiCb
3366  *
3367  *
3368  *     Desc : Remove UE from Pucch TPC RNTI CB
3369  *
3370  *     Ret  :
3371  *
3372  *     Notes:
3373  *
3374  *     File :
3375  *
3376  **********************************************************/
3377 #ifdef ANSI
3378 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb
3379 (
3380 RgSchCellCb           *cell,
3381 RgSchCmnTpcRntiCb     *cb,
3382 RgSchUeCb             *ue
3383 )
3384 #else
3385 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, cb, ue)
3386 RgSchCellCb           *cell;
3387 RgSchCmnTpcRntiCb     *cb;
3388 RgSchUeCb             *ue;
3389 #endif
3390 {
3391    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3392
3393    rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
3394    cmLListDelFrm(&cb->cfgdUes, &uePwr->pucchGrpLnk);
3395    uePwr->pucchGrpLnk.node = NULLP;
3396    return;
3397 }
3398
3399 /***********************************************************
3400  *
3401  *     Func : rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
3402  *
3403  *
3404  *     Desc : Remove UE from to-be-scheduled list of UEs
3405  *            in Pusch RNTI CB
3406  *
3407  *     Ret  :
3408  *
3409  *     Notes:
3410  *
3411  *     File :
3412  *
3413  **********************************************************/
3414 #ifdef ANSI
3415 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
3416 (
3417 RgSchCellCb           *cell,
3418 RgSchCmnTpcRntiCb     *cb,
3419 RgSchUeCb             *ue
3420 )
3421 #else
3422 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue)
3423 RgSchCellCb           *cell;
3424 RgSchCmnTpcRntiCb     *cb;
3425 RgSchUeCb             *ue;
3426 #endif
3427 {
3428    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3429
3430    if (uePwr->schdPucchGrpLnk.node == NULLP)
3431    {
3432       return;
3433    }
3434    rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue);
3435    if (!cb->toBeSchdUes.count)
3436    {
3437       rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
3438    }
3439    return;
3440 }
3441
3442 /***********************************************************
3443  *
3444  *     Func : rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
3445  *
3446  *     Desc : Remove UE from to-be-scheduled list of UEs
3447  *            in Pucch RNTI CB. Do not both about
3448  *            possibly removing Pucch RNTI CB from
3449  *            the cell wide to-be-scheduled list.
3450  *
3451  *     Ret  :
3452  *
3453  *     Notes:
3454  *
3455  *     File :
3456  *
3457  **********************************************************/
3458 #ifdef ANSI
3459 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
3460 (
3461 RgSchCellCb           *cell,
3462 RgSchCmnTpcRntiCb     *cb,
3463 RgSchUeCb             *ue
3464 )
3465 #else
3466 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue)
3467 RgSchCellCb           *cell;
3468 RgSchCmnTpcRntiCb     *cb;
3469 RgSchUeCb             *ue;
3470 #endif
3471 {
3472    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3473
3474    if (uePwr->schdPucchGrpLnk.node != NULLP)
3475    {
3476       cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
3477       uePwr->schdPucchGrpLnk.node = NULLP;
3478    }
3479    return;
3480 }
3481
3482 /***********************************************************
3483  *
3484  *     Func : rgSCHPwrRmvSchdPucchTpcRntiCb
3485  *
3486  *     Desc : Remove Pucch TPC RNTI CB from to-be-scheduled
3487  *            list in cell
3488  *
3489  *     Ret  : Void
3490  *
3491  *     Notes:
3492  *
3493  *     File :
3494  *
3495  **********************************************************/
3496 #ifdef ANSI
3497 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb
3498 (
3499 RgSchCellCb           *cell,
3500 RgSchCmnTpcRntiCb     *cb
3501 )
3502 #else
3503 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb)
3504 RgSchCellCb           *cell;
3505 RgSchCmnTpcRntiCb     *cb;
3506 #endif
3507 {
3508    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3509
3510    if (cb->schdLnk.node == NULLP)
3511    {
3512       return;
3513    }
3514    cmLListDelFrm(&cellPwr->pucchGrpPwr, &cb->schdLnk);
3515    cb->schdLnk.node = NULLP;
3516    return;
3517 }
3518
3519 /***********************************************************
3520  *
3521  *     Func : rgSCHPwrAddSchdUeToPucchTpcRntiCb
3522  *
3523  *     Desc : Add UE to to-be-scheduled list of UEs
3524  *            in Pucch RNTI CB
3525  *
3526  *     Ret  :
3527  *
3528  *     Notes:
3529  *
3530  *     File :
3531  *
3532  **********************************************************/
3533 #ifdef ANSI
3534 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb
3535 (
3536 RgSchCellCb           *cell,
3537 RgSchCmnTpcRntiCb     *cb,
3538 RgSchUeCb             *ue
3539 )
3540 #else
3541 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue)
3542 RgSchCellCb           *cell;
3543 RgSchCmnTpcRntiCb     *cb;
3544 RgSchUeCb             *ue;
3545 #endif
3546 {
3547    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3548
3549    if (uePwr->schdPucchGrpLnk.node != NULLP)
3550    {
3551       /* UE is already in the list */
3552       return;
3553    }
3554    cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
3555    uePwr->schdPucchGrpLnk.node = (PTR)ue;
3556    if (cb->toBeSchdUes.count == 1)
3557    {
3558       /* This is first UE, so queue up this TPC RNTI
3559        * for scheduling */
3560       rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb);
3561    }
3562    return;
3563 }
3564
3565 /***********************************************************
3566  *
3567  *     Func : rgSCHPwrAddSchdPucchTpcRntiCb
3568  *
3569  *     Desc : Add Pucch TPC RNTI CB from to-be-scheduled
3570  *            list in cell
3571  *
3572  *     Ret  : Void
3573  *
3574  *     Notes:
3575  *
3576  *     File :
3577  *
3578  **********************************************************/
3579 #ifdef ANSI
3580 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb
3581 (
3582 RgSchCellCb           *cell,
3583 RgSchCmnTpcRntiCb     *cb
3584 )
3585 #else
3586 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb)
3587 RgSchCellCb           *cell;
3588 RgSchCmnTpcRntiCb     *cb;
3589 #endif
3590 {
3591    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3592
3593    cmLListAdd2Tail(&cellPwr->pucchGrpPwr, &cb->schdLnk);
3594    cb->schdLnk.node = (PTR)cb;
3595    return;
3596 }
3597
3598
3599 /***********************************************************
3600  *
3601  *     Func : rgSCHPwrAddUeToPuschTpcRntiCb
3602  *
3603  *
3604  *     Desc : Add UE to cfgd list of UEs in rnti cb
3605  *
3606  *     Ret  :
3607  *
3608  *     Notes:
3609  *
3610  *     File :
3611  *
3612  **********************************************************/
3613 #ifdef ANSI
3614 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb
3615 (
3616 RgSchCmnTpcRntiCb     *cb,
3617 RgSchUeCb             *ue
3618 )
3619 #else
3620 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb(cb, ue)
3621 RgSchCmnTpcRntiCb     *cb;
3622 RgSchUeCb             *ue;
3623 #endif
3624 {
3625    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3626
3627    cmLListAdd2Tail(&cb->cfgdUes, &uePwr->puschGrpLnk);
3628    uePwr->puschGrpLnk.node = (PTR)ue;
3629    return;
3630 }
3631
3632 /***********************************************************
3633  *
3634  *     Func : rgSCHPwrAddSchdUeToPuschTpcRntiCb
3635  *
3636  *     Desc : Add UE to to-be-scheduled list of UEs
3637  *            in Pusch RNTI CB
3638  *
3639  *     Ret  :
3640  *
3641  *     Notes:
3642  *
3643  *     File :
3644  *
3645  **********************************************************/
3646 #ifdef ANSI
3647 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb
3648 (
3649 RgSchCellCb           *cell,
3650 RgSchCmnTpcRntiCb     *cb,
3651 RgSchUeCb             *ue
3652 )
3653 #else
3654 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue)
3655 RgSchCellCb           *cell;
3656 RgSchCmnTpcRntiCb     *cb;
3657 RgSchUeCb             *ue;
3658 #endif
3659 {
3660    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3661
3662    if (uePwr->schdPuschGrpLnk.node != NULLP)
3663    {
3664       /* UE is already in the list */
3665       return;
3666    }
3667    cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3668    uePwr->schdPuschGrpLnk.node = (PTR)ue;
3669    if (cb->toBeSchdUes.count == 1)
3670    {
3671       /* This is first UE, so queue up this TPC RNTI
3672        * for scheduling */
3673       rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb);
3674    }
3675    return;
3676 }
3677
3678 /***********************************************************
3679  *
3680  *     Func : rgSCHPwrDelUeFrmPuschTpcRntiCb
3681  *
3682  *
3683  *     Desc : Add UE to cfgd list of UEs in rnti cb
3684  *
3685  *     Ret  :
3686  *
3687  *     Notes:
3688  *
3689  *     File :
3690  *
3691  **********************************************************/
3692 #ifdef ANSI
3693 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb
3694 (
3695 RgSchCellCb           *cell,
3696 RgSchCmnTpcRntiCb     *cb,
3697 RgSchUeCb             *ue
3698 )
3699 #else
3700 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, cb, ue)
3701 RgSchCellCb           *cell;
3702 RgSchCmnTpcRntiCb     *cb;
3703 RgSchUeCb             *ue;
3704 #endif
3705 {
3706    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3707
3708    rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
3709    cmLListDelFrm(&cb->cfgdUes, &uePwr->puschGrpLnk);
3710    uePwr->puschGrpLnk.node = NULLP;
3711    return;
3712 }
3713
3714 /***********************************************************
3715  *
3716  *     Func : rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3717  *
3718  *     Desc : Remove UE from to-be-scheduled list of UEs
3719  *            in Pusch RNTI CB
3720  *
3721  *     Ret  :
3722  *
3723  *     Notes:
3724  *
3725  *     File :
3726  *
3727  **********************************************************/
3728 #ifdef ANSI
3729 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3730 (
3731 RgSchCellCb           *cell,
3732 RgSchCmnTpcRntiCb     *cb,
3733 RgSchUeCb             *ue
3734 )
3735 #else
3736 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue)
3737 RgSchCellCb           *cell;
3738 RgSchCmnTpcRntiCb     *cb;
3739 RgSchUeCb             *ue;
3740 #endif
3741 {
3742    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3743
3744    if (uePwr->schdPuschGrpLnk.node == NULLP)
3745    {
3746       return;
3747    }
3748    rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue);
3749    if (!cb->toBeSchdUes.count)
3750    {
3751       rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
3752    }
3753    return;
3754 }
3755
3756 /***********************************************************
3757  *
3758  *     Func : rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3759  *
3760  *     Desc : Remove UE from to-be-scheduled list of UEs
3761  *            in Pusch RNTI CB. Do not both about
3762  *            possibly removing Pusch RNTI CB from
3763  *            the cell wide to-be-scheduled list.
3764  *
3765  *     Ret  :
3766  *
3767  *     Notes:
3768  *
3769  *     File :
3770  *
3771  **********************************************************/
3772 #ifdef ANSI
3773 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3774 (
3775 RgSchCellCb           *cell,
3776 RgSchCmnTpcRntiCb     *cb,
3777 RgSchUeCb             *ue
3778 )
3779 #else
3780 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue)
3781 RgSchCellCb           *cell;
3782 RgSchCmnTpcRntiCb     *cb;
3783 RgSchUeCb             *ue;
3784 #endif
3785 {
3786    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3787
3788    if (uePwr->schdPuschGrpLnk.node != NULLP)
3789    {
3790       cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3791       uePwr->schdPuschGrpLnk.node = NULLP;
3792    }
3793    return;
3794 }
3795
3796 /***********************************************************
3797  *
3798  *     Func : rgSCHPwrAddSchdPuschTpcRntiCb
3799  *
3800  *     Desc : Add Pusch TPC RNTI CB from to-be-scheduled
3801  *            list in cell
3802  *
3803  *     Ret  : Void
3804  *
3805  *     Notes:
3806  *
3807  *     File :
3808  *
3809  **********************************************************/
3810 #ifdef ANSI
3811 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb
3812 (
3813 RgSchCellCb           *cell,
3814 RgSchCmnTpcRntiCb     *cb
3815 )
3816 #else
3817 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb)
3818 RgSchCellCb           *cell;
3819 RgSchCmnTpcRntiCb     *cb;
3820 #endif
3821 {
3822    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3823
3824    cmLListAdd2Tail(&cellPwr->puschGrpPwr, &cb->schdLnk);
3825    cb->schdLnk.node = (PTR)cb;
3826    return;
3827 }
3828
3829 /***********************************************************
3830  *
3831  *     Func : rgSCHPwrRmvSchdPuschTpcRntiCb
3832  *
3833  *     Desc : Remove Pusch TPC RNTI CB from to-be-scheduled
3834  *            list in cell
3835  *
3836  *     Ret  : Void
3837  *
3838  *     Notes:
3839  *
3840  *     File :
3841  *
3842  **********************************************************/
3843 #ifdef ANSI
3844 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb
3845 (
3846 RgSchCellCb           *cell,
3847 RgSchCmnTpcRntiCb     *cb
3848 )
3849 #else
3850 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb)
3851 RgSchCellCb           *cell;
3852 RgSchCmnTpcRntiCb     *cb;
3853 #endif
3854 {
3855    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3856
3857    if (cb->schdLnk.node == NULLP)
3858    {
3859       return;
3860    }
3861    cmLListDelFrm(&cellPwr->puschGrpPwr, &cb->schdLnk);
3862    cb->schdLnk.node = NULLP;
3863    return;
3864 }
3865
3866 /***********************************************************
3867  *
3868  *     Func : rgSCHPwrChkPucchTpcRntiIdx
3869  *
3870  *     Desc : Validate that the given index is OK to
3871  *            be assigned to a new UE for the Pucch TPC
3872  *            RNTI
3873  *
3874  *     Ret  :
3875  *
3876  *     Notes:
3877  *
3878  *     File :
3879  *
3880  **********************************************************/
3881 #ifdef ANSI
3882 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx
3883 (
3884 RgSchCmnTpcRntiCb     *cb,
3885 uint8_t                     idx
3886 )
3887 #else
3888 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx(cb, idx)
3889 RgSchCmnTpcRntiCb     *cb;
3890 uint8_t                     idx;
3891 #endif
3892 {
3893
3894    if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
3895    {
3896       return RFAILED;
3897    }
3898    if (rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx) != ROK)
3899    {
3900       return RFAILED;
3901    }
3902    return ROK;
3903 }
3904
3905 /***********************************************************
3906  *
3907  *     Func : rgSCHPwrChkPuschTpcRntiIdx
3908  *
3909  *     Desc : Validate that the given index is OK to
3910  *            be assigned to a new UE for the Pusch TPC
3911  *            RNTI
3912  *
3913  *     Ret  :
3914  *
3915  *     Notes:
3916  *
3917  *     File :
3918  *
3919  **********************************************************/
3920 #ifdef ANSI
3921 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx
3922 (
3923 RgSchCmnTpcRntiCb     *cb,
3924 uint8_t                     idx
3925 )
3926 #else
3927 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx(cb, idx)
3928 RgSchCmnTpcRntiCb     *cb;
3929 uint8_t                     idx;
3930 #endif
3931 {
3932
3933    if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
3934    {
3935       return RFAILED;
3936    }
3937    if (rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx) != ROK)
3938    {
3939       return RFAILED;
3940    }
3941    return ROK;
3942 }
3943
3944 /***********************************************************
3945  *
3946  *     Func : rgSCHPwrChkUniqPucchTpcRntiIdx
3947  *
3948  *     Desc : Validate index against format type of TPC RNTI
3949  *
3950  *     Ret  :
3951  *
3952  *     Notes:
3953  *
3954  *     File :
3955  *
3956  **********************************************************/
3957 #ifdef ANSI
3958 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx
3959 (
3960 RgSchCmnTpcRntiCb     *cb,
3961 uint8_t                     idx
3962 )
3963 #else
3964 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx)
3965 RgSchCmnTpcRntiCb     *cb;
3966 uint8_t                     idx;
3967 #endif
3968 {
3969    CmLList           *lnk;
3970
3971    for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
3972    {
3973       RgSchUeCb             *ue = (RgSchUeCb *)lnk->node;
3974       RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3975       if (uePwr->pucchIdx == idx)
3976       {
3977          return RFAILED;
3978       }
3979    }
3980    return ROK;
3981 }
3982
3983 /***********************************************************
3984  *
3985  *     Func : rgSCHPwrChkUniqPuschTpcRntiIdx
3986  *
3987  *     Desc : Validate index against format type of TPC RNTI
3988  *
3989  *     Ret  :
3990  *
3991  *     Notes:
3992  *
3993  *     File :
3994  *
3995  **********************************************************/
3996 #ifdef ANSI
3997 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx
3998 (
3999 RgSchCmnTpcRntiCb     *cb,
4000 uint8_t                     idx
4001 )
4002 #else
4003 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx)
4004 RgSchCmnTpcRntiCb     *cb;
4005 uint8_t                     idx;
4006 #endif
4007 {
4008    CmLList           *lnk;
4009
4010    for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
4011    {
4012       RgSchUeCb             *ue = (RgSchUeCb *)lnk->node;
4013       RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
4014       if (uePwr->puschIdx == idx)
4015       {
4016          return RFAILED;
4017       }
4018    }
4019    return ROK;
4020 }
4021
4022 /***********************************************************
4023  *
4024  *     Func : rgSCHPwrChkTpcRntiIdx
4025  *
4026  *     Desc : Validate index against format type of TPC RNTI.
4027  *
4028  *     Ret  :
4029  *
4030  *     Notes:
4031  *
4032  *     File :
4033  *
4034  **********************************************************/
4035 #ifdef ANSI
4036 PRIVATE S16 rgSCHPwrChkTpcRntiIdx
4037 (
4038 RgSchCmnTpcRntiCb     *cb,
4039 uint8_t                     idx
4040 )
4041 #else
4042 PRIVATE S16 rgSCHPwrChkTpcRntiIdx(cb, idx)
4043 RgSchCmnTpcRntiCb     *cb;
4044 uint8_t                     idx;
4045 #endif
4046 {
4047    if (cb->isFmt3a)
4048    {
4049       if (idx >= TFU_MAX_1BIT_TPC)
4050       {
4051          return RFAILED;
4052       }
4053    }
4054    else
4055    {
4056       if (idx >= TFU_MAX_2BIT_TPC)
4057       {
4058          return RFAILED;
4059       }
4060    }
4061    return ROK;
4062 }
4063 /* Warning Fix: Commenting out as not used */
4064
4065 /***********************************************************
4066  *
4067  *     Func : rgSCHPwrGetPCMaxValFromPCMax
4068  *
4069  *     Desc : Returns the power headroom in dB
4070  *            corresponding to a power headroom
4071  *            report
4072  *
4073  *     Ret  : S8
4074  *
4075  *     Notes:
4076  *
4077  *     File :
4078  *
4079  **********************************************************/
4080 #ifdef ANSI
4081 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax
4082 (
4083 uint8_t                    pCMax
4084 )
4085 #else
4086 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax(pCMax)
4087 uint8_t                    pCMax;
4088 #endif
4089 {
4090    return ((pCMax & 63) - 30);
4091 }
4092
4093
4094
4095 /***********************************************************
4096  *
4097  *     Func : rgSCHPwrGetPhValFromPhr
4098  *
4099  *     Desc : Returns the power headroom in dB
4100  *            corresponding to a power headroom
4101  *            report
4102  *
4103  *     Ret  : S8
4104  *
4105  *     Notes:
4106  *
4107  *     File :
4108  *
4109  **********************************************************/
4110 #ifdef ANSI
4111 PRIVATE S8 rgSCHPwrGetPhValFromPhr
4112 (
4113 uint8_t                    phr
4114 )
4115 #else
4116 PRIVATE S8 rgSCHPwrGetPhValFromPhr(phr)
4117 uint8_t                    phr;
4118 #endif
4119 {
4120    return ((phr & 63) - 23);
4121 }
4122
4123
4124 \f
4125 /**********************************************************************
4126  
4127          End of file
4128 **********************************************************************/