1 /** @file mlan_cfp.c
2 *
3 * @brief This file provides WLAN client mode channel, frequency and power related code
4 *
5 * Copyright 2008-2024 NXP
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
11 /*************************************************************
12 Change Log:
13 04/16/2009: initial version
14 ************************************************************/
15 #include <mlan_api.h>
16
17 /* Additional WMSDK header files */
18 #include <wmerrno.h>
19 #include <osa.h>
20
21 /* Always keep this include at the end of all include files */
22 #include <mlan_remap_mem_operations.h>
23 /********************************************************
24 Local Variables
25 ********************************************************/
26
27 /** 100mW */
28 #define WLAN_TX_PWR_DEFAULT 20
29 /** 100mW */
30 #define WLAN_TX_PWR_US_DEFAULT 20
31 /** 100mW */
32 #define WLAN_TX_PWR_JP_BG_DEFAULT 20
33 /** 200mW */
34 #define WLAN_TX_PWR_JP_A_DEFAULT 23
35 /** 100mW */
36 #define WLAN_TX_PWR_FR_100MW 20
37 /** 10mW */
38 #define WLAN_TX_PWR_FR_10MW 10
39 /** 100mW */
40 #define WLAN_TX_PWR_EMEA_DEFAULT 20
41 /** 200mW */
42 #define WLAN_TX_PWR_200MW 23
43 /** 2000mW */
44 #define WLAN_TX_PWR_CN_2000MW 33
45 #if defined(RW610)
46 /** 22dBm */
47 #define WLAN_TX_PWR_WW_DEFAULT 22
48 #else
49 /** 8dBm */
50 #define WLAN_TX_PWR_WW_DEFAULT 8
51 #endif
52 /** Region code mapping */
53 typedef struct _country_code_mapping
54 {
55 /** Region */
56 t_u8 country_code[COUNTRY_CODE_LEN];
57 /** Code for B/G CFP table */
58 t_u8 cfp_code_bg;
59 /** Code for A CFP table */
60 t_u8 cfp_code_a;
61 } country_code_mapping_t;
62
63 static const country_code_mapping_t country_code_mapping[] = {
64 {"WW", 0x00, 0x00}, /* World Wide Safe */
65 {"US", 0x10, 0x10}, /* US FCC */
66 {"CA", 0x10, 0x20}, /* IC Canada */
67 {"SG", 0x10, 0x10}, /* Singapore */
68 {"EU", 0x30, 0x30}, /* ETSI */
69 {"AU", 0x30, 0x30}, /* Australia */
70 {"KR", 0x30, 0x30}, /* Republic Of Korea */
71 {"FR", 0x32, 0x32}, /* France */
72 {"JP", 0xFF, 0x40}, /* Japan */
73 {"CN", 0x30, 0x50}, /* China */
74 };
75
76 #define COUNTRY_ID_US 0
77 #define COUNTRY_ID_JP 1
78 #define COUNTRY_ID_CN 2
79 #define COUNTRY_ID_EU 3
80
81 typedef struct _oper_bw_chan
82 {
83 /*non-global operating class*/
84 t_u8 oper_class;
85 /*global operating class*/
86 t_u8 global_oper_class;
87 /*bandwidth 0-20M 1-40M 2-80M 3-160M*/
88 t_u8 bandwidth;
89 /*channel list*/
90 t_u8 channel_list[13];
91 } oper_bw_chan;
92
93 /** oper class table for US*/
94 static oper_bw_chan oper_bw_chan_us[] = {
95 /** non-Global oper class, global oper class, bandwidth, channel list*/
96 {1, 115, 0, {36, 40, 44, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
97 {2, 118, 0, {52, 56, 60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
98 {3, 124, 0, {149, 153, 157, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
99 {4, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 0}},
100 {5, 125, 0, {149, 153, 157, 161, 165, 0, 0, 0, 0, 0, 0, 0, 0}},
101 {12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0}},
102 {22, 116, 1, {36, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
103 {23, 119, 1, {52, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
104 {24, 122, 1, {100, 108, 116, 124, 132, 140, 0, 0, 0, 0, 0, 0, 0}},
105 {25, 126, 1, {149, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
106 {26, 126, 1, {149, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
107 {27, 117, 1, {40, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
108 {28, 120, 1, {56, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
109 {29, 123, 1, {104, 112, 120, 128, 136, 144, 0, 0, 0, 0, 0, 0, 0}},
110 {30, 127, 1, {153, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
111 {31, 127, 1, {153, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
112 {32, 83, 1, {1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0}},
113 {33, 84, 1, {5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0}},
114 #if CONFIG_11AC
115 {128, 128, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
116 {129, 129, 3, {50, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
117 {130, 130, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
118 #endif
119 };
120
121 /** oper class table for EU*/
122 static oper_bw_chan oper_bw_chan_eu[] = {
123 /** non-global oper class,global oper class, bandwidth, channel list*/
124 {1, 115, 0, {36, 40, 44, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
125 {2, 118, 0, {52, 56, 60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
126 {3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0, 0}},
127 {4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
128 {5, 116, 1, {36, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
129 {6, 119, 1, {52, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
130 {7, 122, 1, {100, 108, 116, 124, 132, 0, 0, 0, 0, 0, 0, 0, 0}},
131 {8, 117, 1, {40, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
132 {9, 120, 1, {56, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
133 {10, 123, 1, {104, 112, 120, 128, 136, 0, 0, 0, 0, 0, 0, 0, 0}},
134 {11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0}},
135 {12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0}},
136 {17, 125, 0, {149, 153, 157, 161, 165, 169, 0, 0, 0, 0, 0, 0, 0}},
137 #if CONFIG_11AC
138 {128, 128, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
139 {129, 129, 3, {50, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
140 {130, 130, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
141 #endif
142 };
143
144 /** oper class table for Japan*/
145 static oper_bw_chan oper_bw_chan_jp[] = {
146 /** non-Global oper class,global oper class, bandwidth, channel list*/
147 {1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48, 0, 0, 0, 0, 0}},
148 {30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
149 {31, 82, 0, {14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
150 {32, 118, 0, {52, 56, 60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
151 {33, 118, 0, {52, 56, 60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
152 {34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0, 0}},
153 {35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0, 0}},
154 {36, 116, 1, {36, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
155 {37, 119, 1, {52, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
156 {38, 119, 1, {52, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
157 {39, 122, 1, {100, 108, 116, 124, 132, 0, 0, 0, 0, 0, 0, 0, 0}},
158 {40, 122, 1, {100, 108, 116, 124, 132, 0, 0, 0, 0, 0, 0, 0, 0}},
159 {41, 117, 1, {40, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
160 {42, 120, 1, {56, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
161 {43, 120, 1, {56, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
162 {44, 123, 1, {104, 112, 120, 128, 136, 0, 0, 0, 0, 0, 0, 0, 0}},
163 {45, 123, 1, {104, 112, 120, 128, 136, 0, 0, 0, 0, 0, 0, 0, 0}},
164 {56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0}},
165 {57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0}},
166 {58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0, 0}},
167 #if CONFIG_11AC
168 {128, 128, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
169 {129, 129, 3, {50, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
170 {130, 130, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
171 #endif
172 };
173
174 /** oper class table for China*/
175 static oper_bw_chan oper_bw_chan_cn[] = {
176 /** non-Global oper class,global oper class, bandwidth, channel list*/
177 {1, 115, 0, {36, 40, 44, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
178 {2, 118, 0, {52, 56, 60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
179 {3, 125, 0, {149, 153, 157, 161, 165, 0, 0, 0, 0, 0, 0, 0, 0}},
180 {4, 116, 1, {36, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
181 {5, 119, 1, {52, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
182 {6, 126, 1, {149, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
183 {7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
184 {8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0}},
185 {9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0}},
186 #if CONFIG_11AC
187 {128, 128, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
188 {129, 129, 3, {50, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
189 {130, 130, 2, {42, 58, 106, 122, 138, 155, 0, 0, 0, 0, 0, 0, 0}},
190 #endif
191 };
192
193 /** Country code for ETSI */
194 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
195 "AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "MK",
196 "DE", "GR", "HU", "IS", "IE", "IT", "KR", "LV", "LI", "LT", "LU", "MT", "MD", "MC", "ME", "NL",
197 "NO", "PL", "RO", "RU", "SM", "RS", "SI", "SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NZ"};
198
199 /**
200 * The structure for Channel-Frequency-Power table
201 */
202 typedef struct _cfp_table
203 {
204 /** Region or Code */
205 t_u8 code;
206 /** Frequency/Power */
207 const chan_freq_power_t *cfp;
208 /** No of CFP flag */
209 int cfp_no;
210 } cfp_table_t;
211
212 /* Format { Channel, Frequency (MHz), MaxTxPower } */
213 /** Band: 'B/G', Region: USA FCC/Canada IC */
214 static const chan_freq_power_t channel_freq_power_US_BG[] = {
215 {1, 2412, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {2, 2417, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
216 {3, 2422, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {4, 2427, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
217 {5, 2432, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {6, 2437, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
218 {7, 2442, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {8, 2447, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
219 {9, 2452, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {10, 2457, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
220 {11, 2462, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}};
221
222 /** Band: 'B/G', Region: Europe ETSI/China */
223 static const chan_freq_power_t channel_freq_power_EU_BG[] = {
224 {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
225 {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
226 {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
227 {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
228 {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
229 {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
230 {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}};
231
232 /** Band: 'B/G', Region: France */
233 static const chan_freq_power_t channel_freq_power_FR_BG[] = {
234 {1, 2412, WLAN_TX_PWR_FR_100MW, (bool)MFALSE}, {2, 2417, WLAN_TX_PWR_FR_100MW, (bool)MFALSE},
235 {3, 2422, WLAN_TX_PWR_FR_100MW, (bool)MFALSE}, {4, 2427, WLAN_TX_PWR_FR_100MW, (bool)MFALSE},
236 {5, 2432, WLAN_TX_PWR_FR_100MW, (bool)MFALSE}, {6, 2437, WLAN_TX_PWR_FR_100MW, (bool)MFALSE},
237 {7, 2442, WLAN_TX_PWR_FR_100MW, (bool)MFALSE}, {8, 2447, WLAN_TX_PWR_FR_100MW, (bool)MFALSE},
238 {9, 2452, WLAN_TX_PWR_FR_100MW, (bool)MFALSE}, {10, 2457, WLAN_TX_PWR_FR_10MW, (bool)MFALSE},
239 {11, 2462, WLAN_TX_PWR_FR_10MW, (bool)MFALSE}, {12, 2467, WLAN_TX_PWR_FR_10MW, (bool)MFALSE},
240 {13, 2472, WLAN_TX_PWR_FR_10MW, (bool)MFALSE}};
241
242 /** Band: 'B/G', Region: Japan */
243 static const chan_freq_power_t channel_freq_power_JPN40_BG[] = {{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}};
244
245 /** Band : 'B/G', Region: Special */
246 static const chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
247 {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE},
248 {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE},
249 {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE},
250 {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE},
251 {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE},
252 {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE},
253 {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}, {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, (bool)MFALSE}};
254
255 /** Band : 'B/G', Region: World Wide Safe */
256 static chan_freq_power_t channel_freq_power_WW_BG[] = {
257 {1, 2412, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {2, 2417, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
258 {3, 2422, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {4, 2427, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
259 {5, 2432, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {6, 2437, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
260 {7, 2442, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {8, 2447, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
261 {9, 2452, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {10, 2457, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
262 {11, 2462, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {12, 2467, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
263 {13, 2472, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}};
264
265 /** Band : 'B/G', Region: Custom - Place holder for Max 14 channels (As defined in WWSM)*/
266 static chan_freq_power_t channel_freq_power_Custom_BG[] = {
267 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
268 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
269 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
270 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
271 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
272 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
273 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}};
274
275 static uint8_t rf_radio_modes_group[] = {
276 0, /* set the radio in power down mode */
277 /*1, sets the radio in 5GHz band, 2X2 mode(path A+B) */
278 3, /* sets the radio in 5GHz band, 1X1 mode(path A) */
279 /* 4, sets the radio in 5GHz band, 1X1 mode(path B) */
280 /* 9, sets the radio in 2.4GHz band, 2X2 mode(path A+B) */
281 11, /* sets the radio in 2.4GHz band, 1X1 mode(path A) */
282 /* 14, sets the radio in 2.4GHz band, 1X1 mode(path B)*/
283 };
284
285 /**
286 * The 2.4GHz CFP tables
287 */
288 static cfp_table_t cfp_table_BG[] = {
289 {
290 0x00, /* World Wide Safe */
291 (chan_freq_power_t *)channel_freq_power_WW_BG,
292 (int)(sizeof(channel_freq_power_WW_BG) / sizeof(chan_freq_power_t)),
293 },
294 {
295 0x10, /* US FCC */
296 (const chan_freq_power_t *)channel_freq_power_US_BG,
297 (int)(sizeof(channel_freq_power_US_BG) / sizeof(chan_freq_power_t)),
298 },
299 {
300 0x20, /* CANADA IC */
301 (const chan_freq_power_t *)channel_freq_power_US_BG,
302 (int)(sizeof(channel_freq_power_US_BG) / sizeof(chan_freq_power_t)),
303 },
304 {
305 0x30, /* EU */
306 (const chan_freq_power_t *)channel_freq_power_EU_BG,
307 (int)(sizeof(channel_freq_power_EU_BG) / sizeof(chan_freq_power_t)),
308 },
309 {
310 0x32, /* FRANCE */
311 (const chan_freq_power_t *)channel_freq_power_FR_BG,
312 (int)(sizeof(channel_freq_power_FR_BG) / sizeof(chan_freq_power_t)),
313 },
314 {
315 0x40, /* JAPAN */
316 (const chan_freq_power_t *)channel_freq_power_JPN40_BG,
317 (int)(sizeof(channel_freq_power_JPN40_BG) / sizeof(chan_freq_power_t)),
318 },
319 {
320 0x50, /* China */
321 (const chan_freq_power_t *)channel_freq_power_EU_BG,
322 (int)(sizeof(channel_freq_power_EU_BG) / sizeof(chan_freq_power_t)),
323 },
324 {
325 0xff, /* Special */
326 (const chan_freq_power_t *)channel_freq_power_SPECIAL_BG,
327 (int)(sizeof(channel_freq_power_SPECIAL_BG) / sizeof(chan_freq_power_t)),
328 },
329 /* Add new region here */
330 };
331
332 /** Number of the CFP tables for 2.4GHz */
333 #define MLAN_CFP_TABLE_SIZE_BG (sizeof(cfp_table_BG) / sizeof(cfp_table_t))
334
335 #if CONFIG_5GHz_SUPPORT
336 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
337 /** Band: 'A', Region: USA FCC, Spain, France */
338 static const chan_freq_power_t channel_freq_power_A[] = {
339 {36, 5180, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {40, 5200, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
340 {44, 5220, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {48, 5240, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
341 {52, 5260, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {56, 5280, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
342 {60, 5300, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {64, 5320, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
343 {100, 5500, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {104, 5520, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
344 {108, 5540, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {112, 5560, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
345 {116, 5580, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {120, 5600, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
346 {124, 5620, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {128, 5640, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
347 {132, 5660, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {136, 5680, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
348 {140, 5700, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {144, 5720, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
349 {149, 5745, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {153, 5765, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
350 {157, 5785, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {161, 5805, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
351 {165, 5825, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
352 #if CONFIG_UNII4_BAND_SUPPORT
353 {169, 5845, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {173, 5865, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
354 {177, 5885, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
355 #endif
356 };
357
358 /** Band: 'A', Region: Canada IC */
359 static const chan_freq_power_t channel_freq_power_CAN_A[] = {
360 {36, 5180, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {40, 5200, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
361 {44, 5220, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {48, 5240, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
362 {52, 5260, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {56, 5280, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
363 {60, 5300, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {64, 5320, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
364 {100, 5500, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {104, 5520, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
365 {108, 5540, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {112, 5560, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
366 {116, 5580, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {132, 5660, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
367 {136, 5680, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE}, {140, 5700, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
368 #if CONFIG_11AC
369 {144, 5720, WLAN_TX_PWR_US_DEFAULT, (bool)MTRUE},
370 #endif
371 {149, 5745, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {153, 5765, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
372 {157, 5785, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}, {161, 5805, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE},
373 {165, 5825, WLAN_TX_PWR_US_DEFAULT, (bool)MFALSE}};
374
375 /** Band: 'A', Region: Europe ETSI */
376 static const chan_freq_power_t channel_freq_power_EU_A[] = {
377 {36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
378 {44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
379 {52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
380 {60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
381 {100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
382 {108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
383 {116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
384 {124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
385 {132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE},
386 {140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MTRUE}, {149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
387 {153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE},
388 {161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}, {165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, (bool)MFALSE}};
389
390 /** Band: 'A', Region: Japan */
391 static const chan_freq_power_t channel_freq_power_JPN_A[] = {
392 {36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MFALSE}, {40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MFALSE},
393 {44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MFALSE}, {48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MFALSE},
394 {52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
395 {60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
396 {100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
397 {108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
398 {116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
399 {124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
400 {132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE},
401 {140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}, {144, 5720, WLAN_TX_PWR_JP_A_DEFAULT, (bool)MTRUE}};
402
403 /** Band: 'A', Region: China */
404 static const chan_freq_power_t channel_freq_power_CN_A[] = {
405 {36, 5180, WLAN_TX_PWR_200MW, MFALSE}, {40, 5200, WLAN_TX_PWR_200MW, MFALSE},
406 {44, 5220, WLAN_TX_PWR_200MW, MFALSE}, {48, 5240, WLAN_TX_PWR_200MW, MFALSE},
407 {52, 5260, WLAN_TX_PWR_200MW, MTRUE}, {56, 5280, WLAN_TX_PWR_200MW, MTRUE},
408 {60, 5300, WLAN_TX_PWR_200MW, MTRUE}, {64, 5320, WLAN_TX_PWR_200MW, MTRUE},
409 {149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE}, {153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
410 {157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE}, {161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
411 {165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}};
412
413
414 /** Band: 'A', Region: World Wide Safe */
415 static chan_freq_power_t channel_freq_power_WW_A[] = {
416 {36, 5180, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {40, 5200, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
417 {44, 5220, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {48, 5240, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
418 {52, 5260, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {56, 5280, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
419 {60, 5300, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {64, 5320, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
420 {100, 5500, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {104, 5520, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
421 {108, 5540, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {112, 5560, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
422 {116, 5580, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {120, 5600, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
423 {124, 5620, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {128, 5640, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
424 {132, 5660, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {136, 5680, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
425 {140, 5700, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE}, {144, 5720, WLAN_TX_PWR_WW_DEFAULT, (bool)MTRUE},
426 {149, 5745, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {153, 5765, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
427 {157, 5785, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {161, 5805, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
428 {165, 5825, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}};
429
430 /** Band: 'A', Region: Custom - Place holder for Max 25 channels (As defined in WWSM) */
431 static chan_freq_power_t channel_freq_power_Custom_A[] = {
432 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
433 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
434 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
435 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
436 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
437 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
438 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
439 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
440 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
441 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
442 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
443 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
444 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
445 #if CONFIG_UNII4_BAND_SUPPORT
446 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE}, {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
447 {0, 0, WLAN_TX_PWR_WW_DEFAULT, (bool)MFALSE},
448 #endif
449 };
450
451 /** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
452 static const chan_freq_power_t channel_freq_power_low_band[] = {
453 {36, 5180, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
454 {40, 5200, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
455 {44, 5220, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
456 {48, 5240, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
457 };
458
459 /** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
460 static const chan_freq_power_t channel_freq_power_lower_middle_band[] = {
461 {52, 5260, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
462 {56, 5280, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
463 {60, 5300, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
464 {64, 5320, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
465 };
466
467 /** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
468 static const chan_freq_power_t channel_freq_power_upper_middle_band[] = {
469 {100, 5500, WLAN_TX_PWR_DEFAULT, (bool)MTRUE}, {104, 5520, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
470 {108, 5540, WLAN_TX_PWR_DEFAULT, (bool)MTRUE}, {112, 5560, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
471 {116, 5580, WLAN_TX_PWR_DEFAULT, (bool)MTRUE}, {120, 5600, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
472 {124, 5620, WLAN_TX_PWR_DEFAULT, (bool)MTRUE}, {128, 5640, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
473 {132, 5660, WLAN_TX_PWR_DEFAULT, (bool)MTRUE}, {136, 5680, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
474 {140, 5700, WLAN_TX_PWR_DEFAULT, (bool)MTRUE},
475 };
476
477 /** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
478 static const chan_freq_power_t channel_freq_power_high_band[] = {{149, 5745, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
479 {153, 5765, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
480 {157, 5785, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
481 {161, 5805, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
482 {165, 5825, WLAN_TX_PWR_DEFAULT, (bool)MFALSE}};
483
484 /** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
485 * High band (5725-5850 MHz) channels */
486 static const chan_freq_power_t channel_freq_power_low_high_band[] = {
487 {36, 5180, WLAN_TX_PWR_DEFAULT, (bool)MFALSE}, {40, 5200, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
488 {44, 5220, WLAN_TX_PWR_DEFAULT, (bool)MFALSE}, {48, 5240, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
489 {149, 5745, WLAN_TX_PWR_DEFAULT, (bool)MFALSE}, {153, 5765, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
490 {157, 5785, WLAN_TX_PWR_DEFAULT, (bool)MFALSE}, {161, 5805, WLAN_TX_PWR_DEFAULT, (bool)MFALSE},
491 {165, 5825, WLAN_TX_PWR_DEFAULT, (bool)MFALSE}};
492
493 /**
494 * The 5GHz CFP tables
495 */
496 static cfp_table_t cfp_table_A[] = {
497 {
498 0x00, /* World Wide Safe*/
499 (chan_freq_power_t *)channel_freq_power_WW_A,
500 (int)(sizeof(channel_freq_power_WW_A) / sizeof(chan_freq_power_t)),
501 },
502 {
503 0x10, /* US FCC */
504 (const chan_freq_power_t *)channel_freq_power_A,
505 (int)(sizeof(channel_freq_power_A) / sizeof(chan_freq_power_t)),
506 },
507 {
508 0x20, /* CANADA IC */
509 (const chan_freq_power_t *)channel_freq_power_CAN_A,
510 (int)(sizeof(channel_freq_power_CAN_A) / sizeof(chan_freq_power_t)),
511 },
512 {
513 0x30, /* EU */
514 (const chan_freq_power_t *)channel_freq_power_EU_A,
515 (int)(sizeof(channel_freq_power_EU_A) / sizeof(chan_freq_power_t)),
516 },
517 {
518 0x32, /* FRANCE */
519 (const chan_freq_power_t *)channel_freq_power_A,
520 (int)(sizeof(channel_freq_power_A) / sizeof(chan_freq_power_t)),
521 },
522 {
523 0x40, /* JAPAN */
524 (const chan_freq_power_t *)channel_freq_power_JPN_A,
525 (int)((int)(sizeof(channel_freq_power_JPN_A) / sizeof(chan_freq_power_t))),
526 },
527 {
528 0x50, /* China */
529 (const chan_freq_power_t *)channel_freq_power_CN_A,
530 (int)(sizeof(channel_freq_power_CN_A) / sizeof(chan_freq_power_t)),
531 },
532 {
533 0xff, /* Special */
534 (const chan_freq_power_t *)channel_freq_power_JPN_A,
535 (int)(sizeof(channel_freq_power_JPN_A) / sizeof(chan_freq_power_t)),
536 },
537 {0x1, /* Low band (5150-5250 MHz) channels */
538 (const chan_freq_power_t *)channel_freq_power_low_band,
539 (int)(sizeof(channel_freq_power_low_band) / sizeof(chan_freq_power_t))},
540 {0x2, /* Lower middle band (5250-5350 MHz) channels */
541 (const chan_freq_power_t *)channel_freq_power_lower_middle_band,
542 (int)(sizeof(channel_freq_power_lower_middle_band) / sizeof(chan_freq_power_t))},
543 {0x3, /* Upper middle band (5470-5725 MHz) channels */
544 (const chan_freq_power_t *)channel_freq_power_upper_middle_band,
545 (int)(sizeof(channel_freq_power_upper_middle_band) / sizeof(chan_freq_power_t))},
546 {0x4, /* High band (5725-5850 MHz) channels */
547 (const chan_freq_power_t *)channel_freq_power_high_band,
548 (int)(sizeof(channel_freq_power_high_band) / sizeof(chan_freq_power_t))},
549 {0x5, /* Low band (5150-5250 MHz) and High band (5725-5850 MHz) channels */
550 (const chan_freq_power_t *)channel_freq_power_low_high_band,
551 (int)(sizeof(channel_freq_power_low_high_band) / sizeof(chan_freq_power_t))},
552 /* Add new region here */
553 };
554
555 /** Number of the CFP tables for 5GHz */
556 #define MLAN_CFP_TABLE_SIZE_A (sizeof(cfp_table_A) / sizeof(cfp_table_t))
557
558 #endif /* CONFIG_5GHz_SUPPORT */
559
560 /********************************************************
561 Global Variables
562 ********************************************************/
563 /**
564 * The table to keep region code
565 */
566 t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {0x00, 0x10, 0x20, 0x30, 0x32, 0x40, 0x41, 0x50, 0xfe, 0xff};
567
568 /** The table to keep CFP code for A */
569 t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = {0x1, 0x2, 0x3, 0x4, 0x5};
570
571 /**
572 * The rates supported for ad-hoc B mode
573 */
574 t_u8 AdhocRates_B[B_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0};
575
576 /**
577 * The rates supported for ad-hoc G mode
578 */
579 t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0};
580
581 /**
582 * The rates supported for ad-hoc BG mode
583 */
584 t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0};
585
586 /**
587 * The rates supported in A mode for ad-hoc
588 */
589 t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0};
590
591 /**
592 * The rates supported in A mode (used for BAND_A)
593 */
594 t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0};
595
596 #if CONFIG_11N
597 /**
598 * The rates supported by the card
599 */
600 static t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
601 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, 0x0D,
602 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
603 0x10E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
605 #else
606 /**
607 * The rates supported by the card
608 */
609 t_u16 WlanDataRates[WLAN_SUPPORTED_RATES] = {0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60,
610 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
614 #endif
615
616 /**
617 * The rates supported in B mode
618 */
619 t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x16, 0};
620
621 /**
622 * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
623 */
624 t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0};
625
626 /**
627 * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
628 */
629 t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x0c, 0x12, 0x16, 0x18,
630 0x24, 0x30, 0x48, 0x60, 0x6c, 0};
631
632 /**
633 * The rates supported in N mode
634 */
635 t_u8 SupportedRates_N[N_SUPPORTED_RATES] = {0x02, 0x04, 0};
636
637 #if CONFIG_11AX
638 #define MCS_NUM_AX 12
639 /**
640 * for MCS0/MCS1/MCS3/MCS4 have 4 additional DCM=1 value
641 * note: the value in the table is 2 multiplier of the actual rate
642 */
643 static t_u16 ax_mcs_rate_nss1[12][MCS_NUM_AX + 4] = {
644 {0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481, 0x511, 0x5A1, 0x6C1, 0x781, 0x871,
645 0x962}, /*SG 160M*/
646 {0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440, 0x4C9, 0x551, 0x661, 0x716, 0x7F9,
647 0x8DC}, /*MG 160M*/
648 {0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E, 0x4C9, 0x5BE, 0x661, 0x72D,
649 0x7F9}, /*LG 160M*/
650 {0x48, 0x24, 0x90, 0x48, 0xD8, 0x120, 0x90, 0x1B0, 0xD8, 0x240, 0x288, 0x2D0, 0x360, 0x3C0, 0x438,
651 0x4B0}, /*SG 80M*/
652 {0x44, 0x22, 0x88, 0x44, 0xCC, 0x110, 0x88, 0x198, 0xCC, 0x220, 0x264, 0x2A8, 0x330, 0x38B, 0x3FC,
653 0x46E}, /*MG 80M*/
654 {0x3D, 0x1E, 0x7A, 0x3D, 0xB7, 0xF5, 0x7A, 0x16F, 0xB7, 0x1EA, 0x227, 0x264, 0x2DF, 0x330, 0x396, 0x3FC}, /*LG 80M*/
655 {0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135, 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 40M*/
656 {0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124, 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 40M*/
657 {0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107, 0x124, 0x15F, 0x186, 0x1B6, 0x1E7}, /*LG 40M*/
658 {0x11, 0x8, 0x22, 0x11, 0x33, 0x44, 0x22, 0x67, 0x33, 0x89, 0x9A, 0xAC, 0xCE, 0xE5, 0x102, 0x11E}, /*SG 20M*/
659 {0x10, 0x8, 0x20, 0x10, 0x30, 0x41, 0x20, 0x61, 0x30, 0x82, 0x92, 0xA2, 0xC3, 0xD8, 0xF3, 0x10E}, /*MG 20M*/
660 {0xE, 0x7, 0x1D, 0xE, 0x2B, 0x3A, 0x1D, 0x57, 0x2B, 0x75, 0x83, 0x92, 0xAF, 0xC3, 0xDB, 0xF3} /*LG 20M*/
661 };
662 #endif
663
664 /**
665 * @brief This function finds the CFP in
666 * cfp_table_BG/A based on region/code and band parameter.
667 *
668 * @param pmadapter A pointer to mlan_adapter structure
669 * @param region The region code
670 * @param band The band
671 * @param cfp_no A pointer to CFP number
672 *
673 * @return A pointer to CFP
674 */
wlan_get_region_cfp_table(pmlan_adapter pmadapter,t_u8 region,t_u16 band,int * cfp_no)675 const chan_freq_power_t *wlan_get_region_cfp_table(pmlan_adapter pmadapter, t_u8 region, t_u16 band, int *cfp_no)
676 {
677 t_u32 i;
678 t_u8 cfp_bg;
679 #if CONFIG_5GHz_SUPPORT
680 t_u8 cfp_a;
681 #endif /* CONFIG_5GHz_SUPPORT */
682
683 ENTER();
684
685 cfp_bg = region;
686 #if CONFIG_5GHz_SUPPORT
687 cfp_a = region;
688 #endif /* CONFIG_5GHz_SUPPORT */
689 if (region == 0U || region == 0x40)
690 {
691 /* Invalid region code or Japan case, use CFP code */
692 cfp_bg = pmadapter->cfp_code_bg;
693 #if CONFIG_5GHz_SUPPORT
694 cfp_a = pmadapter->cfp_code_a;
695 #endif /* CONFIG_5GHz_SUPPORT */
696 }
697
698 if ((band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) != 0U)
699 {
700 #ifdef OTP_CHANINFO
701 /* Return the FW cfp table for requested region code, if available.
702 * If region is not forced and the requested region code is different,
703 * simply return the corresponding pre-defined table.
704 */
705 if ((pmadapter->otp_region != MNULL) && (pmadapter->cfp_otp_bg != MNULL))
706 {
707 if (pmadapter->otp_region->force_reg != (t_u16)MFALSE ||
708 (cfp_bg == (t_u8)pmadapter->otp_region->region_code))
709 {
710 *cfp_no = (int)pmadapter->tx_power_table_bg_rows;
711 LEAVE();
712 return pmadapter->cfp_otp_bg;
713 }
714 }
715 #endif
716 for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++)
717 {
718 PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i, cfp_table_BG[i].code);
719 /* Check if region/code matches for BG bands */
720 if (cfp_table_BG[i].code == cfp_bg)
721 {
722 /* Select by band */
723 *cfp_no = cfp_table_BG[i].cfp_no;
724 LEAVE();
725 return cfp_table_BG[i].cfp;
726 }
727 }
728 }
729
730 #if CONFIG_5GHz_SUPPORT
731 if ((band & (BAND_A | BAND_AN | BAND_AAC)) != 0U)
732 {
733 #ifdef OTP_CHANINFO
734 /* Return the FW cfp table for requested region code */
735 if ((pmadapter->otp_region != MNULL) && (pmadapter->cfp_otp_a != MNULL))
736 {
737 if (pmadapter->otp_region->force_reg != (t_u16)MFALSE ||
738 (cfp_a == (t_u8)pmadapter->otp_region->region_code))
739 {
740 *cfp_no = (int)pmadapter->tx_power_table_a_rows;
741 LEAVE();
742 return pmadapter->cfp_otp_a;
743 }
744 }
745 #endif
746 for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++)
747 {
748 PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i, cfp_table_A[i].code);
749 /* Check if region/code matches for A bands */
750 if (cfp_table_A[i].code == cfp_a)
751 {
752 /* Select by band */
753 *cfp_no = cfp_table_A[i].cfp_no;
754 LEAVE();
755 return cfp_table_A[i].cfp;
756 }
757 }
758 }
759 #endif /* CONFIG_5GHz_SUPPORT */
760
761 if (region == 0U)
762 {
763 #if CONFIG_5GHz_SUPPORT
764 PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n", band, cfp_bg, cfp_a);
765
766 #else
767 PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x]\n", band, cfp_bg);
768 #endif /* CONFIG_5GHz_SUPPORT */
769 }
770 else
771 {
772 PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band, region);
773 }
774
775 LEAVE();
776 return MNULL;
777 }
778
779 /********************************************************
780 Global Functions
781 ********************************************************/
782 /**
783 * @brief This function converts region string to integer code
784 *
785 * @param pmadapter A pointer to mlan_adapter structure
786 * @param country_code Country string
787 * @param cfp_bg Pointer to buffer
788 * @param cfp_a Pointer to buffer
789 *
790 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
791 */
wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,t_u8 * country_code,t_u8 * cfp_bg,t_u8 * cfp_a)792 mlan_status wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter, t_u8 *country_code, t_u8 *cfp_bg, t_u8 *cfp_a)
793 {
794 t_u8 i;
795
796 ENTER();
797
798 /* Look for code in mapping table */
799 for (i = 0; i < NELEMENTS(country_code_mapping); i++)
800 {
801 if (!__memcmp(pmadapter, country_code_mapping[i].country_code, country_code, COUNTRY_CODE_LEN - 1))
802 {
803 *cfp_bg = country_code_mapping[i].cfp_code_bg;
804 *cfp_a = country_code_mapping[i].cfp_code_a;
805 LEAVE();
806 return MLAN_STATUS_SUCCESS;
807 }
808 }
809
810 LEAVE();
811 return MLAN_STATUS_FAILURE;
812 }
813
814 #ifdef SD8801
815 /**
816 * @brief Use index to get the data rate
817 *
818 * @param pmadapter A pointer to mlan_adapter structure
819 * @param index The index of data rate
820 * @param ht_info HT info
821 *
822 * @return Data rate or 0
823 */
wlan_index_to_data_rate(pmlan_adapter pmadapter,t_u8 index,t_u8 ht_info)824 t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 ht_info)
825 {
826 #if CONFIG_11N
827 #ifdef STREAM_2X2
828 #define MCS_NUM_SUPP 16
829 t_u16 mcs_num_supp = MCS_NUM_SUPP;
830 t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
831 {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6,
832 0x21c}, /*LG 40M*/
833 {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c,
834 0x258}, /*SG 40M */
835 {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104}, /*LG 20M */
836 {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}}; /*SG 20M */
837 #else
838 #define MCS_NUM_SUPP 8
839 t_u16 mcs_num_supp = MCS_NUM_SUPP;
840 t_u16 mcs_rate[4][MCS_NUM_SUPP] = {{0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e}, /*LG 40M*/
841 {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c}, /*SG 40M */
842 {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82}, /*LG 20M */
843 {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90}}; /*SG 20M */
844 #endif
845 #endif
846 t_u32 rate = 0;
847
848 ENTER();
849
850 #if CONFIG_11N
851 #ifdef STREAM_2X2
852 if (pmadapter->hw_dev_mcs_support == HT_STREAM_MODE_1X1)
853 mcs_num_supp = 8;
854 #endif
855 if (ht_info & MBIT(0))
856 {
857 if (index == MLAN_RATE_BITMAP_MCS0)
858 {
859 if (ht_info & MBIT(2))
860 rate = 0x0D; /* MCS 32 SGI rate */
861 else
862 rate = 0x0C; /* MCS 32 LGI rate */
863 }
864 else if (index < mcs_num_supp)
865 {
866 if (ht_info & MBIT(1))
867 {
868 if (ht_info & MBIT(2))
869 rate = mcs_rate[1][index]; /* SGI, 40M */
870 else
871 rate = mcs_rate[0][index]; /* LGI, 40M */
872 }
873 else
874 {
875 if (ht_info & MBIT(2))
876 rate = mcs_rate[3][index]; /* SGI, 20M */
877 else
878 rate = mcs_rate[2][index]; /* LGI, 20M */
879 }
880 }
881 else
882 rate = WlanDataRates[0];
883 }
884 else
885 #endif /* ENABLE_802_11N */
886 {
887 #if CONFIG_11N
888 /* 11n non HT rates */
889 if (index >= WLAN_SUPPORTED_RATES_EXT)
890 {
891 #else
892 if (index >= WLAN_SUPPORTED_RATES)
893 {
894 #endif
895 index = 0;
896 }
897 rate = WlanDataRates[index];
898 }
899 LEAVE();
900 return rate;
901 }
902 #else
903 /**
904 * @brief Use index to get the data rate
905 *
906 * @param pmadapter A pointer to mlan_adapter structure
907 * @param index The index of data rate
908 * @param tx_rate_info Tx rate info
909 * @param ext_rate_info Extend tx rate info
910 * @return Data rate or 0
911 */
912 t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter,
913 t_u8 index,
914 t_u8 tx_rate_info
915 #if CONFIG_11AX
916 ,
917 t_u8 ext_rate_info
918 #endif
919 )
920 {
921 #if CONFIG_11N
922 #ifdef STREAM_2X2
923 #define MCS_NUM_SUPP 16U
924 t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
925 {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6,
926 0x21c}, /*LG 40M*/
927 {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c,
928 0x258}, /*SG 40M */
929 {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104}, /*LG 20M */
930 {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}}; /*SG 20M */
931 #else
932 #define MCS_NUM_SUPP 8U
933 t_u16 mcs_rate[4][MCS_NUM_SUPP] = {{0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e}, /*LG 40M*/
934 {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c}, /*SG 40M */
935 {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82}, /*LG 20M */
936 {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90}}; /*SG 20M */
937 #endif
938 #endif
939
940 #if CONFIG_11AC
941 #define MCS_NUM_AC 10
942 /* NSS 1. note: the value in the table is 2 multiplier of the actual rate
943 * in other words, it is in the unit of 500 Kbs
944 */
945 t_u16 ac_mcs_rate_nss1[8][MCS_NUM_AC] = {
946 {0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C, 0x618}, /* LG 160M*/
947 {0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618, 0x6C6}, /* SG 160M*/
948 {0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 0x249, 0x2BE, 0x30C}, /* LG 80M */
949 {0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 0x28A, 0x30C, 0x363}, /* SG 80M */
950 {0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x144, 0x168}, /* LG 40M */
951 {0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 0x12C, 0x168, 0x190}, /* SG 40M */
952 {0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00}, /* LG 20M */
953 {0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00}, /* SG 20M */
954 };
955 #ifdef STREAM_2X2
956 /* NSS 2. note: the value in the table is 2 multiplier of the actual rate */
957 t_u16 ac_mcs_rate_nss2[8][MCS_NUM_AC] = {
958 {0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 0x924, 0xAF8, 0xC30}, /*LG 160M*/
959 {0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 0xA28, 0xC30, 0xD8B}, /*SG 160M*/
960
961 {0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C, 0x618}, /*LG 80M*/
962 {0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618, 0x6C6}, /*SG 80M*/
963 {0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 0x21C, 0x288, 0x2D0}, /*LG 40M*/
964 {0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 0x258, 0x2D0, 0x320}, /*SG 40M*/
965 {0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 0x138, 0x00}, /*LG 20M*/
966 {0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 0x15B, 0x00}, /*SG 20M*/
967 };
968 #endif
969 #endif /* CONFIG_11AC */
970
971 t_u32 rate = 0;
972 #if (CONFIG_11AC) || (CONFIG_11AX)
973 t_u8 mcs_index = 0;
974 #endif
975 #if CONFIG_11AX
976 t_u8 he_dcm = 0;
977 t_u8 stbc = 0;
978 #endif
979 t_u8 bw = 0;
980 t_u8 gi = 0;
981 ENTER();
982
983 #if CONFIG_11AC
984 if ((tx_rate_info & 0x3U) == (t_u8)MLAN_RATE_FORMAT_VHT)
985 {
986 /* VHT rate */
987 mcs_index = index & 0xFU;
988
989 if (mcs_index > 9U)
990 {
991 mcs_index = 9U;
992 }
993
994 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
995 bw = (tx_rate_info & 0xCU) >> 2U;
996 /* LGI: gi =0, SGI: gi = 1 */
997 gi = (tx_rate_info & 0x10U) >> 4U;
998 #ifdef STREAM_2X2
999 if ((index >> 4) == 1)
1000 {
1001 /* NSS = 2 */
1002 rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
1003 }
1004 else
1005 #endif
1006 {
1007 /* NSS = 1 */
1008 rate = ac_mcs_rate_nss1[2U * (3U - bw) + gi][mcs_index];
1009 }
1010 }
1011 else
1012 #endif
1013 #if CONFIG_11AX
1014 if ((mlan_rate_format)(tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HE)
1015 {
1016 /* HE rate */
1017 mcs_index = index & 0xF;
1018 he_dcm = ext_rate_info & MBIT(0);
1019 if (mcs_index > MCS_NUM_AX - 1)
1020 mcs_index = MCS_NUM_AX - 1;
1021 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
1022 bw = (tx_rate_info & (MBIT(3) | MBIT(2))) >> 2;
1023 /* BIT7:BIT4 0:0= 0.8us,0:1= 0.8us, 1:0=1.6us, 1:1=3.2us or 0.8us */
1024 gi = (tx_rate_info & MBIT(4)) >> 4 | (tx_rate_info & MBIT(7)) >> 6;
1025 /* STBC: BIT5 in tx rate info */
1026 stbc = (tx_rate_info & MBIT(5)) >> 5;
1027 if (gi > 3)
1028 {
1029 PRINTM(MERROR, "Invalid gi value");
1030 return 0;
1031 }
1032 if ((gi == 3) && stbc && he_dcm)
1033 {
1034 gi = 0;
1035 stbc = 0;
1036 he_dcm = 0;
1037 }
1038 /* map to gi 0:0.8us,1:1.6us 2:3.2us*/
1039 if (gi > 0)
1040 gi = gi - 1;
1041 switch (mcs_index)
1042 {
1043 case 0:
1044 case 1:
1045 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi][mcs_index * 2 + he_dcm];
1046 break;
1047 case 2:
1048 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi][mcs_index * 2];
1049 break;
1050 case 3:
1051 case 4:
1052 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi][mcs_index * 2 - 1 + he_dcm];
1053 break;
1054 default:
1055 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi][mcs_index + 4];
1056 break;
1057 }
1058 }
1059 else
1060 #endif
1061 #if CONFIG_11N
1062 if ((tx_rate_info & 0x3U) == (t_u8)MLAN_RATE_FORMAT_HT)
1063 {
1064 /* HT rate */
1065 /* 20M: bw=0, 40M: bw=1 */
1066 bw = (tx_rate_info & 0xCU) >> 2U;
1067 /* LGI: gi =0, SGI: gi = 1 */
1068 gi = (tx_rate_info & 0x10U) >> 4U;
1069 if (index == MLAN_RATE_BITMAP_MCS0)
1070 {
1071 if (gi == 1U)
1072 {
1073 rate = 0x0D; /* MCS 32 SGI rate */
1074 }
1075 else
1076 {
1077 rate = 0x0C; /* MCS 32 LGI rate */
1078 }
1079 }
1080 else if (index < MCS_NUM_SUPP)
1081 {
1082 if (bw <= 1U)
1083 {
1084 rate = mcs_rate[2U * (1U - bw) + gi][index];
1085 }
1086 else
1087 {
1088 rate = WlanDataRates[0];
1089 }
1090 }
1091 else
1092 {
1093 rate = WlanDataRates[0];
1094 }
1095 }
1096 else
1097 #endif /* CONFIG_11N */
1098 {
1099 #if CONFIG_11N
1100 /* 11n non HT rates */
1101 if (index >= WLAN_SUPPORTED_RATES_EXT)
1102 {
1103 #else
1104 if (index >= WLAN_SUPPORTED_RATES)
1105 {
1106 #endif
1107 index = 0;
1108 }
1109 rate = WlanDataRates[index];
1110 }
1111 LEAVE();
1112 return rate;
1113 }
1114 #endif
1115
1116 /**
1117 * @brief Get active data rates
1118 *
1119 * @param pmpriv A pointer to mlan_private structure
1120 * @param bss_mode The specified BSS mode (Infra/IBSS)
1121 * @param config_bands The specified band configuration
1122 * @param rates The buf to return the active rates
1123 *
1124 * @return The number of Rates
1125 */
1126 t_u32 wlan_get_active_data_rates(mlan_private *pmpriv,
1127 mlan_bss_mode bss_mode,
1128 t_u16 config_bands,
1129 WLAN_802_11_RATES rates)
1130 {
1131 t_u32 k;
1132
1133 ENTER();
1134
1135 if (pmpriv->media_connected != MTRUE)
1136 {
1137 k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands, rates);
1138 }
1139 else
1140 {
1141 k = wlan_copy_rates(rates, 0, pmpriv->curr_bss_params.data_rates, (int)pmpriv->curr_bss_params.num_of_rates);
1142 }
1143
1144 LEAVE();
1145 return k;
1146 }
1147
1148 #ifdef STA_SUPPORT
1149 /**
1150 * @brief This function search through all the regions cfp table to find the channel,
1151 * if the channel is found then gets the MIN txpower of the channel
1152 * present in all the regions.
1153 *
1154 * @param pmpriv A pointer to mlan_private structure
1155 * @param channel Channel number.
1156 *
1157 * @return The Tx power
1158 */
1159 t_u8 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel)
1160 {
1161 t_u8 i = 0;
1162 t_u8 j = 0;
1163 t_u8 tx_power = 0;
1164 t_u32 cfp_no;
1165 const chan_freq_power_t *cfp = MNULL;
1166 #if CONFIG_5GHz_SUPPORT
1167 const chan_freq_power_t *cfp_a = MNULL;
1168 t_u32 cfp_no_a;
1169 #endif /* CONFIG_5GHz_SUPPORT */
1170
1171 ENTER();
1172
1173 for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++)
1174 {
1175 /* Get CFP */
1176 cfp = cfp_table_BG[i].cfp;
1177 cfp_no = (t_u32)cfp_table_BG[i].cfp_no;
1178 /* Find matching channel and get Tx power */
1179 for (j = 0; j < cfp_no; j++)
1180 {
1181 if ((cfp + j)->channel == channel)
1182 {
1183 if (tx_power != 0U)
1184 {
1185 tx_power = MIN(tx_power, (t_u8)((cfp + j)->max_tx_power));
1186 }
1187 else
1188 {
1189 tx_power = (t_u8)(cfp + j)->max_tx_power;
1190 }
1191 break;
1192 }
1193 }
1194 }
1195
1196 #if CONFIG_5GHz_SUPPORT
1197 for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++)
1198 {
1199 /* Get CFP */
1200 cfp_a = cfp_table_A[i].cfp;
1201 cfp_no_a = (t_u32)cfp_table_A[i].cfp_no;
1202 for (j = 0; j < cfp_no_a; j++)
1203 {
1204 if ((cfp_a + j)->channel == channel)
1205 {
1206 if (tx_power != 0U)
1207 {
1208 tx_power = MIN(tx_power, (t_u8)((cfp_a + j)->max_tx_power));
1209 }
1210 else
1211 {
1212 tx_power = (t_u8)((cfp_a + j)->max_tx_power);
1213 }
1214 break;
1215 }
1216 }
1217 }
1218 #endif /* CONFIG_5GHz_SUPPORT */
1219
1220 LEAVE();
1221 return tx_power;
1222 }
1223
1224 /**
1225 * @brief Get the channel frequency power info for a specific channel
1226 *
1227 * @param pmadapter A pointer to mlan_adapter structure
1228 * @param band It can be BAND_A, BAND_G or BAND_B
1229 * @param channel The channel to search for
1230 * @param region_channel A pointer to region_chan_t structure
1231 *
1232 * @return A pointer to chan_freq_power_t structure or MNULL if not found.
1233 */
1234
1235 const chan_freq_power_t *wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,
1236 t_u16 band,
1237 t_u16 channel,
1238 region_chan_t *region_channel)
1239 {
1240 region_chan_t *rc;
1241 const chan_freq_power_t *cfp = MNULL;
1242 t_u8 i, j;
1243
1244 ENTER();
1245
1246 j = 0;
1247 while (cfp == MNULL && (j < MAX_REGION_CHANNEL_NUM))
1248 {
1249 bool continue_loop = MFALSE;
1250 rc = ®ion_channel[j];
1251
1252 if (rc->valid == (t_u8)MFALSE || rc->pcfp == MNULL)
1253 {
1254 j++;
1255 continue;
1256 }
1257 switch (rc->band)
1258 {
1259 case BAND_A:
1260 switch (band)
1261 {
1262 case BAND_AN:
1263 case BAND_A | BAND_AN:
1264 case BAND_A | BAND_AN | BAND_AAC:
1265 case BAND_A: /* Matching BAND_A */
1266 break;
1267
1268 default:
1269 j++;
1270 continue_loop = MTRUE;
1271 break;
1272 }
1273 break;
1274 case BAND_B:
1275 case BAND_G:
1276 switch (band)
1277 {
1278 case BAND_GN:
1279 case BAND_B | BAND_G | BAND_GN:
1280 case BAND_G | BAND_GN:
1281 case BAND_GN | BAND_GAC:
1282 case BAND_B | BAND_G | BAND_GN | BAND_GAC:
1283 case BAND_G | BAND_GN | BAND_GAC:
1284 case BAND_B | BAND_G:
1285 case BAND_B: /* Matching BAND_B/G */
1286 case BAND_G:
1287 break;
1288 default:
1289 j++;
1290 continue_loop = MTRUE;
1291 break;
1292 }
1293 break;
1294 default:
1295 j++;
1296 continue_loop = MTRUE;
1297 break;
1298 }
1299 if (continue_loop == MTRUE)
1300 {
1301 continue;
1302 }
1303 if (channel == FIRST_VALID_CHANNEL)
1304 {
1305 cfp = &rc->pcfp[0];
1306 }
1307 else
1308 {
1309 for (i = 0; i < rc->num_cfp; i++)
1310 {
1311 if (rc->pcfp[i].channel == channel)
1312 {
1313 cfp = &rc->pcfp[i];
1314 break;
1315 }
1316 }
1317 }
1318 j++;
1319 }
1320
1321 if (cfp == MNULL && channel != 0U)
1322 {
1323 PRINTM(MERROR,
1324 "wlan_get_cfp_by_band_and_channel(): cannot find "
1325 "cfp by band %d & channel %d\n",
1326 band, channel);
1327 }
1328
1329 LEAVE();
1330 return cfp;
1331 }
1332
1333 /**
1334 * @brief Find the channel frequency power info for a specific channel
1335 *
1336 * @param pmadapter A pointer to mlan_adapter structure
1337 * @param band It can be BAND_A, BAND_G or BAND_B
1338 * @param channel The channel to search for
1339 *
1340 * @return A pointer to chan_freq_power_t structure or MNULL if not found.
1341 */
1342 const chan_freq_power_t *wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter, t_u16 band, t_u16 channel)
1343 {
1344 const chan_freq_power_t *cfp = MNULL;
1345
1346 ENTER();
1347
1348 /* Any station(s) with 11D enabled */
1349 if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled, wlan_is_station) > 0)
1350 {
1351 cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel, pmadapter->universal_channel);
1352 }
1353 else
1354 {
1355 cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel, pmadapter->region_channel);
1356 }
1357
1358 LEAVE();
1359 return cfp;
1360 }
1361
1362 /**
1363 * @brief Find the channel frequency power info for a specific frequency
1364 *
1365 * @param pmadapter A pointer to mlan_adapter structure
1366 * @param band It can be BAND_A, BAND_G or BAND_B
1367 * @param freq The frequency to search for
1368 *
1369 * @return Pointer to chan_freq_power_t structure; MNULL if not found
1370 */
1371 const chan_freq_power_t *wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter, t_u16 band, t_u32 freq)
1372 {
1373 const chan_freq_power_t *cfp = MNULL;
1374 region_chan_t *rc;
1375 t_u8 i, j;
1376
1377 ENTER();
1378
1379 j = 0;
1380 while (cfp == MNULL && (j < MAX_REGION_CHANNEL_NUM))
1381 {
1382 bool continue_loop = MFALSE;
1383 rc = &pmadapter->region_channel[j];
1384
1385 /* Any station(s) with 11D enabled */
1386 if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled, wlan_is_station) > 0)
1387 {
1388 rc = &pmadapter->universal_channel[j];
1389 }
1390
1391 if (rc->valid == 0U || rc->pcfp == MNULL)
1392 {
1393 j++;
1394 continue;
1395 }
1396 switch (rc->band)
1397 {
1398 case BAND_A:
1399 switch (band)
1400 {
1401 case BAND_AN:
1402 case BAND_A | BAND_AN:
1403 case BAND_A | BAND_AN | BAND_AAC:
1404 case BAND_A: /* Matching BAND_A */
1405 break;
1406 default:
1407 j++;
1408 continue_loop = MTRUE;
1409 break;
1410 }
1411 break;
1412 case BAND_B:
1413 case BAND_G:
1414 switch (band)
1415 {
1416 case BAND_GN:
1417 case BAND_B | BAND_G | BAND_GN:
1418 case BAND_G | BAND_GN:
1419 case BAND_GN | BAND_GAC:
1420 case BAND_B | BAND_G | BAND_GN | BAND_GAC:
1421 case BAND_G | BAND_GN | BAND_GAC:
1422 case BAND_B | BAND_G:
1423 case BAND_B:
1424 case BAND_G:
1425 break;
1426 default:
1427 j++;
1428 continue_loop = MTRUE;
1429 break;
1430 }
1431 break;
1432 default:
1433 j++;
1434 continue_loop = MTRUE;
1435 break;
1436 }
1437 if (continue_loop == MTRUE)
1438 {
1439 continue;
1440 }
1441 for (i = 0; i < rc->num_cfp; i++)
1442 {
1443 if (rc->pcfp[i].freq == freq)
1444 {
1445 cfp = &rc->pcfp[i];
1446 break;
1447 }
1448 }
1449 j++;
1450 }
1451
1452 if (cfp == MNULL && freq != 0U)
1453 {
1454 PRINTM(MERROR,
1455 "wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
1456 "band %d & freq %d\n",
1457 band, freq);
1458 }
1459
1460 LEAVE();
1461 return cfp;
1462 }
1463 #endif /* STA_SUPPORT */
1464
1465 /**
1466 * @brief Check if Rate Auto
1467 *
1468 * @param pmpriv A pointer to mlan_private structure
1469 *
1470 * @return MTRUE or MFALSE
1471 */
1472 bool wlan_is_rate_auto(mlan_private *pmpriv)
1473 {
1474 t_u32 i;
1475 int rate_num = 0;
1476
1477 ENTER();
1478
1479 for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
1480 {
1481 if (pmpriv->bitmap_rates[i] != 0U)
1482 {
1483 rate_num++;
1484 }
1485 }
1486
1487 LEAVE();
1488 if (rate_num > 1)
1489 {
1490 return MTRUE;
1491 }
1492 else
1493 {
1494 return MFALSE;
1495 }
1496 }
1497
1498 /**
1499 * @brief Covert Rate Bitmap to Rate index
1500 *
1501 * @param pmadapter Pointer to mlan_adapter structure
1502 * @param rate_bitmap Pointer to rate bitmap
1503 * @param size Size of the bitmap array
1504 *
1505 * @return Rate index
1506 */
1507 int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
1508 {
1509 int i;
1510
1511 ENTER();
1512
1513 for (i = 0; i < size * 8; i++)
1514 {
1515 if ((rate_bitmap[i / 16] & ((t_u32)1U << ((t_u32)i % 16U))) != 0U)
1516 {
1517 LEAVE();
1518 return i;
1519 }
1520 }
1521
1522 LEAVE();
1523 return -1;
1524 }
1525
1526 /**
1527 * @brief Convert config_bands to B/G/A band
1528 *
1529 * @param config_bands The specified band configuration
1530 *
1531 * @return BAND_B|BAND_G|BAND_A
1532 */
1533 t_u16 wlan_convert_config_bands(t_u16 config_bands)
1534 {
1535 t_u16 bands = 0;
1536 if (config_bands & BAND_B)
1537 bands |= BAND_B;
1538 if (config_bands & BAND_G || config_bands & BAND_GN
1539 #ifdef ENABLE_802_11AC
1540 || config_bands & BAND_GAC
1541 #endif
1542 #ifdef ENABLE_802_11AX
1543 || config_bands & BAND_GAX
1544 #endif
1545 )
1546 bands |= BAND_G;
1547 if (config_bands & BAND_A || config_bands & BAND_AN
1548 #ifdef ENABLE_802_11AC
1549 || config_bands & BAND_AAC
1550 #endif
1551 #ifdef ENABLE_802_11AX
1552 || config_bands & BAND_AAX
1553 #endif
1554 )
1555 bands |= BAND_A;
1556 return bands;
1557 }
1558
1559 /**
1560 * @brief Get supported data rates
1561 *
1562 * @param pmpriv A pointer to mlan_private structure
1563 * @param bss_mode The specified BSS mode (Infra/IBSS)
1564 * @param config_bands The specified band configuration
1565 * @param rates The buf to return the supported rates
1566 *
1567 * @return The number of Rates
1568 */
1569 t_u32 wlan_get_supported_rates(mlan_private *pmpriv,
1570 mlan_bss_mode bss_mode,
1571 t_u16 config_bands,
1572 WLAN_802_11_RATES rates)
1573 {
1574 t_u32 k = 0;
1575 t_u16 bands = 0;
1576
1577 ENTER();
1578
1579 bands = wlan_convert_config_bands(config_bands);
1580 if (bss_mode == MLAN_BSS_MODE_INFRA)
1581 {
1582 /* Infra. mode */
1583 if (bands == BAND_B)
1584 {
1585 /* B only */
1586 k = wlan_copy_rates(rates, k, SupportedRates_B, sizeof(SupportedRates_B));
1587 }
1588 else if (bands == BAND_G)
1589 {
1590 /* G only */
1591 k = wlan_copy_rates(rates, k, SupportedRates_G, sizeof(SupportedRates_G));
1592 }
1593 else if (bands & (BAND_B | BAND_G))
1594 {
1595 /* BG only */
1596 #ifdef WIFI_DIRECT_SUPPORT
1597 if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
1598 k = wlan_copy_rates(rates, k, SupportedRates_G, sizeof(SupportedRates_G));
1599 else
1600 #endif
1601 k = wlan_copy_rates(rates, k, SupportedRates_BG, sizeof(SupportedRates_BG));
1602 }
1603 else if (bands & BAND_A)
1604 {
1605 /* support A */
1606 k = wlan_copy_rates(rates, k, SupportedRates_A, sizeof(SupportedRates_A));
1607 }
1608 }
1609 else
1610 {
1611 /* Adhoc. mode */
1612 if (bands == BAND_B)
1613 {
1614 /* B only */
1615 k = wlan_copy_rates(rates, k, AdhocRates_B, sizeof(AdhocRates_B));
1616 }
1617 else if (bands == BAND_G)
1618 {
1619 /* G only */
1620 k = wlan_copy_rates(rates, k, AdhocRates_G, sizeof(AdhocRates_G));
1621 }
1622 else if (bands & BAND_A)
1623 {
1624 /* support A */
1625 k = wlan_copy_rates(rates, k, AdhocRates_A, sizeof(AdhocRates_A));
1626 }
1627 else
1628 {
1629 k = wlan_copy_rates(rates, k, AdhocRates_BG, sizeof(AdhocRates_BG));
1630 }
1631 }
1632
1633 LEAVE();
1634 return k;
1635 }
1636
1637 /**
1638 * @brief This function sets region table.
1639 *
1640 * @param pmpriv A pointer to mlan_private structure
1641 * @param region The region code
1642 * @param band The band
1643 *
1644 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1645 */
1646 mlan_status wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u16 band)
1647 {
1648 mlan_adapter *pmadapter = pmpriv->adapter;
1649 int i = 0;
1650 const chan_freq_power_t *cfp;
1651 int cfp_no;
1652
1653 ENTER();
1654
1655 (void)__memset(pmadapter, pmadapter->region_channel, 0, sizeof(pmadapter->region_channel));
1656
1657 if ((band & (BAND_B | BAND_G | BAND_GN)) != 0U)
1658 {
1659 cfp = wlan_get_region_cfp_table(pmadapter, region, (BAND_G | BAND_B | BAND_GN), &cfp_no);
1660 if (cfp != MNULL)
1661 {
1662 pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
1663 pmadapter->region_channel[i].pcfp = cfp;
1664 }
1665 else
1666 {
1667 PRINTM(MERROR, "wrong region code %#x in Band B-G\n", region);
1668 LEAVE();
1669 return MLAN_STATUS_FAILURE;
1670 }
1671 pmadapter->region_channel[i].valid = (t_u8)MTRUE;
1672 pmadapter->region_channel[i].region = region;
1673 if ((band & BAND_GN) != 0U)
1674 {
1675 pmadapter->region_channel[i].band = BAND_G;
1676 }
1677 else
1678 {
1679 pmadapter->region_channel[i].band = (band & BAND_G) != 0U ? BAND_G : BAND_B;
1680 }
1681 i++;
1682 }
1683 #if CONFIG_5GHz_SUPPORT
1684 if ((band & (BAND_A | BAND_AN | BAND_AAC)) != 0U)
1685 {
1686 cfp = wlan_get_region_cfp_table(pmadapter, region, BAND_A, &cfp_no);
1687 if (cfp != MNULL)
1688 {
1689 pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
1690 pmadapter->region_channel[i].pcfp = cfp;
1691 }
1692 else
1693 {
1694 PRINTM(MERROR, "wrong region code %#x in Band A\n", region);
1695 LEAVE();
1696 return MLAN_STATUS_FAILURE;
1697 }
1698 pmadapter->region_channel[i].valid = (t_u8)MTRUE;
1699 pmadapter->region_channel[i].region = region;
1700 pmadapter->region_channel[i].band = BAND_A;
1701 }
1702 #endif /* CONFIG_5GHz_SUPPORT */
1703
1704 LEAVE();
1705 return MLAN_STATUS_SUCCESS;
1706 }
1707
1708 /**
1709 * @brief Get if radar detection is enabled or not on a certain channel
1710 *
1711 * @param priv Private driver information structure
1712 * @param chnl Channel to determine radar detection requirements
1713 *
1714 * @return
1715 * - MTRUE if radar detection is required
1716 * - MFALSE otherwise
1717 */
1718 t_bool wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
1719 {
1720 t_u8 i, j;
1721 t_bool required = MFALSE;
1722 const chan_freq_power_t *pcfp = MNULL;
1723
1724 ENTER();
1725
1726 /* get the cfp table first */
1727 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++)
1728 {
1729 if (priv->adapter->region_channel[i].band == BAND_A)
1730 {
1731 pcfp = priv->adapter->region_channel[i].pcfp;
1732 break;
1733 }
1734 }
1735
1736 if (pcfp == MNULL)
1737 {
1738 /* This means operation in BAND-A is not support, we can just return
1739 false here, it's harmless */
1740 goto done;
1741 }
1742
1743 /* get the radar detection requirements according to chan num */
1744 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++)
1745 {
1746 if (pcfp[j].channel == chnl)
1747 {
1748 required = pcfp[j].passive_scan_or_radar_detect;
1749 break;
1750 }
1751 }
1752
1753 done:
1754 LEAVE();
1755 return required;
1756 }
1757
1758 /**
1759 * @brief Get if scan type is passive or not on a certain channel for b/g band
1760 *
1761 * @param priv Private driver information structure
1762 * @param chnl Channel to determine scan type
1763 *
1764 * @return
1765 * - MTRUE if scan type is passive
1766 * - MFALSE otherwise
1767 */
1768
1769 t_bool wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
1770 {
1771 t_u8 i, j;
1772 t_bool passive = MFALSE;
1773 const chan_freq_power_t *pcfp = MNULL;
1774
1775 ENTER();
1776
1777 /* get the cfp table first */
1778 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++)
1779 {
1780 if ((priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) != 0U)
1781 {
1782 pcfp = priv->adapter->region_channel[i].pcfp;
1783 break;
1784 }
1785 }
1786
1787 if (pcfp == MNULL)
1788 {
1789 /* This means operation in BAND-B or BAND_G is not support, we can
1790 just return false here */
1791 goto done;
1792 }
1793
1794 /* get the bg scan type according to chan num */
1795 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++)
1796 {
1797 if (pcfp[j].channel == chnl)
1798 {
1799 passive = pcfp[j].passive_scan_or_radar_detect;
1800 break;
1801 }
1802 }
1803
1804 done:
1805 LEAVE();
1806 return passive;
1807 }
1808
1809 /**
1810 * @bried convert ht_info to rate_info
1811 *
1812 * @param ht_info ht_info
1813 *
1814 * @return rate_info
1815 */
1816 t_u8 wlan_convert_v14_rate_ht_info(t_u8 ht_info)
1817 {
1818 t_u8 rate_info = 0;
1819 rate_info = ht_info & 0x01U;
1820 /* band */
1821 rate_info |= (ht_info & MBIT(1)) << 1;
1822 /* Short GI */
1823 rate_info |= (ht_info & MBIT(2)) << 1;
1824 return rate_info;
1825 }
1826
1827 /**
1828 * @brief Validate if channel is in range of World Wide Safe Mode
1829 *
1830 * @param chan_num Channel Number
1831 *
1832 * @return Valid or Invalid
1833 */
1834 t_bool wlan_is_channel_valid(t_u8 chan_num)
1835 {
1836 t_bool valid = MFALSE;
1837 int i = 0;
1838 chan_freq_power_t *cfp_wwsm;
1839 int cfp_no = 0;
1840
1841 ENTER();
1842
1843 cfp_wwsm = (chan_freq_power_t *)channel_freq_power_WW_BG;
1844 cfp_no = (int)(sizeof(channel_freq_power_WW_BG) / sizeof(chan_freq_power_t));
1845
1846 for (i = 0; i < cfp_no; i++)
1847 {
1848 /* Channel 0 is invalid */
1849 if (chan_num == 0U)
1850 {
1851 PRINTM(MERROR, "Invalid channel. Channel number can't be %d\r\n", chan_num);
1852 valid = MFALSE;
1853 break;
1854 }
1855
1856 if (chan_num == cfp_wwsm[i].channel)
1857 {
1858 valid = MTRUE;
1859 break;
1860 }
1861 }
1862
1863 #if CONFIG_5GHz_SUPPORT
1864 if (!valid)
1865 {
1866 cfp_wwsm = (chan_freq_power_t *)channel_freq_power_WW_A;
1867 cfp_no = (int)(sizeof(channel_freq_power_WW_A) / sizeof(chan_freq_power_t));
1868
1869 for (i = 0; i < cfp_no; i++)
1870 {
1871 /* Channel 0 is invalid */
1872 if (chan_num == 0U)
1873 {
1874 PRINTM(MERROR, "Invalid channel. Channel number can't be %d\r\n", chan_num);
1875 valid = MFALSE;
1876 break;
1877 }
1878
1879 if (chan_num == cfp_wwsm[i].channel)
1880 {
1881 valid = MTRUE;
1882 break;
1883 }
1884 }
1885 }
1886 #endif
1887
1888 LEAVE();
1889 return valid;
1890 }
1891
1892 /**
1893 * @brief Validate if channel is in range of region table
1894 *
1895 * @param priv Private driver information structure
1896 * @param chan_num Channel Number
1897 *
1898 * @return Valid or Invalid
1899 */
1900 t_bool wlan_check_channel_by_region_table(mlan_private *pmpriv, t_u8 chan_num)
1901 {
1902 t_bool valid = MFALSE;
1903 int i = 0;
1904 mlan_adapter *pmadapter = pmpriv->adapter;
1905 const chan_freq_power_t *cfp = pmadapter->region_channel[0].pcfp;
1906 int cfp_no = pmadapter->region_channel[0].num_cfp;
1907
1908 ENTER();
1909
1910 if(NULL == cfp)
1911 return MFALSE;
1912
1913 /* Channel 0 is invalid */
1914 if (chan_num == 0)
1915 {
1916 PRINTM(MERROR, "Invalid channel. Channel number can't be %d\r\n", chan_num);
1917 valid = MFALSE;
1918 return valid;
1919 }
1920
1921 for (i = 0; i < cfp_no; i++)
1922 {
1923 if (chan_num == cfp[i].channel)
1924 {
1925 valid = MTRUE;
1926 break;
1927 }
1928 }
1929
1930 #if CONFIG_5GHz_SUPPORT
1931 if (!valid)
1932 {
1933 cfp = pmadapter->region_channel[1].pcfp;
1934 cfp_no = pmadapter->region_channel[1].num_cfp;
1935
1936 if(NULL == cfp)
1937 return MFALSE;
1938
1939 for (i = 0; i < cfp_no; i++)
1940 {
1941 if (chan_num == cfp[i].channel)
1942 {
1943 valid = MTRUE;
1944 break;
1945 }
1946 }
1947 }
1948 #endif
1949
1950 LEAVE();
1951 return valid;
1952 }
1953
1954 /**
1955 * @brief Validate if radio mode is in range of World Wide Safe Mode
1956 *
1957 * @param mode radio mode
1958 *
1959 * @return Valid or Invalid
1960 */
1961 t_bool wlan_is_radio_mode_valid(t_u8 mode)
1962 {
1963 t_bool valid = MFALSE;
1964 int i = 0;
1965 int mode_num;
1966
1967 ENTER();
1968 mode_num = (sizeof(rf_radio_modes_group) / sizeof(rf_radio_modes_group[0]));
1969
1970 for (i = 0; i < mode_num; i++)
1971 {
1972 if (mode == rf_radio_modes_group[i])
1973 {
1974 valid = MTRUE;
1975 break;
1976 }
1977 }
1978
1979 if (valid == MFALSE)
1980 {
1981 PRINTF("Invalid radio mode. Radio mode can't be %d\r\n", mode);
1982 }
1983 LEAVE();
1984 return valid;
1985 }
1986
1987 /**
1988 * @brief Validate if channel and its frequency is in range of World Wide Safe Mode
1989 *
1990 * @param chan_num Channel Number
1991 * @param chan_freq Channel Frequency
1992 *
1993 * @return Valid or Invalid
1994 */
1995 t_bool wlan_is_channel_and_freq_valid(mlan_adapter *pmadapter, t_u8 chan_num, t_u16 chan_freq)
1996 {
1997 t_bool valid = MFALSE;
1998 int i = 0;
1999 const chan_freq_power_t *cfp;
2000 int cfp_no = 0;
2001
2002 ENTER();
2003
2004 cfp = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code, (BAND_G | BAND_B | BAND_GN), &cfp_no);
2005
2006 for (i = 0; i < cfp_no; i++)
2007 {
2008 /* Channel 0 is invalid */
2009 if (chan_num == 0U)
2010 {
2011 PRINTM(MERROR, "Invalid channel. Channel number can't be %d\r\n", chan_num);
2012 valid = MFALSE;
2013 break;
2014 }
2015
2016 if (chan_num == cfp[i].channel)
2017 {
2018 /* Channel Number is valid. Now validate the corresponding frequency as well */
2019 if (chan_freq == cfp[i].freq)
2020 {
2021 valid = MTRUE;
2022 }
2023 else
2024 {
2025 PRINTM(MERROR, "Channel freq mismatch. Expected %d, Configured %d\r\n", cfp[i].freq, chan_freq);
2026 valid = MFALSE;
2027 }
2028
2029 break;
2030 }
2031 }
2032
2033 #if CONFIG_5GHz_SUPPORT
2034 if (!valid)
2035 {
2036 cfp = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code, BAND_A, &cfp_no);
2037
2038 for (i = 0; i < cfp_no; i++)
2039 {
2040 /* Channel 0 is invalid */
2041 if (chan_num == 0U)
2042 {
2043 PRINTM(MERROR, "Invalid channel. Channel number can't be %d\r\n", chan_num);
2044 valid = MFALSE;
2045 break;
2046 }
2047
2048 if (chan_num == cfp[i].channel)
2049 {
2050 /* Channel Number is valid. Now validate the corresponding frequency as well */
2051 if (chan_freq == cfp[i].freq)
2052 {
2053 valid = MTRUE;
2054 }
2055 else
2056 {
2057 PRINTM(MERROR, "Channel freq mismatch. Expected %d, Configured %d\r\n", cfp[i].freq,
2058 chan_freq);
2059 valid = MFALSE;
2060 }
2061
2062 break;
2063 }
2064 }
2065 }
2066 #endif
2067
2068 LEAVE();
2069 return valid;
2070 }
2071
2072 /**
2073 * @brief Set Custom CFP Table
2074 *
2075 * @param chanlist Channel List Config
2076 * @param cfp_no_bg A pointer to the number of CFP entries for Band BG
2077 * @param cfp_no_a A pointer to the number of CFP entries for Band A
2078 *
2079 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2080 */
2081 #if CONFIG_5GHz_SUPPORT
2082 mlan_status wlan_set_custom_cfp_table(wifi_chanlist_t *chanlist, t_u8 *cfp_no_bg, t_u8 *cfp_no_a)
2083 #else
2084 mlan_status wlan_set_custom_cfp_table(wifi_chanlist_t *chanlist, t_u8 *cfp_no_bg)
2085 #endif
2086 {
2087 t_u8 i = 0;
2088 t_u8 idx_bg = 0;
2089 *cfp_no_bg = 0;
2090
2091 #if CONFIG_5GHz_SUPPORT
2092 t_u8 idx_a = 0;
2093 *cfp_no_a = 0;
2094 #endif
2095
2096 ENTER();
2097
2098 for (i = 0; i < chanlist->num_chans; i++)
2099 {
2100 if ((chanlist->chan_info[i].chan_num <= MAX_CHANNELS_BG) &&
2101 (idx_bg < (sizeof(channel_freq_power_Custom_BG) / sizeof(chan_freq_power_t))))
2102 {
2103 channel_freq_power_Custom_BG[idx_bg].channel = chanlist->chan_info[i].chan_num;
2104 channel_freq_power_Custom_BG[idx_bg].freq = chanlist->chan_info[i].chan_freq;
2105 channel_freq_power_Custom_BG[idx_bg].passive_scan_or_radar_detect =
2106 chanlist->chan_info[i].passive_scan_or_radar_detect;
2107 idx_bg++;
2108 *cfp_no_bg = idx_bg;
2109 }
2110 #if CONFIG_5GHz_SUPPORT
2111 else if ((chanlist->chan_info[i].chan_num > MAX_CHANNELS_BG) &&
2112 (idx_a < (sizeof(channel_freq_power_Custom_A) / sizeof(chan_freq_power_t))))
2113 {
2114 channel_freq_power_Custom_A[idx_a].channel = chanlist->chan_info[i].chan_num;
2115 channel_freq_power_Custom_A[idx_a].freq = chanlist->chan_info[i].chan_freq;
2116 channel_freq_power_Custom_A[idx_a].passive_scan_or_radar_detect =
2117 chanlist->chan_info[i].passive_scan_or_radar_detect;
2118 idx_a++;
2119 *cfp_no_a = idx_a;
2120 }
2121 #endif
2122 else
2123 {
2124 #if CONFIG_5GHz_SUPPORT
2125 PRINTM(MERROR, "Error in configuring custom CFP table. ch %d, idx_bg %d, idx_a %d\r\n",
2126 chanlist->chan_info[i].chan_num, idx_bg, idx_a);
2127 #else
2128 PRINTM(MERROR, "Error in configuring custom CFP table. ch %d, idx_bg %d\r\n", chanlist->chan_info[i].chan_num,
2129 idx_bg);
2130 #endif
2131 return MLAN_STATUS_FAILURE;
2132 }
2133 }
2134
2135 LEAVE();
2136 return MLAN_STATUS_SUCCESS;
2137 }
2138
2139 /**
2140 * @brief This function sets custom region table.
2141 *
2142 * @param pmpriv A pointer to mlan_private structure
2143 * @param cfp_no_bg Number of CFP entries for Band BG
2144 * @param cfp_no_a Number of CFP entries for Band A
2145 *
2146 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2147 */
2148 #if CONFIG_5GHz_SUPPORT
2149 void wlan_set_custom_regiontable(mlan_private *pmpriv, t_u8 cfp_no_bg, t_u8 cfp_no_a)
2150 #else
2151 void wlan_set_custom_regiontable(mlan_private *pmpriv, t_u8 cfp_no_bg)
2152 #endif
2153 {
2154 mlan_adapter *pmadapter = pmpriv->adapter;
2155 int i = 0;
2156
2157 ENTER();
2158
2159 if (cfp_no_bg != 0U)
2160 {
2161 pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no_bg;
2162 pmadapter->region_channel[i].pcfp = channel_freq_power_Custom_BG;
2163 }
2164
2165 i++;
2166
2167 #if CONFIG_5GHz_SUPPORT
2168 if (cfp_no_a != 0U)
2169 {
2170 pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no_a;
2171 pmadapter->region_channel[i].pcfp = channel_freq_power_Custom_A;
2172 }
2173 #endif
2174
2175 LEAVE();
2176 }
2177
2178 /**
2179 * @brief This function gets the list of configured active channels.
2180 *
2181 * @param pmpriv A pointer to mlan_private structure
2182 * @param chan_list A pointer to the channel list
2183 * @param num_chans A pointer to the number of active channels
2184 * @param acs_band ACS band info 0: get 2.4G channel list
2185 * 1: get 5G channel list
2186 */
2187 void wlan_get_active_channel_list(mlan_private *pmpriv, t_u8 *chan_list, t_u8 *num_chans, t_u16 acs_band)
2188 {
2189 mlan_adapter *pmadapter = pmpriv->adapter;
2190 int i = 0;
2191 int j = 0;
2192 const chan_freq_power_t *cfp;
2193 int cfp_no;
2194
2195 ENTER();
2196
2197 *num_chans = 0;
2198
2199 if (acs_band == 0)
2200 {
2201 cfp = pmadapter->region_channel[i].pcfp;
2202 cfp_no = pmadapter->region_channel[i].num_cfp;
2203 for (j = 0; j < cfp_no; j++)
2204 {
2205 if ((!(cfp[j].dynamic.flags & NXP_CHANNEL_DISABLED)) && (!cfp[j].passive_scan_or_radar_detect))
2206 {
2207 *(chan_list++) = cfp[j].channel;
2208 *num_chans = *num_chans + 1;
2209 }
2210 }
2211 }
2212 if (acs_band == 1)
2213 {
2214 #if CONFIG_5GHz_SUPPORT
2215 i = 1;
2216 cfp = pmadapter->region_channel[i].pcfp;
2217 cfp_no = (int)pmadapter->region_channel[i].num_cfp;
2218
2219 for (j = 0; j < cfp_no; j++)
2220 {
2221 if ((!(cfp[j].dynamic.flags & NXP_CHANNEL_DISABLED)) && (!cfp[j].passive_scan_or_radar_detect))
2222 {
2223 *(chan_list++) = (t_u8)cfp[j].channel;
2224 *num_chans = *num_chans + 1U;
2225 }
2226 }
2227
2228 #endif
2229 }
2230 }
2231
2232 #ifdef OTP_CHANINFO
2233 /**
2234 * @brief Update CFP tables and power tables from FW
2235 *
2236 * @param priv Private driver information structure
2237 * @param buf Pointer to the buffer holding TLV data
2238 * from 0x242 command response.
2239 * @param buf_left bufsize
2240 *
2241 * @return
2242 * None
2243 */
2244 void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
2245 {
2246 mlan_adapter *pmadapter = pmpriv->adapter;
2247 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2248 MrvlIEtypesHeader_t *head;
2249 t_u16 tlv;
2250 t_u16 tlv_buf_len;
2251 t_u16 tlv_buf_left;
2252 t_u16 i;
2253 int k = 0, rows, cols;
2254 t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
2255 #if CONFIG_5GHz_SUPPORT
2256 t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
2257 #endif
2258 t_u8 *tlv_buf;
2259 t_u8 *data;
2260 t_u8 *tmp;
2261 mlan_status ret;
2262
2263 ENTER();
2264
2265 if (buf == MNULL)
2266 {
2267 PRINTM(MERROR, "CFP table update failed!\n");
2268 goto out;
2269 }
2270 if (pmadapter->otp_region != MNULL)
2271 {
2272 wlan_free_fw_cfp_tables(pmadapter);
2273 }
2274
2275 pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
2276 pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
2277 #if CONFIG_5GHz_SUPPORT
2278 pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
2279 pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
2280 #endif
2281 tlv_buf = (t_u8 *)buf;
2282 tlv_buf_left = buf_left;
2283
2284 while (tlv_buf_left >= sizeof(*head))
2285 {
2286 head = (MrvlIEtypesHeader_t *)(void *)tlv_buf;
2287 tlv = wlan_le16_to_cpu(head->type);
2288 tlv_buf_len = wlan_le16_to_cpu(head->len);
2289
2290 if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
2291 {
2292 break;
2293 }
2294 data = (t_u8 *)head + sizeof(*head);
2295
2296 switch (tlv)
2297 {
2298 case TLV_TYPE_REGION_INFO:
2299 /* Skip adding fw region info if it already exists or
2300 * if this TLV has no set data
2301 */
2302 if (*data == 0U)
2303 {
2304 break;
2305 }
2306 if (pmadapter->otp_region != MNULL)
2307 {
2308 break;
2309 }
2310
2311 ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(otp_region_info_t), MLAN_MEM_DEF,
2312 (t_u8 **)(void **)&pmadapter->otp_region);
2313
2314 if (ret != MLAN_STATUS_SUCCESS || (pmadapter->otp_region == MNULL))
2315 {
2316 PRINTM(MERROR,
2317 "Memory allocation for the otp region"
2318 " info struct failed!\n");
2319 break;
2320 }
2321 /* Save region info values from OTP in the otp_region
2322 * structure
2323 */
2324 (void)__memcpy(pmadapter, pmadapter->otp_region, data, sizeof(otp_region_info_t));
2325
2326 data += sizeof(otp_region_info_t);
2327 /* Get pre-defined cfp tables corresponding to the region code
2328 * in OTP
2329 */
2330 for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++)
2331 {
2332 if (cfp_table_BG[i].code == pmadapter->otp_region->region_code)
2333 {
2334 max_tx_pwr_bg = (cfp_table_BG[i].cfp)->max_tx_power;
2335 break;
2336 }
2337 }
2338 #if CONFIG_5GHz_SUPPORT
2339 for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++)
2340 {
2341 if (cfp_table_A[i].code == pmadapter->otp_region->region_code)
2342 {
2343 max_tx_pwr_a = (cfp_table_A[i].cfp)->max_tx_power;
2344 break;
2345 }
2346 }
2347 #endif
2348 /* Update the region code and the country code in pmadapter */
2349 pmadapter->region_code = pmadapter->otp_region->region_code;
2350 pmadapter->country_code[0] = pmadapter->otp_region->country_code[0];
2351 pmadapter->country_code[1] = pmadapter->otp_region->country_code[1];
2352 pmadapter->country_code[2] = (t_u8)'\0';
2353 pmadapter->domain_reg.country_code[0] = pmadapter->otp_region->country_code[0];
2354 pmadapter->domain_reg.country_code[1] = pmadapter->otp_region->country_code[1];
2355 pmadapter->domain_reg.country_code[2] = (t_u8)'\0';
2356 pmadapter->cfp_code_bg = pmadapter->otp_region->region_code;
2357 #if CONFIG_5GHz_SUPPORT
2358 pmadapter->cfp_code_a = pmadapter->otp_region->region_code;
2359 #endif
2360 break;
2361 case TLV_TYPE_CHAN_ATTR_CFG:
2362 /* Skip adding fw cfp tables if they already exist or
2363 * if this TLV has no set data
2364 */
2365 if (*data == 0U)
2366 {
2367 break;
2368 }
2369
2370 #if CONFIG_5GHz_SUPPORT
2371 if ((pmadapter->cfp_otp_bg != MNULL) || (pmadapter->cfp_otp_a != MNULL))
2372 #else
2373 if (pmadapter->cfp_otp_bg != MNULL)
2374 #endif
2375 {
2376 break;
2377 }
2378
2379 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2380 pmadapter->tx_power_table_bg_rows * sizeof(chan_freq_power_t), MLAN_MEM_DEF,
2381 (t_u8 **)(void **)&pmadapter->cfp_otp_bg);
2382 if ((ret != MLAN_STATUS_SUCCESS) || (pmadapter->cfp_otp_bg == MNULL))
2383 {
2384 PRINTM(MERROR,
2385 "Memory allocation for storing otp bg"
2386 " table data failed!\n");
2387 break;
2388 }
2389 (void)__memset(pmadapter, pmadapter->cfp_otp_bg, 0, pmadapter->tx_power_table_bg_rows * sizeof(chan_freq_power_t));
2390 /* Save channel usability flags from OTP data in the fw cfp bg
2391 * table and set frequency and max_tx_power values
2392 */
2393 for (i = 0; i < pmadapter->tx_power_table_bg_rows; i++)
2394 {
2395 (pmadapter->cfp_otp_bg + i)->channel = *data;
2396 if (*data == 14U)
2397 {
2398 (pmadapter->cfp_otp_bg + i)->freq = 2484;
2399 }
2400 else
2401 {
2402 (pmadapter->cfp_otp_bg + i)->freq = (t_u32)2412U + (t_u32)5U * ((t_u32)*data - (t_u32)1U);
2403 }
2404 (pmadapter->cfp_otp_bg + i)->max_tx_power = max_tx_pwr_bg;
2405 data++;
2406 (pmadapter->cfp_otp_bg + i)->dynamic.flags = *data;
2407 if ((*data & NXP_CHANNEL_DFS) != 0U)
2408 {
2409 (pmadapter->cfp_otp_bg + i)->passive_scan_or_radar_detect = MTRUE;
2410 }
2411 data++;
2412 }
2413 #if CONFIG_5GHz_SUPPORT
2414 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2415 pmadapter->tx_power_table_a_rows * sizeof(chan_freq_power_t), MLAN_MEM_DEF,
2416 (t_u8 **)(void *)&pmadapter->cfp_otp_a);
2417 if ((ret != MLAN_STATUS_SUCCESS) || (pmadapter->cfp_otp_a == MNULL))
2418 {
2419 PRINTM(MERROR,
2420 "Memory allocation for storing otp a"
2421 " table data failed!\n");
2422 break;
2423 }
2424 (void)__memset(pmadapter, pmadapter->cfp_otp_bg, 0, pmadapter->tx_power_table_bg_rows * sizeof(chan_freq_power_t));
2425 /* Save channel usability flags from OTP data in the fw cfp a
2426 * table and set frequency and max_tx_power values
2427 */
2428 for (i = 0; i < pmadapter->tx_power_table_a_rows; i++)
2429 {
2430 (pmadapter->cfp_otp_a + i)->channel = *data;
2431 if (*data < 183U)
2432 {
2433 /* 5GHz channels */
2434 (pmadapter->cfp_otp_a + i)->freq = (t_u32)5035U + (t_u32)5U * ((t_u32)*data - (t_u32)7U);
2435 }
2436 else
2437 {
2438 /* 4GHz channels */
2439 (pmadapter->cfp_otp_a + i)->freq = (t_u32)4915U + (t_u32)5U * ((t_u32)*data - (t_u32)183U);
2440 }
2441 (pmadapter->cfp_otp_a + i)->max_tx_power = max_tx_pwr_a;
2442 data++;
2443 (pmadapter->cfp_otp_a + i)->dynamic.flags = *data;
2444 if ((*data & NXP_CHANNEL_DFS) != 0U)
2445 {
2446 (pmadapter->cfp_otp_a + i)->passive_scan_or_radar_detect = MTRUE;
2447 }
2448 data++;
2449 }
2450 #endif
2451 break;
2452 case TLV_TYPE_POWER_TABLE:
2453 /* Skip adding fw power tables if this TLV has no data or
2454 * if they already exists but force reg rule is set in the otp
2455 */
2456 if (*data == 0U)
2457 {
2458 break;
2459 }
2460 if ((pmadapter->otp_region != MNULL) && (pmadapter->otp_region->force_reg != 0U) &&
2461 (pmadapter->tx_power_table_bg != MNULL))
2462 {
2463 break;
2464 }
2465
2466 /* Save the tlv data in power tables for band BG and A */
2467 tmp = data;
2468 i = 0;
2469 while ((i < (t_u16)pmadapter->tx_power_table_bg_rows * (t_u16)pmadapter->tx_power_table_bg_cols) &&
2470 (i < tlv_buf_len) && (*tmp != 36U))
2471 {
2472 i++;
2473 tmp++;
2474 }
2475 if (pmadapter->tx_power_table_bg == MNULL)
2476 {
2477 ret = pcb->moal_malloc(pmadapter->pmoal_handle, i, MLAN_MEM_DEF,
2478 (t_u8 **)&pmadapter->tx_power_table_bg);
2479 if ((ret != MLAN_STATUS_SUCCESS) || (pmadapter->tx_power_table_bg == MNULL))
2480 {
2481 PRINTM(MERROR,
2482 "Memory allocation for the BG-band"
2483 " power table falied!\n");
2484 break;
2485 }
2486 }
2487 if (i > 0U)
2488 {
2489 (void)__memcpy(pmadapter, pmadapter->tx_power_table_bg, data, i);
2490 }
2491 pmadapter->tx_power_table_bg_size = i;
2492 data += i;
2493 #if CONFIG_5GHz_SUPPORT
2494 i = 0;
2495 while ((i < (t_u16)pmadapter->tx_power_table_a_rows * (t_u16)pmadapter->tx_power_table_a_cols) &&
2496 (i < (tlv_buf_len - pmadapter->tx_power_table_bg_size)))
2497 {
2498 i++;
2499 }
2500 if (pmadapter->tx_power_table_a == MNULL)
2501 {
2502 ret = pcb->moal_malloc(pmadapter->pmoal_handle, i, MLAN_MEM_DEF,
2503 (t_u8 **)&pmadapter->tx_power_table_a);
2504 if ((ret != MLAN_STATUS_SUCCESS) || (pmadapter->tx_power_table_a == MNULL))
2505 {
2506 PRINTM(MERROR,
2507 "Memory allocation for the A-band"
2508 " power table failed!\n");
2509 break;
2510 }
2511 }
2512 if (i > 0U)
2513 {
2514 (void)__memcpy(pmadapter, pmadapter->tx_power_table_a, data, i);
2515 }
2516 pmadapter->tx_power_table_a_size = i;
2517 #endif
2518 break;
2519 case TLV_TYPE_POWER_TABLE_ATTR:
2520 pmadapter->tx_power_table_bg_rows = ((power_table_attr_t *)(void *)data)->rows_2g;
2521 pmadapter->tx_power_table_bg_cols = ((power_table_attr_t *)(void *)data)->cols_2g;
2522 #if CONFIG_5GHz_SUPPORT
2523 pmadapter->tx_power_table_a_rows = ((power_table_attr_t *)(void *)data)->rows_5g;
2524 pmadapter->tx_power_table_a_cols = ((power_table_attr_t *)(void *)data)->cols_5g;
2525 #endif
2526 break;
2527 default:
2528 PRINTM(MINFO, "Unexpected TLV \n");
2529 break;
2530 }
2531 tlv_buf += (sizeof(*head) + tlv_buf_len);
2532 tlv_buf_left -= ((t_u16)sizeof(*head) + tlv_buf_len);
2533 }
2534 if ((pmadapter->cfp_otp_bg == MNULL) || (pmadapter->tx_power_table_bg == MNULL))
2535 {
2536 goto out;
2537 }
2538 /* Set remaining flags for BG */
2539 rows = (int)pmadapter->tx_power_table_bg_rows;
2540 cols = (int)pmadapter->tx_power_table_bg_cols;
2541
2542 for (i = 0; i < (t_u16)rows; i++)
2543 {
2544 k = ((int)i * (int)cols) + (int)1U;
2545 if (((pmadapter->cfp_otp_bg + i)->dynamic.flags & NXP_CHANNEL_DISABLED) != 0U)
2546 {
2547 continue;
2548 }
2549
2550 if (pmadapter->tx_power_table_bg[k + (int)MOD_CCK] == 0U)
2551 {
2552 (pmadapter->cfp_otp_bg + i)->dynamic.flags |= NXP_CHANNEL_NO_CCK;
2553 }
2554
2555 if (pmadapter->tx_power_table_bg[k + (int)MOD_OFDM_PSK] == 0U &&
2556 pmadapter->tx_power_table_bg[k + (int)MOD_OFDM_QAM16] == 0U &&
2557 pmadapter->tx_power_table_bg[k + (int)MOD_OFDM_QAM64] == 0U)
2558 {
2559 (pmadapter->cfp_otp_bg + i)->dynamic.flags |= NXP_CHANNEL_NO_OFDM;
2560 }
2561 }
2562 out:
2563 LEAVE();
2564 }
2565
2566 /**
2567 * @brief This function deallocates otp cfp and power tables memory.
2568 *
2569 * @param pmadapter A pointer to mlan_adapter structure
2570 */
2571 void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
2572 {
2573 pmlan_callbacks pcb;
2574
2575 ENTER();
2576
2577 pcb = &pmadapter->callbacks;
2578 if (pmadapter->otp_region != NULL)
2579 {
2580 (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter->otp_region);
2581 }
2582 if (pmadapter->cfp_otp_bg != NULL)
2583 {
2584 (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter->cfp_otp_bg);
2585 }
2586 if (pmadapter->tx_power_table_bg != NULL)
2587 {
2588 (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter->tx_power_table_bg);
2589 }
2590 pmadapter->otp_region = MNULL;
2591 pmadapter->cfp_otp_bg = MNULL;
2592 pmadapter->tx_power_table_bg = MNULL;
2593 pmadapter->tx_power_table_bg_size = 0;
2594 #if CONFIG_5GHz_SUPPORT
2595 if (pmadapter->cfp_otp_a != NULL)
2596 {
2597 (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter->cfp_otp_a);
2598 }
2599 if (pmadapter->tx_power_table_a != NULL)
2600 {
2601 (void)pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter->tx_power_table_a);
2602 }
2603 pmadapter->cfp_otp_a = MNULL;
2604 pmadapter->tx_power_table_a = MNULL;
2605 pmadapter->tx_power_table_a_size = 0;
2606 #endif
2607 LEAVE();
2608 }
2609 #endif /* OTP_CHANINFO */
2610
2611 t_bool wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
2612 {
2613 t_u8 i;
2614 t_u32 meas_country_code_len = 0;
2615
2616 ENTER();
2617 /* Look for code in EU country code table */
2618 for (i = 0; i < NELEMENTS(eu_country_code_table); i++)
2619 {
2620 meas_country_code_len = COUNTRY_CODE_LEN - 1U;
2621 if (__memcmp(pmadapter, eu_country_code_table[i], country_code, meas_country_code_len) == 0)
2622 {
2623 LEAVE();
2624 return MTRUE;
2625 }
2626 }
2627
2628 LEAVE();
2629 return MFALSE;
2630 }
2631
2632 static oper_bw_chan *wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
2633 {
2634 t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
2635 int country_id = 0;
2636 oper_bw_chan *poper_bw_chan = MNULL;
2637 t_u32 meas_country_code_len = 0;
2638
2639 ENTER();
2640 for (country_id = 0; country_id < 3; country_id++)
2641 {
2642 meas_country_code_len = COUNTRY_CODE_LEN - 1U;
2643 if (__memcmp(pmpriv->adapter, pmpriv->adapter->country_code, country_code[country_id], meas_country_code_len) ==
2644 0)
2645 {
2646 break;
2647 }
2648 }
2649 if (country_id >= 3)
2650 {
2651 country_id = COUNTRY_ID_US; /*Set default to US*/
2652 }
2653 if (wlan_is_etsi_country(pmpriv->adapter, pmpriv->adapter->country_code))
2654 {
2655 country_id = COUNTRY_ID_EU; /** Country in EU */
2656 }
2657
2658 switch (country_id)
2659 {
2660 case COUNTRY_ID_US:
2661 poper_bw_chan = oper_bw_chan_us;
2662 *arraysize = (int)sizeof(oper_bw_chan_us);
2663 break;
2664 case COUNTRY_ID_JP:
2665 poper_bw_chan = oper_bw_chan_jp;
2666 *arraysize = (int)sizeof(oper_bw_chan_jp);
2667 break;
2668 case COUNTRY_ID_CN:
2669 poper_bw_chan = oper_bw_chan_cn;
2670 *arraysize = (int)sizeof(oper_bw_chan_cn);
2671 break;
2672 case COUNTRY_ID_EU:
2673 poper_bw_chan = oper_bw_chan_eu;
2674 *arraysize = (int)sizeof(oper_bw_chan_eu);
2675 break;
2676 default:
2677 PRINTM(MERROR, "Country not support!\n");
2678 break;
2679 }
2680
2681 LEAVE();
2682 return poper_bw_chan;
2683 }
2684
2685 mlan_status wlan_get_global_nonglobal_oper_class(
2686 mlan_private *pmpriv, t_u8 channel, t_u8 bw, t_u8 *oper_class, t_u8 *global_op_class)
2687 {
2688 oper_bw_chan *poper_bw_chan = MNULL;
2689 #if CONFIG_11AC
2690 t_u8 center_freq_idx = 0;
2691 #endif
2692 t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
2693 int i = 0, arraysize = 0, channum = 0, table_size = 0;
2694
2695 ENTER();
2696 poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
2697 if (poper_bw_chan == MNULL)
2698 {
2699 PRINTM(MCMND, "Operating class table do not find!\n");
2700 LEAVE();
2701 return MLAN_STATUS_FAILURE;
2702 }
2703 for (i = 0; i < (int)sizeof(center_freqs); i++)
2704 {
2705 if (channel == center_freqs[i])
2706 {
2707 PRINTM(MERROR, "Invalid channel number %d!\n", channel);
2708 LEAVE();
2709 return MLAN_STATUS_FAILURE;
2710 }
2711 }
2712 #if CONFIG_11AC
2713 if (bw == (t_u8)BW_80MHZ)
2714 {
2715 center_freq_idx = wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
2716 channel = center_freq_idx;
2717 }
2718 #endif
2719 table_size = arraysize / (int)sizeof(oper_bw_chan);
2720 for (i = 0; i < table_size; i++)
2721 {
2722 if (poper_bw_chan[i].bandwidth == bw)
2723 {
2724 for (channum = 0; channum < (int)(sizeof(poper_bw_chan[i].channel_list)); channum++)
2725 {
2726 if (poper_bw_chan[i].channel_list[channum] != (t_u8)0U &&
2727 poper_bw_chan[i].channel_list[channum] == channel)
2728 {
2729 if (oper_class != MNULL)
2730 {
2731 *oper_class = poper_bw_chan[i].oper_class;
2732 }
2733 if (global_op_class != MNULL)
2734 {
2735 *global_op_class = poper_bw_chan[i].global_oper_class;
2736 }
2737 return MLAN_STATUS_SUCCESS;
2738 }
2739 }
2740 }
2741 }
2742 PRINTM(MCMND, "Operating class not find!\n");
2743 LEAVE();
2744 return MLAN_STATUS_FAILURE;
2745 }
2746
2747 int wlan_add_supported_oper_class_ie(mlan_private *pmpriv, t_u8 **pptlv_out, t_u8 curr_oper_class)
2748 {
2749 t_u8 oper_class_us[] = {115,
2750 118,
2751 124,
2752 121,
2753 125,
2754 81,
2755 116,
2756 119,
2757 122,
2758 126,
2759 126,
2760 117,
2761 120,
2762 123,
2763 127,
2764 127,
2765 83,
2766 84
2767 #if CONFIG_11AC
2768 ,
2769 128,
2770 129,
2771 130
2772 #endif
2773 };
2774 t_u8 oper_class_eu[] = {115,
2775 118,
2776 121,
2777 81,
2778 116,
2779 119,
2780 122,
2781 117,
2782 120,
2783 123,
2784 83,
2785 84,
2786 125
2787 #if CONFIG_11AC
2788 ,
2789 128,
2790 129,
2791 130
2792 #endif
2793 };
2794 t_u8 oper_class_jp[] = {115,
2795 81,
2796 82,
2797 118,
2798 118,
2799 121,
2800 121,
2801 116,
2802 119,
2803 119,
2804 122,
2805 122,
2806 117,
2807 120,
2808 120,
2809 123,
2810 123,
2811 83,
2812 84,
2813 121
2814 #if CONFIG_11AC
2815 ,
2816 128,
2817 129,
2818 130
2819 #endif
2820 };
2821 t_u8 oper_class_cn[] = {115,
2822 118,
2823 125,
2824 116,
2825 119,
2826 126,
2827 81,
2828 83,
2829 84
2830 #if CONFIG_11AC
2831 ,
2832 128,
2833 129,
2834 130
2835 #endif
2836 };
2837 t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
2838 int country_id = 0, ret = 0;
2839 MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
2840 t_u32 meas_country_code_len = 0;
2841
2842 ENTER();
2843
2844 for (country_id = 0; country_id < 3; country_id++)
2845 {
2846 meas_country_code_len = COUNTRY_CODE_LEN - 1U;
2847 if (__memcmp(pmpriv->adapter, pmpriv->adapter->country_code, country_code[country_id], meas_country_code_len) ==
2848 0)
2849 {
2850 break;
2851 }
2852 }
2853 if (country_id >= 3)
2854 {
2855 country_id = COUNTRY_ID_US; /*Set default to US*/
2856 }
2857 if (wlan_is_etsi_country(pmpriv->adapter, pmpriv->adapter->country_code))
2858 {
2859 country_id = COUNTRY_ID_EU; /** Country in EU */
2860 }
2861 poper_class = (MrvlIETypes_SuppOperClass_t *)(void *)*pptlv_out;
2862 (void)__memset(pmpriv->adapter, poper_class, 0, sizeof(MrvlIETypes_SuppOperClass_t));
2863 poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
2864 if (country_id == COUNTRY_ID_US)
2865 {
2866 poper_class->header.len = (t_u16)sizeof(oper_class_us);
2867 (void)__memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_us, sizeof(oper_class_us));
2868 }
2869 else if (country_id == COUNTRY_ID_JP)
2870 {
2871 poper_class->header.len = (t_u16)sizeof(oper_class_jp);
2872 (void)__memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_jp, sizeof(oper_class_jp));
2873 }
2874 else if (country_id == COUNTRY_ID_CN)
2875 {
2876 poper_class->header.len = (t_u16)sizeof(oper_class_cn);
2877 (void)__memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_cn, sizeof(oper_class_cn));
2878 }
2879 else if (country_id == COUNTRY_ID_EU)
2880 {
2881 poper_class->header.len = (t_u16)sizeof(oper_class_eu);
2882 (void)__memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_eu, sizeof(oper_class_eu));
2883 }
2884 else
2885 {
2886 /* Do nothing */
2887 }
2888 poper_class->current_oper_class = curr_oper_class;
2889 poper_class->header.len += (t_u16)sizeof(poper_class->current_oper_class);
2890 DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class, sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
2891 ret = (int)sizeof(MrvlIEtypesHeader_t) + (int)poper_class->header.len;
2892 *pptlv_out += ret;
2893 poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
2894
2895 LEAVE();
2896 return ret;
2897 }
2898
2899 #if CONFIG_ECSA
2900 /**
2901 * @brief Check validation of given channel and oper class
2902 *
2903 * @param pmpriv A pointer to mlan_private structure
2904 * @param channel Channel number
2905 * @param oper_class operating class
2906 *
2907 * @return MLAN_STATUS_PENDING --success, otherwise fail
2908 */
2909 mlan_status wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel, t_u8 oper_class)
2910 {
2911 int arraysize = 0, i = 0, channum = 0;
2912 oper_bw_chan *poper_bw_chan = MNULL;
2913 #if CONFIG_11AC
2914 t_u8 center_freq_idx = 0;
2915 #endif
2916 t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
2917
2918 ENTER();
2919
2920 for (i = 0; i < (int)sizeof(center_freqs); i++)
2921 {
2922 if (channel == center_freqs[i])
2923 {
2924 PRINTM(MERROR, "Invalid channel number %d!\n", channel);
2925 LEAVE();
2926 return MLAN_STATUS_FAILURE;
2927 }
2928 }
2929 if (oper_class <= 0 || oper_class > 130)
2930 {
2931 PRINTM(MERROR, "Invalid operating class!\n");
2932 LEAVE();
2933 return MLAN_STATUS_FAILURE;
2934 }
2935 #if CONFIG_11AC
2936 if (oper_class >= 128)
2937 {
2938 center_freq_idx = wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
2939 channel = center_freq_idx;
2940 }
2941 #endif
2942 poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
2943
2944 if (!poper_bw_chan)
2945 {
2946 PRINTM(MCMND, "Operating class table do not find!\n");
2947 LEAVE();
2948 return MLAN_STATUS_FAILURE;
2949 }
2950
2951 for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++)
2952 {
2953 if (poper_bw_chan[i].oper_class == oper_class || poper_bw_chan[i].global_oper_class == oper_class)
2954 {
2955 for (channum = 0; channum < (int)sizeof(poper_bw_chan[i].channel_list); channum++)
2956 {
2957 if (poper_bw_chan[i].channel_list[channum] && poper_bw_chan[i].channel_list[channum] == channel)
2958 {
2959 LEAVE();
2960 return MLAN_STATUS_SUCCESS;
2961 }
2962 }
2963 }
2964 }
2965
2966 PRINTM(MCMND, "Operating class %d do not match channel %d!\n", oper_class, channel);
2967 LEAVE();
2968 return MLAN_STATUS_FAILURE;
2969 }
2970 #endif
2971