* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fapi_5g / source / api / fapi2phy / p5 / nr5g_fapi_proc_config_req.c
1 /******************************************************************************
2 *   Copyright (c) 2021 Intel.
3 *
4 *   Licensed under the Apache License, Version 2.0 (the "License");
5 *   you may not use this file except in compliance with the License.
6 *   You may obtain a copy of the License at
7 *
8 *       http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *   Unless required by applicable law or agreed to in writing, software
11 *   distributed under the License is distributed on an "AS IS" BASIS,
12 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *   See the License for the specific language governing permissions and
14 *   limitations under the License.
15 *
16 *******************************************************************************/
17
18 /**
19  * @file
20  * This file consist of implementation of FAPI CONFIG.request message.
21  *
22  **/
23
24 #include "nr5g_mac_phy_api.h"
25 #include "nr5g_fapi_framework.h"
26 #include "nr5g_fapi_fapi2mac_api.h"
27 #include "nr5g_fapi_fapi2phy_api.h"
28 #include "nr5g_fapi_fapi2phy_p5_proc.h"
29 #include "nr5g_fapi_fapi2phy_p5_pvt_proc.h"
30 #include "nr5g_fapi_memory.h"
31
32  /** @ingroup group_source_api_p5_fapi2phy_proc
33  *
34  *  @param[in]  p_phy_instance Pointer to PHY instance.
35  *  @param[in]  p_fapi_req Pointer to FAPI CONFIG.request message structure.
36  *  @param[in]  p_fapi_vendor_msg Pointer to FAPI vendor message structure.
37  *  @return     Returns ::SUCCESS and ::FAILURE.
38  *
39  *  @description
40  *  This message instructs how the PHY should be configured.
41  *
42  *  The *carrier_aggregation_level* parameter is a vendor specific 
43  *  configuration and programmed through Vendor Specific Message structure 
44  *  ::fapi_config_req_vendor_msg_t 
45  *
46 **/
47 uint8_t nr5g_fapi_config_request(
48     bool is_urllc,
49     p_nr5g_fapi_phy_instance_t p_phy_instance,
50     fapi_config_req_t * p_fapi_req,
51     fapi_vendor_msg_t * p_fapi_vendor_msg)
52 {
53     PCONFIGREQUESTStruct p_ia_config_req;
54     PMAC2PHY_QUEUE_EL p_list_elem;
55     nr5g_fapi_stats_t *p_stats;
56
57 #ifndef DEBUG_MODE
58     /* Below print is for better logging on console in radio mode. */
59     NR5G_FAPI_LOG(INFO_LOG, (""));
60 #endif
61
62     if (NULL == p_phy_instance) {
63         NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Invalid " "phy instance"));
64         return FAILURE;
65     }
66     p_stats = &p_phy_instance->stats;
67     p_stats->fapi_stats.fapi_config_req++;
68
69     if (NULL == p_fapi_req) {
70         NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Invalid fapi " "message"));
71         return FAILURE;
72     }
73
74     if (NULL == p_fapi_vendor_msg) {
75         NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Invalid fapi "
76                 "vendor message"));
77         return FAILURE;
78     }
79
80     if (FAPI_STATE_RUNNING == p_phy_instance->state) {
81         NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Message not "
82                 "supported by PHY in Running State"));
83         return FAILURE;
84     }
85
86     p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
87         MSG_TYPE_PHY_CONFIG_REQ, 1, (uint32_t) sizeof(CONFIGREQUESTStruct));
88     if (!p_list_elem) {
89         NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Unable to create "
90                 "list element. Out of memory!!!"));
91         return FAILURE;
92     }
93
94     p_ia_config_req = (PCONFIGREQUESTStruct) (p_list_elem + 1);
95     NR5G_FAPI_MEMSET(p_ia_config_req, sizeof(CONFIGREQUESTStruct), 0,
96         sizeof(CONFIGREQUESTStruct));
97     p_ia_config_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_CONFIG_REQ;
98     p_ia_config_req->sMsgHdr.nMessageLen =
99         (uint16_t) sizeof(CONFIGREQUESTStruct);
100     p_ia_config_req->nCarrierIdx = p_phy_instance->phy_id;
101
102     nr5g_fapi_config_req_to_phy_translation(p_phy_instance, p_fapi_req,
103         p_ia_config_req);
104     /* Vendor Parameters */
105     if (p_fapi_vendor_msg) {
106         p_ia_config_req->nCarrierAggregationLevel =
107             p_fapi_vendor_msg->config_req_vendor.carrier_aggregation_level;
108         p_ia_config_req->nGroupHopFlag =
109             p_fapi_vendor_msg->config_req_vendor.group_hop_flag;
110         p_ia_config_req->nSequenceHopFlag =
111             p_fapi_vendor_msg->config_req_vendor.sequence_hop_flag;
112         p_ia_config_req->nHoppingId =
113             p_fapi_vendor_msg->config_req_vendor.hopping_id;
114         p_ia_config_req->nUrllcCapable =
115             p_fapi_vendor_msg->config_req_vendor.urllc_capable;
116         p_ia_config_req->nUrllcMiniSlotMask =
117             p_fapi_vendor_msg->config_req_vendor.urllc_mini_slot_mask;
118         p_ia_config_req->nPrachNrofRxRU =
119             p_fapi_vendor_msg->config_req_vendor.prach_nr_of_rx_ru;
120         p_ia_config_req->nNrOfDLPorts =
121             p_fapi_vendor_msg->config_req_vendor.nr_of_dl_ports;
122         p_ia_config_req->nNrOfULPorts =
123             p_fapi_vendor_msg->config_req_vendor.nr_of_ul_ports;
124         p_ia_config_req->nSSBSubcSpacing =
125             p_fapi_vendor_msg->config_req_vendor.ssb_subc_spacing;
126         p_phy_instance->phy_config.use_vendor_EpreXSSB =
127             p_fapi_vendor_msg->config_req_vendor.use_vendor_EpreXSSB;
128     }
129
130     p_ia_config_req->nDLFftSize =
131         nr5g_fapi_calc_fft_size(p_ia_config_req->nSubcCommon,
132         p_ia_config_req->nDLBandwidth);
133     p_ia_config_req->nULFftSize =
134         nr5g_fapi_calc_fft_size(p_ia_config_req->nSubcCommon,
135         p_ia_config_req->nULBandwidth);
136
137     /* Add element to send list */
138     nr5g_fapi_fapi2phy_add_to_api_list(is_urllc, p_list_elem);
139
140     p_stats->iapi_stats.iapi_config_req++;
141     NR5G_FAPI_LOG(INFO_LOG, ("[CONFIG.request][%d]", p_phy_instance->phy_id));
142     return SUCCESS;
143 }
144
145  /** @ingroup group_source_api_p5_fapi2phy_proc
146  *
147  *  @param[in]  p_phy_instance Pointer to PHY instance.
148  *  @param[in]  p_fapi_req Pointer to FAPI CONFIG.request structure.
149  *  @param[in]  p_ia_config_req Pointer to IAPI CONFIG.request structure.
150  *  
151  *  @return     Returns ::SUCCESS and ::FAILURE.
152  *
153  *  @description
154  *  This function converts FAPI CONFIG.request TLVs to IAPI Config.request
155  *  structure.
156  *
157 **/
158 uint8_t nr5g_fapi_config_req_to_phy_translation(
159     p_nr5g_fapi_phy_instance_t p_phy_instance,
160     fapi_config_req_t * p_fapi_req,
161     PCONFIGREQUESTStruct p_ia_config_req)
162 {
163     fapi_uint32_tlv_t *tlvs = p_fapi_req->tlvs;
164     uint32_t i = 0, j = 0, k = 0;
165     uint32_t ss_pbch_power = 0;
166     uint32_t mib = 0;
167     uint32_t n_ssb_mask_idx = 0;
168     uint32_t n_beamid_idx = 0;
169     SLOTCONFIGStruct *p_sslot_Config = NULL;
170
171     while (i < p_fapi_req->number_of_tlvs) {
172         switch (tlvs[i].tl.tag) {
173             /***** Carrier Config *****/
174             case FAPI_DL_BANDWIDTH_TAG:
175                 p_ia_config_req->nDLBandwidth =
176                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
177                 ++i;
178                 break;
179
180             case FAPI_DL_FREQUENCY_TAG:
181                 p_ia_config_req->nDLAbsFrePointA = tlvs[i].value;
182                 ++i;
183                 break;
184
185                 /* FAPI_DL_K0_TAG - NA */
186                 /* FAPI_DL_GRIDSIZE_TAG - NA */
187
188             case FAPI_NUM_TX_ANT_TAG:
189                 p_ia_config_req->nNrOfTxAnt =
190                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
191                 ++i;
192                 break;
193
194             case FAPI_UPLINK_BANDWIDTH_TAG:
195                 p_ia_config_req->nULBandwidth =
196                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
197                 ++i;
198                 break;
199
200             case FAPI_UPLINK_FREQUENCY_TAG:
201                 p_ia_config_req->nULAbsFrePointA = tlvs[i].value;
202                 ++i;
203                 break;
204
205                 /* FAPI_UL_K0_TAG - NA */
206                 /* FAPI_UL_GRIDSIZE_TAG - NA */
207
208             case FAPI_NUM_RX_ANT_TAG:
209                 p_phy_instance->phy_config.n_nr_of_rx_ant =
210                     p_ia_config_req->nNrOfRxAnt =
211                         GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
212                 ++i;
213                 break;
214
215                 /* FAPI_FREQUENCY_SHIFT_7P5_KHZ_TAG - NA */
216
217             /***** Cell Config *****/
218             case FAPI_PHY_CELL_ID_TAG:
219                 p_phy_instance->phy_config.phy_cell_id =
220                     p_ia_config_req->nPhyCellId =
221                         GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
222                 ++i;
223                 break;
224
225             case FAPI_FRAME_DUPLEX_TYPE_TAG:
226                 p_ia_config_req->nFrameDuplexType =
227                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
228                 ++i;
229                 break;
230
231             /***** SSB Config *****/
232             case FAPI_SS_PBCH_POWER_TAG:
233                 ss_pbch_power = tlvs[i++].value;
234                 if (0 == ss_pbch_power) {
235                     p_ia_config_req->nSSBPwr = 1;
236                 } else if (54002 == ss_pbch_power) {
237                     p_ia_config_req->nSSBPwr = 20000;
238                 } else {
239                     p_ia_config_req->nSSBPwr = ss_pbch_power - 54000;
240                 }
241                 break;
242
243                 /* FAPI_BCH_PAYLOAD_TAG - NA */
244
245             case FAPI_SCS_COMMON_TAG:
246                 p_ia_config_req->nSubcCommon =
247                     p_ia_config_req->nSSBSubcSpacing =
248                     p_phy_instance->phy_config.sub_c_common =
249                         GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
250                 ++i;
251                 break;
252
253             /***** PRACH Config *****/
254             case FAPI_PRACH_SUBC_SPACING_TAG:
255                 p_ia_config_req->nPrachSubcSpacing =
256                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
257                 ++i;
258                 break;
259
260             case FAPI_RESTRICTED_SET_CONFIG_TAG:
261                 p_ia_config_req->nPrachRestrictSet =
262                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
263                 ++i;
264                 break;
265
266             case FAPI_NUM_PRACH_FD_OCCASIONS_TAG:
267                 p_ia_config_req->nPrachFdm =
268                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
269                 ++i;
270                 break;
271
272             case FAPI_PRACH_CONFIG_INDEX_TAG:
273                 p_ia_config_req->nPrachConfIdx =
274                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
275                 ++i;
276                 break;
277
278             case FAPI_PRACH_ROOT_SEQUENCE_INDEX_TAG:
279                 p_ia_config_req->nPrachRootSeqIdx =
280                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
281                 ++i;
282                 break;
283
284             case FAPI_K1_TAG:
285                 p_ia_config_req->nPrachFreqStart =
286                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
287                 ++i;
288                 break;
289
290             case FAPI_PRACH_ZERO_CORR_CONF_TAG:
291                 p_ia_config_req->nPrachZeroCorrConf =
292                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
293                 ++i;
294                 break;
295
296             case FAPI_SSB_PER_RACH_TAG:
297                 p_ia_config_req->nPrachSsbRach =
298                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
299                 ++i;
300                 break;
301             /***** SSB Table *****/
302             case FAPI_SSB_OFFSET_POINT_A_TAG:
303                 p_ia_config_req->nSSBPrbOffset =
304                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length) /
305                         (pow(2, p_ia_config_req->nSubcCommon));
306                 ++i;
307                 break;
308
309             case FAPI_SSB_PERIOD_TAG:
310                 p_ia_config_req->nSSBPeriod =
311                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
312                 ++i;
313                 break;
314
315             case FAPI_SSB_SUBCARRIER_OFFSET_TAG:
316                 p_ia_config_req->nSSBSubcOffset =
317                     (tlvs[i].value >> tlvs[i].tl.length);
318                 ++i;
319                 break;
320
321             case FAPI_MIB_TAG:
322                 mib = tlvs[i++].value;
323                 p_ia_config_req->nMIB[0] = (uint8_t) (mib >> 24);
324                 p_ia_config_req->nMIB[1] = (uint8_t) (mib >> 16);
325                 p_ia_config_req->nMIB[2] = (uint8_t) (mib >> 8);
326                 break;
327
328             case FAPI_DMRS_TYPE_A_POS_TAG:
329                 p_ia_config_req->nDMRSTypeAPos =
330                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
331                 ++i;
332                 break;
333
334             case FAPI_SSB_MASK_TAG:
335                 if (n_ssb_mask_idx < 2) {
336                     p_ia_config_req->nSSBMask[n_ssb_mask_idx++] =
337                         tlvs[i].value;
338                     ++i;
339                 }
340                 break;
341
342             case FAPI_BEAM_ID_TAG:
343                 if (n_beamid_idx < MAX_NUM_ANT_NR5G) {
344                     p_ia_config_req->nBeamId[n_beamid_idx++] =
345                         GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
346                     ++i;
347                 }
348                 break;
349
350                 /* FAPI_SS_PBCH_MULTIPLE_CARRIERS_IN_A_BAND_TAG - NA */
351                 /* FAPI_MULTIPLE_CELLS_SS_PBCH_IN_A_CARRIER_TAG - NA */
352
353             /***** TDD Table *****/
354             case FAPI_TDD_PERIOD_TAG:
355                 p_ia_config_req->nTddPeriod =
356                     nr5g_fapi_calc_phy_tdd_period((uint8_t)
357                     GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length),
358                     p_ia_config_req->nSubcCommon);
359                 ++i;
360                 break;
361
362             case FAPI_SLOT_CONFIG_TAG:
363                 for (j = 0; j < p_ia_config_req->nTddPeriod; j++) {
364                     p_sslot_Config = &p_ia_config_req->sSlotConfig[j];
365                     for (k = 0; k < MAX_NUM_OF_SYMBOL_PER_SLOT; k++, i++) {
366                         p_sslot_Config->nSymbolType[k] =
367                             GETVLFRM32B(tlvs[i].value, tlvs[i].tl.length);
368                     }
369                 }
370                 break;
371
372             /***** Measurement Config *****/
373                 /* FAPI_RSSI_MEASUREMENT_TAG - NA */
374
375             /***** Beamforming Table *****/
376
377             /***** Precoding Table *****/
378             default:
379                 {
380                     NR5G_FAPI_LOG(ERROR_LOG, ("[CONFIG.request] Unsupported "
381                             "TLV tag : 0x%x", tlvs[i].tl.tag));
382                 }
383                 break;
384         }
385     }
386     nr5g_fapi_config_req_fill_dependent_fields(p_ia_config_req);
387     return SUCCESS;
388 }
389
390  /** @ingroup group_source_api_p5_fapi2phy_proc
391  *
392  *  @param[in,out]  p_ia_config_req Pointer to IAPI CONFIG.request structure.
393  *
394  *  @return     Returns ::SUCCESS and ::FAILURE.
395  *
396  *  @description
397  *  This function converts IAPI Config.request structure fields that depend on
398  *  others. The order ofLV 5G FAPI 222.10.02 - 3.3.2.1
399  *
400 **/
401 uint8_t nr5g_fapi_config_req_fill_dependent_fields(
402     PCONFIGREQUESTStruct p_ia_config_req)
403 {
404     if (0 == p_ia_config_req->nFrameDuplexType) { // FDD
405         p_ia_config_req->nTddPeriod = 0;
406     }
407
408     return SUCCESS;
409 }
410
411  /** @ingroup group_source_api_p5_fapi2phy_proc
412  *
413  *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
414  *  @param[in]  n_subc_common subcarrierSpacing for common.
415  *  
416  *  @return     IAPI *nTddPeriod*.
417  *
418  *  @description
419  *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
420  *  structure.
421  *
422 **/
423 uint8_t nr5g_fapi_calc_phy_tdd_period(
424     uint8_t fapi_tdd_period,
425     uint8_t n_subc_common)
426 {
427     switch (n_subc_common) {
428         case 0:
429             return
430                 nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_0
431                 (fapi_tdd_period);
432         case 1:
433             return
434                 nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_1
435                 (fapi_tdd_period);
436         case 2:
437             return
438                 nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_2
439                 (fapi_tdd_period);
440         case 3:
441             return
442                 nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_3
443                 (fapi_tdd_period);
444         default:
445             break;
446     }
447
448     return 0;
449 }
450
451  /** @ingroup group_source_api_p5_fapi2phy_proc
452  *
453  *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
454  *  
455  *  @return     IAPI *nTddPeriod*.
456  *
457  *  @description
458  *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
459  *  structure based on *subCarrierSpacingCommon - 0*.
460  *
461 **/
462 uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_0(
463     uint8_t fapi_tdd_period)
464 {
465     if (2 == fapi_tdd_period)
466         return 1;
467     else if (4 == fapi_tdd_period)
468         return 2;
469     else if (6 == fapi_tdd_period)
470         return 5;
471     else if (7 == fapi_tdd_period)
472         return 10;
473     else
474         return 0;
475
476     return 0;
477 }
478
479  /** @ingroup group_source_api_p5_fapi2phy_proc
480  *
481  *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
482  *  
483  *  @return     IAPI *nTddPeriod*.
484  *
485  *  @description
486  *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
487  *  structure based on *subCarrierSpacingCommon - 1*.
488  *
489 **/
490 uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_1(
491     uint8_t fapi_tdd_period)
492 {
493     if (0 == fapi_tdd_period)
494         return 1;
495     else if (2 == fapi_tdd_period)
496         return 2;
497     else if (4 == fapi_tdd_period)
498         return 4;
499     else if (5 == fapi_tdd_period)
500         return 5;
501     else if (6 == fapi_tdd_period)
502         return 10;
503     else if (7 == fapi_tdd_period)
504         return 20;
505     else
506         return 0;
507
508     return 0;
509 }
510
511  /** @ingroup group_source_api_p5_fapi2phy_proc
512  *
513  *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
514  *  
515  *  @return     IAPI *nTddPeriod*.
516  *
517  *  @description
518  *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
519  *  structure based on *subCarrierSpacingCommon - 2*.
520  *
521 **/
522 uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_2(
523     uint8_t fapi_tdd_period)
524 {
525     if (0 == fapi_tdd_period)
526         return 2;
527     else if (2 == fapi_tdd_period)
528         return 4;
529     else if (3 == fapi_tdd_period)
530         return 5;
531     else if (4 == fapi_tdd_period)
532         return 8;
533     else if (5 == fapi_tdd_period)
534         return 10;
535     else if (6 == fapi_tdd_period)
536         return 20;
537     else if (7 == fapi_tdd_period)
538         return 40;
539     else
540         return 0;
541
542     return 0;
543 }
544
545  /** @ingroup group_source_api_p5_fapi2phy_proc
546  *
547  *  @param[in]  fapi_tdd_period DL UL Transmission Periodicity. 
548  *  
549  *  @return     IAPI *nTddPeriod*.
550  *
551  *  @description
552  *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
553  *  structure based on *subCarrierSpacingCommon - 3*.
554  *
555 **/
556 uint8_t nr5g_fapi_calc_phy_tdd_period_for_n_subc_common_3(
557     uint8_t fapi_tdd_period)
558 {
559     if (0 == fapi_tdd_period)
560         return 4;
561     else if (1 == fapi_tdd_period)
562         return 5;
563     else if (2 == fapi_tdd_period)
564         return 8;
565     else if (3 == fapi_tdd_period)
566         return 10;
567     else if (4 == fapi_tdd_period)
568         return 16;
569     else if (5 == fapi_tdd_period)
570         return 20;
571     else if (6 == fapi_tdd_period)
572         return 40;
573     else if (7 == fapi_tdd_period)
574         return 80;
575     else
576         return 0;
577
578     return 0;
579 }
580
581  /** @ingroup group_source_api_p5_fapi2phy_proc
582  *
583  *  @param[in]  nSubcCommon  Sub carrier spacing
584  *  @param[in]  nDLBandwidth/ nULBandwidth  Sub carrier spacing
585  *  
586  *  
587  *  @return     IAPI FFT size for DL UL
588  *
589  *  @description
590  *  This function converts FAPI *TddPeriod* to IAPI *nTddPeriod* 
591  *  structure based on *subCarrierSpacingCommon - 3*.
592  *
593 **/
594 uint16_t nr5g_fapi_calc_fft_size(
595     uint8_t sub_carrier_common,
596     uint16_t bw)
597 {
598     if (FAPI_SUBCARRIER_SPACING_15 == sub_carrier_common) {
599         if (FAPI_BANDWIDTH_5_MHZ == bw)
600             return FAPI_FFT_SIZE_512;
601         else if (FAPI_BANDWIDTH_10_MHZ == bw)
602             return FAPI_FFT_SIZE_1024;
603         else if ((FAPI_BANDWIDTH_15_MHZ == bw) || (FAPI_BANDWIDTH_20_MHZ == bw))
604             return FAPI_FFT_SIZE_2048;
605         else if ((FAPI_BANDWIDTH_25_MHZ == bw) || (FAPI_BANDWIDTH_30_MHZ == bw)
606             || (FAPI_BANDWIDTH_40_MHZ == bw) || (FAPI_BANDWIDTH_50_MHZ == bw))
607             return FAPI_FFT_SIZE_4096;
608     } else if (FAPI_SUBCARRIER_SPACING_30 == sub_carrier_common) {
609         if ((FAPI_BANDWIDTH_5_MHZ == bw) || (FAPI_BANDWIDTH_10_MHZ == bw))
610             return FAPI_FFT_SIZE_512;
611         else if ((FAPI_BANDWIDTH_15_MHZ == bw) || (FAPI_BANDWIDTH_20_MHZ == bw))
612             return FAPI_FFT_SIZE_1024;
613         else if ((FAPI_BANDWIDTH_25_MHZ == bw) || (FAPI_BANDWIDTH_30_MHZ == bw)
614             || (FAPI_BANDWIDTH_40_MHZ == bw) || (FAPI_BANDWIDTH_50_MHZ == bw))
615             return FAPI_FFT_SIZE_2048;
616         else if ((FAPI_BANDWIDTH_60_MHZ == bw) || (FAPI_BANDWIDTH_70_MHZ == bw)
617             || (FAPI_BANDWIDTH_80_MHZ == bw) || ((FAPI_BANDWIDTH_90_MHZ == bw))
618             || (FAPI_BANDWIDTH_100_MHZ == bw))
619             return FAPI_FFT_SIZE_4096;
620     } else if (FAPI_SUBCARRIER_SPACING_60 == sub_carrier_common) {
621         if ((FAPI_BANDWIDTH_10_MHZ == bw) || (FAPI_BANDWIDTH_15_MHZ == bw) ||
622             (FAPI_BANDWIDTH_20_MHZ == bw) || (FAPI_BANDWIDTH_25_MHZ == bw))
623             return FAPI_FFT_SIZE_512;
624         else if ((FAPI_BANDWIDTH_30_MHZ == bw) || (FAPI_BANDWIDTH_40_MHZ == bw)
625             || (FAPI_BANDWIDTH_50_MHZ == bw))
626             return FAPI_FFT_SIZE_1024;
627         else if ((FAPI_BANDWIDTH_60_MHZ == bw) || (FAPI_BANDWIDTH_70_MHZ == bw)
628             || (FAPI_BANDWIDTH_80_MHZ == bw) || (FAPI_BANDWIDTH_90_MHZ == bw) ||
629             (FAPI_BANDWIDTH_100_MHZ == bw))
630             return FAPI_FFT_SIZE_2048;
631         else if (FAPI_BANDWIDTH_200_MHZ == bw)
632             return FAPI_FFT_SIZE_4096;
633     } else if (FAPI_SUBCARRIER_SPACING_120 == sub_carrier_common) {
634         if (FAPI_BANDWIDTH_50_MHZ == bw)
635             return FAPI_FFT_SIZE_512;
636         else if (FAPI_BANDWIDTH_100_MHZ == bw)
637             return FAPI_FFT_SIZE_1024;
638         else if (FAPI_BANDWIDTH_200_MHZ == bw)
639             return FAPI_FFT_SIZE_2048;
640         else if (FAPI_BANDWIDTH_400_MHZ == bw)
641             return FAPI_FFT_SIZE_4096;
642     } else {
643     }
644
645     return 0;
646 }