1 /**
2 * @file mlan_cfp.c
3 *
4 * @brief This file contains WLAN client mode channel, frequency and power
5 * related code
6 *
7 *
8 * Copyright 2009-2022 NXP
9 *
10 * This software file (the File) is distributed by NXP
11 * under the terms of the GNU General Public License Version 2, June 1991
12 * (the License). You may use, redistribute and/or modify the File in
13 * accordance with the terms and conditions of the License, a copy of which
14 * is available by writing to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
16 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
17 *
18 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
20 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
21 * this warranty disclaimer.
22 *
23 */
24
25 /*************************************************************
26 * Change Log:
27 * 04/16/2009: initial version
28 ************************************************************/
29
30 #include "mlan.h"
31 #include "mlan_util.h"
32 #include "mlan_fw.h"
33 #include "mlan_join.h"
34 #include "mlan_main.h"
35
36 /********************************************************
37 * Local Variables
38 ********************************************************/
39
40 /** 100mW */
41 #define WLAN_TX_PWR_DEFAULT 20
42 /** 100mW */
43 #define WLAN_TX_PWR_00_DEFAULT 20
44 /** 100mW */
45 #define WLAN_TX_PWR_US_DEFAULT 20
46 /** 100mW */
47 #define WLAN_TX_PWR_JP_BG_DEFAULT 20
48 /** 200mW */
49 #define WLAN_TX_PWR_JP_A_DEFAULT 23
50 /** 100mW */
51 #define WLAN_TX_PWR_EMEA_DEFAULT 20
52 /** 2000mW */
53 #define WLAN_TX_PWR_CN_2000MW 33
54 /** 200mW */
55 #define WLAN_TX_PWR_200MW 23
56 /** 1000mW */
57 #define WLAN_TX_PWR_1000MW 30
58 /** 250mW */
59 #define WLAN_TX_PWR_250MW 24
60
61 /** Region code mapping */
62 typedef struct _country_code_mapping {
63 /** Region */
64 t_u8 country_code[COUNTRY_CODE_LEN];
65 /** Code for B/G CFP table */
66 t_u8 cfp_code_bg;
67 /** Code for A CFP table */
68 t_u8 cfp_code_a;
69 } country_code_mapping_t;
70
71 #define EU_CFP_CODE_BG 0x30
72 #define EU_CFP_CODE_A 0x30
73
74 /** Region code mapping table */
75 static country_code_mapping_t country_code_mapping[] = {
76 {"WW", 0x00, 0x00}, /* World */
77 {"US", 0x10, 0x10}, /* US FCC */
78 {"CA", 0x10, 0x20}, /* IC Canada */
79 {"SG", 0x10, 0x10}, /* Singapore */
80 {"EU", 0x30, 0x30}, /* ETSI */
81 {"AU", 0x30, 0x30}, /* Australia */
82 {"KR", 0x30, 0x30}, /* Republic Of Korea */
83 {"JP", 0xFF, 0x40}, /* Japan */
84 {"CN", 0x30, 0x50}, /* China */
85 {"BR", 0x01, 0x09}, /* Brazil */
86 {"RU", 0x30, 0x0f}, /* Russia */
87 {"IN", 0x10, 0x06}, /* India */
88 {"MY", 0x30, 0x06}, /* Malaysia */
89 {"NZ", 0x30, 0x30}, /* New Zeland */
90 {"MX", 0x10, 0x07}, /* Mexico */
91 };
92
93 /** Country code for ETSI */
94 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
95 "AL", "AD", "AT", "AU", "BE", "BA", "BG", "HR", "CY", "CZ", "DK", "EE",
96 "FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "LV", "LI", "LT",
97 "LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "SM", "RS", "SI",
98 "SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NZ", "DZ", "AO", "AM",
99 "AW", "BH", "BD", "BT", "BO", "BQ", "BW", "VG", "BF", "BI", "KH", "CL",
100 "KM", "CG", "CD", "CW", "EG", "FO", "GF", "PF", "GE", "GI", "GP", "HK",
101 "IN", "ID", "IM", "IL", "JE", "KE", "XK", "KW", "LA", "LR", "MW", "MV",
102 "MQ", "MR", "YT", "MA", "MZ", "MM", "NA", "NC", "NE", "NG", "OM", "PS",
103 "PT", "QA", "RW", "RE", "BL", "MF", "VC", "SA", "SC", "ZA", "SZ", "SY",
104 "TZ", "TG", "TN", "AE", "VA", "EH", "YE", "ZM", "ZW"};
105
106 /**
107 * The structure for Channel-Frequency-Power table
108 */
109 typedef struct _cfp_table {
110 /** Region or Code */
111 t_u8 code;
112 /** Frequency/Power */
113 chan_freq_power_t *cfp;
114 /** No of CFP flag */
115 int cfp_no;
116 } cfp_table_t;
117
118 /* Format { Channel, Frequency (MHz), MaxTxPower } */
119 /** Band : 'B/G', Region: World Wide Safe */
120 static chan_freq_power_t channel_freq_power_00_BG[] = {
121 {1, 2412, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
122 {2, 2417, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
123 {3, 2422, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
124 {4, 2427, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
125 {5, 2432, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
126 {6, 2437, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
127 {7, 2442, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
128 {8, 2447, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
129 {9, 2452, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
130 {10, 2457, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
131 {11, 2462, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x1c, 0, 0}},
132 {12, 2467, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1d, 0, 0}},
133 {13, 2472, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x1d, 0, 0}}};
134 /* Format { Channel, Frequency (MHz), MaxTxPower } */
135 /** Band: 'B/G', Region: USA FCC/Canada IC */
136 static chan_freq_power_t channel_freq_power_US_BG[] = {
137 {1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
138 {2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
139 {3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
140 {4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
141 {5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
142 {6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
143 {7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
144 {8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
145 {9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
146 {10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}},
147 {11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x1c, 0, 0}}};
148
149 /** Band: 'B/G', Region: Europe ETSI/China */
150 static chan_freq_power_t channel_freq_power_EU_BG[] = {
151 {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
152 {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
153 {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
154 {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
155 {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
156 {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
157 {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
158 {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
159 {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
160 {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
161 {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
162 {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}},
163 {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x1c, 0, 0}}};
164
165 /** Band: 'B/G', Region: Japan */
166 static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
167 {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
168 {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
169 {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
170 {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
171 {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
172 {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
173 {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
174 {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
175 {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
176 {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
177 {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
178 {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
179 {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}}};
180
181 /** Band: 'B/G', Region: Japan */
182 static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
183 {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1d, 0, 0}}};
184
185 /** Band: 'B/G', Region: Japan */
186 static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
187 {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
188 {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
189 {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
190 {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
191 {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
192 {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
193 {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
194 {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
195 {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
196 {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
197 {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
198 {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE, {0x1d, 0, 0}},
199 {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE, {0x1d, 0, 0}}};
200
201 /** Band : 'B/G', Region: Brazil */
202 static chan_freq_power_t channel_freq_power_BR_BG[] = {
203 {1, 2412, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
204 {2, 2417, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
205 {3, 2422, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
206 {4, 2427, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
207 {5, 2432, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
208 {6, 2437, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
209 {7, 2442, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
210 {8, 2447, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
211 {9, 2452, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
212 {10, 2457, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
213 {11, 2462, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
214 {12, 2467, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}},
215 {13, 2472, WLAN_TX_PWR_1000MW, MFALSE, {0x1c, 0, 0}}};
216
217 /** Band : 'B/G', Region: Special */
218 static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
219 {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
220 {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
221 {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
222 {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
223 {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
224 {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
225 {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
226 {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
227 {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
228 {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
229 {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
230 {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
231 {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}},
232 {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE, {0x1c, 0, 0}}};
233
234 /**
235 * The 2.4GHz CFP tables
236 */
237 static cfp_table_t cfp_table_BG[] = {
238 {
239 0x01, /* Brazil */
240 channel_freq_power_BR_BG,
241 NELEMENTS(channel_freq_power_BR_BG),
242 },
243 {
244 0x00, /* World FCC */
245 channel_freq_power_00_BG,
246 NELEMENTS(channel_freq_power_00_BG),
247 },
248 {
249 0x10, /* US FCC */
250 channel_freq_power_US_BG,
251 NELEMENTS(channel_freq_power_US_BG),
252 },
253 {
254 0x20, /* CANADA IC */
255 channel_freq_power_US_BG,
256 NELEMENTS(channel_freq_power_US_BG),
257 },
258 {
259 0x30, /* EU */
260 channel_freq_power_EU_BG,
261 NELEMENTS(channel_freq_power_EU_BG),
262 },
263 {
264 0x40, /* JAPAN */
265 channel_freq_power_JPN40_BG,
266 NELEMENTS(channel_freq_power_JPN40_BG),
267 },
268 {
269 0x41, /* JAPAN */
270 channel_freq_power_JPN41_BG,
271 NELEMENTS(channel_freq_power_JPN41_BG),
272 },
273 {
274 0x50, /* China */
275 channel_freq_power_EU_BG,
276 NELEMENTS(channel_freq_power_EU_BG),
277 },
278 {
279 0xfe, /* JAPAN */
280 channel_freq_power_JPNFE_BG,
281 NELEMENTS(channel_freq_power_JPNFE_BG),
282 },
283 {
284 0xff, /* Special */
285 channel_freq_power_SPECIAL_BG,
286 NELEMENTS(channel_freq_power_SPECIAL_BG),
287 },
288 /* Add new region here */
289 };
290
291 /** Number of the CFP tables for 2.4GHz */
292 #define MLAN_CFP_TABLE_SIZE_BG (NELEMENTS(cfp_table_BG))
293
294 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
295 /** Band: 'A', Region: World Wide Safe */
296 static chan_freq_power_t channel_freq_power_00_A[] = {
297 {36, 5180, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
298 {40, 5200, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
299 {44, 5220, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
300 {48, 5240, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
301 {52, 5260, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
302 {56, 5280, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
303 {60, 5300, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
304 {64, 5320, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
305 {100, 5500, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
306 {104, 5520, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
307 {108, 5540, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
308 {112, 5560, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
309 {116, 5580, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
310 {120, 5600, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
311 {124, 5620, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
312 {128, 5640, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
313 {132, 5660, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
314 {136, 5680, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
315 {140, 5700, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
316 {144, 5720, WLAN_TX_PWR_00_DEFAULT, MTRUE, {0x13, 0, 0}},
317 {149, 5745, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
318 {153, 5765, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
319 {157, 5785, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
320 {161, 5805, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}},
321 {165, 5825, WLAN_TX_PWR_00_DEFAULT, MFALSE, {0x10, 0, 0}}};
322 /* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
323 /** Band: 'A', Region: USA FCC */
324 static chan_freq_power_t channel_freq_power_A[] = {
325 {36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
326 {40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
327 {44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
328 {48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
329 {52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
330 {56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
331 {60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
332 {64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
333 {100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
334 {104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
335 {108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
336 {112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
337 {116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
338 {120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
339 {124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
340 {128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
341 {132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
342 {136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
343 {140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
344 {144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
345 {149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
346 {153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
347 {157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
348 {161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
349 {165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
350 {169, 5845, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
351 {173, 5865, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
352 {177, 5885, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}}};
353
354 /** Band: 'A', Region: Canada IC */
355 static chan_freq_power_t channel_freq_power_CAN_A[] = {
356 {36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
357 {40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
358 {44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
359 {48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
360 {52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
361 {56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
362 {60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
363 {64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
364 {100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
365 {104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
366 {108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
367 {112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
368 {116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
369 {132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
370 {136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
371 {140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
372 {144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE, {0x13, 0, 0}},
373 {149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
374 {153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
375 {157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
376 {161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}},
377 {165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE, {0x10, 0, 0}}};
378
379 /** Band: 'A', Region: Europe ETSI */
380 static chan_freq_power_t channel_freq_power_EU_A[] = {
381 {36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
382 {40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
383 {44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
384 {48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
385 {52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
386 {56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
387 {60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
388 {64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
389 {100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
390 {104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
391 {108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
392 {112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
393 {116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
394 {120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
395 {124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
396 {128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
397 {132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
398 {136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
399 {140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
400 {149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
401 {153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
402 {157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
403 {161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
404 {165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}}};
405
406 /** Band: 'A', Region: Japan */
407 static chan_freq_power_t channel_freq_power_JPN_A[] = {
408 {36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
409 {40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
410 {44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
411 {48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE, {0x10, 0, 0}},
412 {52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
413 {56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
414 {60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
415 {64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
416 {100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
417 {104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
418 {108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
419 {112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
420 {116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
421 {120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
422 {124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
423 {128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
424 {132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
425 {136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
426 {140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}},
427 {144, 5720, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE, {0x13, 0, 0}}};
428
429 /** Band: 'A', Region: China */
430 static chan_freq_power_t channel_freq_power_CN_A[] = {
431 {36, 5180, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
432 {40, 5200, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
433 {44, 5220, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
434 {48, 5240, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
435 {52, 5260, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
436 {56, 5280, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
437 {60, 5300, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
438 {64, 5320, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
439 {149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
440 {153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
441 {157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
442 {161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}},
443 {165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE, {0x10, 0, 0}}};
444
445 /** Band: 'A', NULL */
446 static chan_freq_power_t channel_freq_power_NULL_A[] = {};
447
448 /** Band: 'A', Region: Spain/Austria/Brazil */
449 static chan_freq_power_t channel_freq_power_SPN2_A[] = {
450 {36, 5180, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
451 {40, 5200, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
452 {44, 5220, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
453 {48, 5240, WLAN_TX_PWR_200MW, MFALSE, {0x10, 0, 0}},
454 {52, 5260, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
455 {56, 5280, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
456 {60, 5300, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}},
457 {64, 5320, WLAN_TX_PWR_200MW, MTRUE, {0x13, 0, 0}}};
458
459 /** Band: 'A', Region: Brazil */
460 static chan_freq_power_t channel_freq_power_BR1_A[] = {
461 {100, 5500, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
462 {104, 5520, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
463 {108, 5540, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
464 {112, 5560, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
465 {116, 5580, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
466 {120, 5600, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
467 {124, 5620, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
468 {128, 5640, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
469 {132, 5660, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
470 {136, 5680, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}},
471 {140, 5700, WLAN_TX_PWR_250MW, MTRUE, {0x13, 0, 0}}};
472
473 /** Band: 'A', Region: Brazil */
474 static chan_freq_power_t channel_freq_power_BR2_A[] = {
475 {149, 5745, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
476 {153, 5765, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
477 {157, 5785, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
478 {161, 5805, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}},
479 {165, 5825, WLAN_TX_PWR_1000MW, MFALSE, {0x10, 0, 0}}};
480
481 /** Band: 'A', Region: Russia */
482 static chan_freq_power_t channel_freq_power_RU_A[] = {
483 {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
484 {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
485 {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
486 {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
487 {52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
488 {56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
489 {60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
490 {64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
491 {132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
492 {136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
493 {140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
494 {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
495 {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
496 {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
497 {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
498
499 /** Band: 'A', Region: Mexico */
500 static chan_freq_power_t channel_freq_power_MX_A[] = {
501 {36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
502 {40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
503 {44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
504 {48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
505 {52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
506 {56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
507 {60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
508 {64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
509 {100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
510 {104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
511 {108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
512 {112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
513 {116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
514 {132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
515 {136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
516 {140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE, {0x13, 0, 0}},
517 {149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
518 {153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
519 {157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
520 {161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}},
521 {165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE, {0x10, 0, 0}}};
522
523 /** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
524 static chan_freq_power_t channel_freq_power_low_band[] = {
525 {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
526 {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
527 {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
528 {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
529
530 /** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
531 static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
532 {52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
533 {56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
534 {60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
535 {64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}}};
536
537 /** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
538 static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
539 {100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
540 {104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
541 {108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
542 {112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
543 {116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
544 {120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
545 {124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
546 {128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
547 {132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
548 {136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}},
549 {140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE, {0x13, 0, 0}}};
550
551 /** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
552 static chan_freq_power_t channel_freq_power_high_band[] = {
553 {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
554 {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
555 {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
556 {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
557 {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
558
559 /** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
560 * High band (5725-5850 MHz) channels
561 */
562 static chan_freq_power_t channel_freq_power_low_high_band[] = {
563 {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
564 {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
565 {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
566 {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
567 {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
568 {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
569 {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
570 {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
571 {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
572
573 /** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
574 * mid low (5260-5320) and High band (5725-5850 MHz) channels
575 */
576 static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
577 {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
578 {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
579 {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
580 {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
581 {52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
582 {56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
583 {60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
584 {64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
585 {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
586 {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
587 {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
588 {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}},
589 {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE, {0x10, 0, 0}}};
590
591 /**
592 * The 5GHz CFP tables
593 */
594 static cfp_table_t cfp_table_A[] = {
595 {0x1, /* Low band (5150-5250 MHz) channels */
596 channel_freq_power_low_band, NELEMENTS(channel_freq_power_low_band)},
597 {0x2, /* Lower middle band (5250-5350 MHz) channels */
598 channel_freq_power_lower_middle_band,
599 NELEMENTS(channel_freq_power_lower_middle_band)},
600 {0x3, /* Upper middle band (5470-5725 MHz) channels */
601 channel_freq_power_upper_middle_band,
602 NELEMENTS(channel_freq_power_upper_middle_band)},
603 {0x4, /* High band (5725-5850 MHz) channels */
604 channel_freq_power_high_band, NELEMENTS(channel_freq_power_high_band)},
605 {0x5, /* Low band (5150-5250 MHz) and
606 * High band (5725-5850 MHz) channels
607 */
608 channel_freq_power_low_high_band,
609 NELEMENTS(channel_freq_power_low_high_band)},
610 {0x6, /* Low band (5150-5250 MHz)
611 * Mid band (5260-5320) and
612 * High band (5725-5850 MHz) channels
613 */
614 channel_freq_power_low_middle_high_band,
615 NELEMENTS(channel_freq_power_low_middle_high_band)},
616 {
617 0x07, /* Mexico */
618 channel_freq_power_MX_A,
619 NELEMENTS(channel_freq_power_MX_A),
620 },
621
622 {
623 0x09, /* SPAIN/Austria/Brazil */
624 channel_freq_power_SPN2_A,
625 NELEMENTS(channel_freq_power_SPN2_A),
626 },
627 {
628 0x0c, /* Brazil */
629 channel_freq_power_BR1_A,
630 NELEMENTS(channel_freq_power_BR1_A),
631 },
632 {
633 0x0e, /* Brazil */
634 channel_freq_power_BR2_A,
635 NELEMENTS(channel_freq_power_BR2_A),
636 },
637 {
638 0x0f, /* Russia */
639 channel_freq_power_RU_A,
640 NELEMENTS(channel_freq_power_RU_A),
641 },
642 {
643 0x00, /* World */
644 channel_freq_power_00_A,
645 NELEMENTS(channel_freq_power_00_A),
646 },
647 {
648 0x10, /* US FCC */
649 channel_freq_power_A,
650 NELEMENTS(channel_freq_power_A),
651 },
652 {
653 0x20, /* CANADA IC */
654 channel_freq_power_CAN_A,
655 NELEMENTS(channel_freq_power_CAN_A),
656 },
657 {
658 0x30, /* EU */
659 channel_freq_power_EU_A,
660 NELEMENTS(channel_freq_power_EU_A),
661 },
662 {
663 0x40, /* JAPAN */
664 channel_freq_power_JPN_A,
665 NELEMENTS(channel_freq_power_JPN_A),
666 },
667 {
668 0x41, /* JAPAN */
669 channel_freq_power_JPN_A,
670 NELEMENTS(channel_freq_power_JPN_A),
671 },
672 {
673 0x50, /* China */
674 channel_freq_power_CN_A,
675 NELEMENTS(channel_freq_power_CN_A),
676 },
677 {
678 0xfe, /* JAPAN */
679 channel_freq_power_NULL_A,
680 NELEMENTS(channel_freq_power_NULL_A),
681 },
682 {
683 0xff, /* Special */
684 channel_freq_power_JPN_A,
685 NELEMENTS(channel_freq_power_JPN_A),
686 },
687 /* Add new region here */
688 };
689 /** Number of the CFP tables for 5GHz */
690 #define MLAN_CFP_TABLE_SIZE_A (NELEMENTS(cfp_table_A))
691
692 enum { RATEID_DBPSK1Mbps, //(0)
693 RATEID_DQPSK2Mbps, //(1)
694 RATEID_CCK5_5Mbps, //(2)
695 RATEID_CCK11Mbps, //(3)
696 RATEID_CCK22Mbps, //(4)
697 RATEID_OFDM6Mbps, //(5)
698 RATEID_OFDM9Mbps, //(6)
699 RATEID_OFDM12Mbps, //(7)
700 RATEID_OFDM18Mbps, //(8)
701 RATEID_OFDM24Mbps, //(9)
702 RATEID_OFDM36Mbps, //(10)
703 RATEID_OFDM48Mbps, //(11)
704 RATEID_OFDM54Mbps, //(12)
705 RATEID_OFDM72Mbps, //(13)
706 };
707
708 static const t_u8 rateUnit_500Kbps[] = {
709 (10 / 5), /* 1Mbps */
710 (20 / 5), /* 2Mbps */
711
712 (55 / 5), /* 5.5Mbps */
713 (110 / 5), /* 11Mbps */
714 (10 / 5), /* 22Mbps, intentionally set to 1Mbps
715 * because it's not available
716 */
717
718 (60 / 5), /* 6Mbps */
719 (90 / 5), /* 9Mbps */
720 (120 / 5), /* 12Mbps */
721 (180 / 5), /* 18Mbps */
722 (240 / 5), /* 24Mbps */
723 (360 / 5), /* 36Mbps */
724 (480 / 5), /* 48Mbps */
725 (540 / 5), /* 54Mbps */
726 (60 / 5), /* 72Mbps, intentionally set to 6Mbps
727 * because it's not available
728 */
729 };
730
731 typedef struct _rate_map {
732 /** Rate, in 0.5Mbps */
733 t_u32 rate;
734 /** Mrvl rate id, refer to RATEID_XXX in FW */
735 t_u32 id;
736 /** nss: 0-nss1, 1-nss2 */
737 t_u8 nss;
738 } rate_map;
739
740 /** If user configure to 1x1 or we found peer device only support 1x1,
741 * then we need skip the nss1 part when map to Mrvl rate.
742 */
743 static const rate_map rate_map_table_2x2[] = {
744 /* LG <--> Mrvl rate idx */
745 {2, 0, 0}, // RATEID_DBPSK1Mbps
746 {4, 1, 0}, // RATEID_DQPSK2Mbps
747 {11, 2, 0}, // RATEID_CCK5_5Mbps
748 {22, 3, 0}, // RATEID_CCK11Mbps
749 {44, 4, 0}, // RATEID_CCK22Mbps
750 {12, 5, 0}, // RATEID_OFDM6Mbps
751 {18, 6, 0}, // RATEID_OFDM9Mbps
752 {24, 7, 0}, // RATEID_OFDM12Mbps
753 {36, 8, 0}, // RATEID_OFDM18Mbps
754 {48, 9, 0}, // RATEID_OFDM24Mbps
755 {72, 10, 0}, // RATEID_OFDM36Mbps
756 {96, 11, 0}, // RATEID_OFDM48Mbps
757 {108, 12, 0}, // RATEID_OFDM54Mbps
758 {144, 13, 0}, // RATEID_OFDM72Mbps
759
760 /* HT bw20 <--> Mrvl rate idx - nss2 */
761 {26, 22, 1}, // RATEID_MCS8_13Mbps
762 {52, 23, 1}, // RATEID_MCS9_26Mbps
763 {78, 24, 1}, // RATEID_MCS10_39Mbps
764 {104, 25, 1}, // RATEID_MCS11_52Mbps
765 {156, 26, 1}, // RATEID_MCS12_78Mbps
766 {208, 27, 1}, // RATEID_MCS13_104Mbps
767 {234, 28, 1}, // RATEID_MCS14_117Mbps
768 {260, 29, 1}, // RATEID_MCS15_130Mbps
769 /* HT bw20 <--> Mrvl rate idx - nss1 */
770 {13, 14, 0}, // RATEID_MCS0_6d5Mbps
771 {26, 15, 0}, // RATEID_MCS1_13Mbps
772 {39, 16, 0}, // RATEID_MCS2_19d5Mbps
773 {52, 17, 0}, // RATEID_MCS3_26Mbps
774 {78, 18, 0}, // RATEID_MCS4_39Mbps
775 {104, 19, 0}, // RATEID_MCS5_52Mbps
776 {117, 20, 0}, // RATEID_MCS6_58d5Mbps
777 {130, 21, 0}, // RATEID_MCS7_65Mbps
778
779 /* HT bw40<--> Mrvl rate idx - nss2 */
780 {54, 39, 1}, // RATEID_MCS8BW40_27Mbps
781 {108, 40, 1}, // RATEID_MCS9BW40_54Mbps
782 {162, 41, 1}, // RATEID_MCS10BW40_81Mbps
783 {216, 42, 1}, // RATEID_MCS11BW40_108Mbps
784 {324, 43, 1}, // RATEID_MCS12BW40_162Mbps
785 {432, 44, 1}, // RATEID_MCS13BW40_216Mbps
786 {486, 45, 1}, // RATEID_MCS14BW40_243Mbps
787 {540, 46, 1}, // RATEID_MCS15BW40_270Mbps
788 /* HT bw40<--> Mrvl rate idx - nss1 */
789 {12, 30, 0}, // RATEID_MCS32BW40_6Mbps
790 {27, 31, 0}, // RATEID_MCS0BW40_13d5Mbps
791 {54, 32, 0}, // RATEID_MCS1BW40_27Mbps
792 {81, 33, 0}, // RATEID_MCS2BW40_40d5Mbps
793 {108, 34, 0}, // RATEID_MCS3BW40_54Mbps
794 {162, 35, 0}, // RATEID_MCS4BW40_81Mbps
795 {216, 36, 0}, // RATEID_MCS5BW40_108Mbps
796 {243, 37, 0}, // RATEID_MCS6BW40_121d5Mbps
797 {270, 38, 0}, // RATEID_MCS7BW40_135Mbps
798
799 /* VHT bw20<--> Mrvl rate idx - nss2 */
800 {26, 57, 1}, // RATEID_VHT_MCS0_2SS_BW20 13 Mbps
801 {52, 58, 1}, // RATEID_VHT_MCS1_2SS_BW20 26 Mbps
802 {78, 59, 1}, // RATEID_VHT_MCS2_2SS_BW20 39 Mbps
803 {104, 60, 1}, // RATEID_VHT_MCS3_2SS_BW20 52 Mbps
804 {156, 61, 1}, // RATEID_VHT_MCS4_2SS_BW20 78 Mbps
805 {208, 62, 1}, // RATEID_VHT_MCS5_2SS_BW20 104 Mbps
806 {234, 63, 1}, // RATEID_VHT_MCS6_2SS_BW20 117 Mbps
807 {260, 64, 1}, // RATEID_VHT_MCS7_2SS_BW20 130 Mbps
808 {312, 65, 1}, // RATEID_VHT_MCS8_2SS_BW20 156 Mbps
809 {0, 66, 1}, // RATEID_VHT_MCS9_2SS_BW20 173.3 Mbps(INVALID)
810 /* VHT bw20<--> Mrvl rate idx - nss1 */
811 {13, 47, 0}, // RATEID_VHT_MCS0_1SS_BW20 6.5 Mbps
812 {26, 48, 0}, // RATEID_VHT_MCS1_1SS_BW20 13 Mbps
813 {39, 49, 0}, // RATEID_VHT_MCS2_1SS_BW20 19.5 Mbps
814 {52, 50, 0}, // RATEID_VHT_MCS3_1SS_BW20 26 Mbps
815 {78, 51, 0}, // RATEID_VHT_MCS4_1SS_BW20 39 Mbps
816 {104, 52, 0}, // RATEID_VHT_MCS5_1SS_BW20 52 Mbps
817 {117, 53, 0}, // RATEID_VHT_MCS6_1SS_BW20 58.5 Mbps
818 {130, 54, 0}, // RATEID_VHT_MCS7_1SS_BW20 65 Mbps
819 {156, 55, 0}, // RATEID_VHT_MCS8_1SS_BW20 78 Mbps
820 {0, 56, 0}, // RATEID_VHT_MCS9_1SS_BW20 86.7 Mbps(INVALID)
821
822 /* VHT bw40<--> Mrvl rate idx - nss2 */
823 {54, 77, 1}, // RATEID_VHT_MCS0_2SS_BW40 27 Mbps
824 {108, 78, 1}, // RATEID_VHT_MCS1_2SS_BW40 54 Mbps
825 {162, 79, 1}, // RATEID_VHT_MCS2_2SS_BW40 81 Mbps
826 {216, 80, 1}, // RATEID_VHT_MCS3_2SS_BW40 108 Mbps
827 {324, 81, 1}, // RATEID_VHT_MCS4_2SS_BW40 162 Mbps
828 {432, 82, 1}, // RATEID_VHT_MCS5_2SS_BW40 216 Mbps
829 {486, 83, 1}, // RATEID_VHT_MCS6_2SS_BW40 243 Mbps
830 {540, 84, 1}, // RATEID_VHT_MCS7_2SS_BW40 270 Mbps
831 {648, 85, 1}, // RATEID_VHT_MCS8_2SS_BW40 324 Mbps
832 {720, 86, 1}, // RATEID_VHT_MCS9_2SS_BW40 360 Mbps
833 /* VHT bw40<--> Mrvl rate idx - nss1 */
834 {27, 67, 0}, // RATEID_VHT_MCS0_1SS_BW40 13.5 Mbps
835 {54, 68, 0}, // RATEID_VHT_MCS1_1SS_BW40 27 Mbps
836 {81, 69, 0}, // RATEID_VHT_MCS2_1SS_BW40 40.5 Mbps
837 {108, 70, 0}, // RATEID_VHT_MCS3_1SS_BW40 54 Mbps
838 {162, 71, 0}, // RATEID_VHT_MCS4_1SS_BW40 81 Mbps
839 {216, 72, 0}, // RATEID_VHT_MCS5_1SS_BW40 108 Mbps
840 {243, 73, 0}, // RATEID_VHT_MCS6_1SS_BW40 121.5 Mbps
841 {270, 74, 0}, // RATEID_VHT_MCS7_1SS_BW40 135 Mbps
842 {324, 75, 0}, // RATEID_VHT_MCS8_1SS_BW40 162 Mbps
843 {360, 76, 0}, // RATEID_VHT_MCS9_1SS_BW40 180 Mbps
844
845 /* VHT bw80<--> Mrvl rate idx - nss2 */
846 {117, 97, 1}, // RATEID_VHT_MCS0_2SS_BW80 58.5 Mbps
847 {234, 98, 1}, // RATEID_VHT_MCS1_2SS_BW80 117 Mbps
848 {350, 99, 1}, // RATEID_VHT_MCS2_2SS_BW80 175 Mbps
849 {468, 100, 1}, // RATEID_VHT_MCS3_2SS_BW80 234 Mbps
850 {702, 101, 1}, // RATEID_VHT_MCS4_2SS_BW80 351 Mbps
851 {936, 102, 1}, // RATEID_VHT_MCS5_2SS_BW80 468 Mbps
852 {1053, 103, 1}, // RATEID_VHT_MCS6_2SS_BW80 526.5 Mbps
853 {1170, 104, 1}, // RATEID_VHT_MCS7_2SS_BW80 585 Mbps
854 {1404, 105, 1}, // RATEID_VHT_MCS8_2SS_BW80 702 Mbps
855 {1560, 106, 1}, // RATEID_VHT_MCS9_2SS_BW80 780 Mbps
856 /* VHT bw80<--> Mrvl rate idx - nss1 */
857 {58, 87, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could
858 // correspond to 58
859 {59, 87, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3*2 could
860 // correspond to 59 too
861 {117, 88, 0}, // RATEID_VHT_MCS1_1SS_BW80 58.5 Mbps
862 {175, 89, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
863 // correspond to 175
864 {176, 89, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
865 // correspond to 176 too
866 {234, 90, 0}, // RATEID_VHT_MCS3_1SS_BW80 117 Mbps
867 {351, 91, 0}, // RATEID_VHT_MCS4_1SS_BW80 175.5 Mbps
868 {468, 92, 0}, // RATEID_VHT_MCS5_1SS_BW80 234 Mbps
869 {526, 93, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
870 // correspond to 526
871 {527, 93, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
872 // correspond to 527 too
873 {585, 94, 0}, // RATEID_VHT_MCS7_1SS_BW80 292.5 Mbps
874 {702, 95, 0}, // RATEID_VHT_MCS8_1SS_BW80 351 Mbps
875 {780, 96, 0}, // RATEID_VHT_MCS9_1SS_BW80 390 Mbps
876 };
877
878 /** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
879 * For the chip who only support 1x1, Mrvl rate idx define is different with 2x2
880 * in FW We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
881 */
882 static const rate_map rate_map_table_1x1[] = {
883 /* LG <--> Mrvl rate idx */
884 {2, 0, 0}, // RATEID_DBPSK1Mbps
885 {4, 1, 0}, // RATEID_DQPSK2Mbps
886 {11, 2, 0}, // RATEID_CCK5_5Mbps
887 {22, 3, 0}, // RATEID_CCK11Mbps
888 {44, 4, 0}, // RATEID_CCK22Mbps
889 {12, 5, 0}, // RATEID_OFDM6Mbps
890 {18, 6, 0}, // RATEID_OFDM9Mbps
891 {24, 7, 0}, // RATEID_OFDM12Mbps
892 {36, 8, 0}, // RATEID_OFDM18Mbps
893 {48, 9, 0}, // RATEID_OFDM24Mbps
894 {72, 10, 0}, // RATEID_OFDM36Mbps
895 {96, 11, 0}, // RATEID_OFDM48Mbps
896 {108, 12, 0}, // RATEID_OFDM54Mbps
897 {144, 13, 0}, // RATEID_OFDM72Mbps
898
899 /* HT bw20 <--> Mrvl rate idx */
900 {13, 14, 0}, // RATEID_MCS0_6d5Mbps
901 {26, 15, 0}, // RATEID_MCS1_13Mbps
902 {39, 16, 0}, // RATEID_MCS2_19d5Mbps
903 {52, 17, 0}, // RATEID_MCS3_26Mbps
904 {78, 18, 0}, // RATEID_MCS4_39Mbps
905 {104, 19, 0}, // RATEID_MCS5_52Mbps
906 {117, 20, 0}, // RATEID_MCS6_58d5Mbps
907 {130, 21, 0}, // RATEID_MCS7_65Mbps
908
909 /* HT bw40<--> Mrvl rate idx */
910 {12, 22, 0}, // RATEID_MCS32BW40_6Mbps, for 1x1 start from 22
911 {27, 23, 0}, // RATEID_MCS0BW40_13d5Mbps
912 {54, 24, 0}, // RATEID_MCS1BW40_27Mbps
913 {81, 25, 0}, // RATEID_MCS2BW40_40d5Mbps
914 {108, 26, 0}, // RATEID_MCS3BW40_54Mbps
915 {162, 27, 0}, // RATEID_MCS4BW40_81Mbps
916 {216, 28, 0}, // RATEID_MCS5BW40_108Mbps
917 {243, 29, 0}, // RATEID_MCS6BW40_121d5Mbps
918 {270, 30, 0}, // RATEID_MCS7BW40_135Mbps
919
920 /* VHT bw20<--> Mrvl rate idx */
921 {13, 31, 0}, // RATEID_VHT_MCS0_1SS_BW20 6.5 Mbps
922 {26, 32, 0}, // RATEID_VHT_MCS1_1SS_BW20 13 Mbps
923 {39, 33, 0}, // RATEID_VHT_MCS2_1SS_BW20 19.5 Mbps
924 {52, 34, 0}, // RATEID_VHT_MCS3_1SS_BW20 26 Mbps
925 {78, 35, 0}, // RATEID_VHT_MCS4_1SS_BW20 39 Mbps
926 {104, 36, 0}, // RATEID_VHT_MCS5_1SS_BW20 52 Mbps
927 {117, 37, 0}, // RATEID_VHT_MCS6_1SS_BW20 58.5 Mbps
928 {130, 38, 0}, // RATEID_VHT_MCS7_1SS_BW20 65 Mbps
929 {156, 39, 0}, // RATEID_VHT_MCS8_1SS_BW20 78 Mbps
930 {0, 40, 0}, // RATEID_VHT_MCS9_1SS_BW20 86.7 Mbps(INVALID)
931
932 /* VHT bw40<--> Mrvl rate idx */
933 {27, 41, 0}, // RATEID_VHT_MCS0_1SS_BW40 13.5 Mbps
934 {54, 42, 0}, // RATEID_VHT_MCS1_1SS_BW40 27 Mbps
935 {81, 43, 0}, // RATEID_VHT_MCS2_1SS_BW40 40.5 Mbps
936 {108, 44, 0}, // RATEID_VHT_MCS3_1SS_BW40 54 Mbps
937 {162, 45, 0}, // RATEID_VHT_MCS4_1SS_BW40 81 Mbps
938 {216, 46, 0}, // RATEID_VHT_MCS5_1SS_BW40 108 Mbps
939 {243, 47, 0}, // RATEID_VHT_MCS6_1SS_BW40 121.5 Mbps
940 {270, 48, 0}, // RATEID_VHT_MCS7_1SS_BW40 135 Mbps
941 {324, 49, 0}, // RATEID_VHT_MCS8_1SS_BW40 162 Mbps
942 {360, 50, 0}, // RATEID_VHT_MCS9_1SS_BW40 180 Mbps
943
944 /* VHT bw80<--> Mrvl rate idx */
945 {58, 51, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could
946 // correspond to 58
947 {59, 51, 0}, // RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could
948 // correspond to 59 too
949 {117, 52, 0}, // RATEID_VHT_MCS1_1SS_BW80 58.5 Mbps
950 {175, 53, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
951 // correspond to 175
952 {176, 53, 0}, // RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could
953 // correspond to 176 too
954 {234, 54, 0}, // RATEID_VHT_MCS3_1SS_BW80 117 Mbps
955 {351, 55, 0}, // RATEID_VHT_MCS4_1SS_BW80 175.5 Mbps
956 {468, 56, 0}, // RATEID_VHT_MCS5_1SS_BW80 234 Mbps
957 {526, 57, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
958 // correspond to 526
959 {527, 57, 0}, // RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could
960 // correspond to 527 too
961 {585, 58, 0}, // RATEID_VHT_MCS7_1SS_BW80 292.5 Mbps
962 {702, 59, 0}, // RATEID_VHT_MCS8_1SS_BW80 351 Mbps
963 {780, 60, 0}, // RATEID_VHT_MCS9_1SS_BW80 390 Mbps
964 };
965
966 /********************************************************
967 * Global Variables
968 ********************************************************/
969 /**
970 * The table to keep region code
971 */
972
973 t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {0x00, 0x10, 0x20, 0x30, 0x40,
974 0x41, 0x50, 0xfe, 0xff};
975
976 /** The table to keep CFP code for A */
977 t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = {0x1, 0x2, 0x3, 0x4, 0x5};
978
979 /**
980 * The rates supported for ad-hoc B mode
981 */
982 t_u8 AdhocRates_B[B_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0};
983
984 /**
985 * The rates supported for ad-hoc G mode
986 */
987 t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
988 0x48, 0x60, 0x6c, 0x00};
989
990 /**
991 * The rates supported for ad-hoc BG mode
992 */
993 t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {0x82, 0x84, 0x8b, 0x96, 0x0c,
994 0x12, 0x18, 0x24, 0x30, 0x48,
995 0x60, 0x6c, 0x00};
996
997 /**
998 * The rates supported in A mode for ad-hoc
999 */
1000 t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
1001 0x48, 0x60, 0x6c, 0x00};
1002
1003 /**
1004 * The rates supported in A mode (used for BAND_A)
1005 */
1006 t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0xb0,
1007 0x48, 0x60, 0x6c, 0x00};
1008
1009 /**
1010 * The rates supported by the card
1011 */
1012 static t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
1013 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48,
1014 0x60, 0x6C, 0x90, 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82,
1015 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00};
1016
1017 /**
1018 * The rates supported in B mode
1019 */
1020 t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x16, 0x00};
1021
1022 /**
1023 * The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
1024 */
1025 t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {0x0c, 0x12, 0x18, 0x24, 0x30,
1026 0x48, 0x60, 0x6c, 0x00};
1027
1028 /**
1029 * The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
1030 */
1031 t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {0x02, 0x04, 0x0b, 0x0c, 0x12,
1032 0x16, 0x18, 0x24, 0x30, 0x48,
1033 0x60, 0x6c, 0x00};
1034
1035 /**
1036 * The rates supported in N mode
1037 */
1038 t_u8 SupportedRates_N[N_SUPPORTED_RATES] = {0x02, 0x04, 0};
1039
1040 #define MCS_NUM_AX 12
1041 // for MCS0/MCS1/MCS3/MCS4 have 4 additional DCM=1 value
1042 // note: the value in the table is 2 multiplier of the actual rate
1043 static t_u16 ax_mcs_rate_nss1[12][MCS_NUM_AX + 4] = {
1044 {0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
1045 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962}, /*SG 160M*/
1046 {0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
1047 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC}, /*MG 160M*/
1048 {0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
1049 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9}, /*LG 160M*/
1050 {0x48, 0x24, 0x90, 0x48, 0xD8, 0x120, 0x90, 0x1B0, 0xD8, 0x240, 0x288,
1051 0x2D0, 0x360, 0x3C0, 0x438, 0x4B0}, /*SG 80M*/
1052 {0x44, 0x22, 0x88, 0x44, 0xCC, 0x110, 0x88, 0x198, 0xCC, 0x220, 0x264,
1053 0x2A8, 0x330, 0x38B, 0x3FC, 0x46E}, /*MG 80M*/
1054 {0x3D, 0x1E, 0x7A, 0x3D, 0xB7, 0xF5, 0x7A, 0x16F, 0xB7, 0x1EA, 0x227,
1055 0x264, 0x2DF, 0x330, 0x396, 0x3FC}, /*LG 80M*/
1056 {0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
1057 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 40M*/
1058 {0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
1059 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 40M*/
1060 {0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
1061 0x124, 0x15F, 0x186, 0x1B6, 0x1E7}, /*LG 40M*/
1062 {0x11, 0x8, 0x22, 0x11, 0x33, 0x44, 0x22, 0x67, 0x33, 0x89, 0x9A, 0xAC,
1063 0xCE, 0xE5, 0x102, 0x11E}, /*SG 20M*/
1064 {0x10, 0x8, 0x20, 0x10, 0x30, 0x41, 0x20, 0x61, 0x30, 0x82, 0x92, 0xA2,
1065 0xC3, 0xD8, 0xF3, 0x10E}, /*MG 20M*/
1066 {0xE, 0x7, 0x1D, 0xE, 0x2B, 0x3A, 0x1D, 0x57, 0x2B, 0x75, 0x83, 0x92,
1067 0xAF, 0xC3, 0xDB, 0xF3} /*LG 20M*/
1068 };
1069
1070 #if 0
1071 // note: the value in the table is 2 multiplier of the actual rate
1072 t_u16 ax_tone_ru_rate_nss1[9][MCS_NUM_AX + 4] = {
1073 {0x8, 0x4, 0xF, 0x8, 0x17, 0x1E, 0xF, 0x2D, 0x17, 0x3C, 0x44, 0x4B,
1074 0x5A, 0x64, 0x71, 0x7D}, /*SG 106-tone*/
1075 {0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2B, 0x16, 0x39, 0x40, 0x47,
1076 0x55, 0x5F, 0x6B, 0x76}, /*MG 106-tone*/
1077 {0x7, 0x3, 0xD, 0x6, 0x14, 0x1A, 0xD, 0x27, 0x14, 0x33, 0x3A, 0x40,
1078 0x4D, 0x55, 0x60, 0x6B}, /*LG 106-tone*/
1079 {0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
1080 0x2F, 0x35, 0x3B}, /*SG 52-tone*/
1081 {0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
1082 0x2D, 0x32, 0x38}, /*MG 52-tone*/
1083 {0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
1084 0x28, 0x2D, 0x32}, /*LG 52-tone*/
1085 {0x2, 0x1, 0x4, 0x2, 0x6, 0x7, 0x4, 0xB, 0x5, 0xE, 0x10, 0x12, 0x15,
1086 0x18, 0x1A, 0x1D}, /*SG 26-tone*/
1087 {0x2, 0x1, 0x4, 0x2, 0x5, 0x6, 0x4, 0xA, 0x5, 0xD, 0xF, 0x11, 0x14,
1088 0x16, 0x19, 0x1C}, /*MG 26-tone*/
1089 {0x2, 0x1, 0x3, 0x2, 0x5, 0x6, 0x3, 0x9, 0x4, 0xC, 0xE, 0xF, 0x12, 0x14,
1090 0x17, 0x19} /*LG 26-tone*/
1091 };
1092 #endif
1093
1094 // note: the value in the table is 2 multiplier of the actual rate
1095 static t_u16 ax_mcs_rate_nss2[12][MCS_NUM_AX + 4] = {
1096 {0x120, 0x90, 0x240, 0x120, 0x360, 0x481, 0x240, 0x61C, 0x360, 0x901,
1097 0xA22, 0xB42, 0xD82, 0xF03, 0x10E3, 0x12C3}, /*SG 160M*/
1098 {0x110, 0x88, 0x220, 0x110, 0x330, 0x440, 0x220, 0x661, 0x330, 0x881,
1099 0x992, 0xAA2, 0xCAC, 0xE2D, 0xFF3, 0x11B9}, /*MG 160M*/
1100 {0xF5, 0x7A, 0x1EA, 0xF5, 0x2DF, 0x3D4, 0x1EA, 0x5BE, 0x2DF, 0x7A8,
1101 0x1134, 0x992, 0xB7C, 0xCC2, 0xE5B, 0xFF3}, /*LG 160M*/
1102 {0x90, 0x48, 0x120, 0x90, 0x1B0, 0x240, 0x120, 0x360, 0x1B0, 0x481,
1103 0x511, 0x5A1, 0x6C1, 0x781, 0x871, 0x962}, /*SG 80M*/
1104 {0x88, 0x44, 0x110, 0x88, 0x198, 0x220, 0x110, 0x330, 0x198, 0x440,
1105 0x4C9, 0x551, 0x661, 0x716, 0x7F9, 0x8DC}, /*MG 80M*/
1106 {0x7A, 0x3D, 0xF5, 0x7A, 0x16F, 0x1EA, 0xF5, 0x2DF, 0x16F, 0x3D4, 0x44E,
1107 0x4C9, 0x5BE, 0x661, 0x72D, 0x7F9}, /*LG 80M*/
1108 {0x44, 0x22, 0x89, 0x44, 0xCE, 0x113, 0x89, 0x19D, 0xCE, 0x226, 0x26B,
1109 0x2B0, 0x339, 0x395, 0x408, 0x47B}, /*SG 40M*/
1110 {0x41, 0x20, 0x82, 0x41, 0xC3, 0x104, 0x82, 0x186, 0xC3, 0x208, 0x249,
1111 0x28A, 0x30C, 0x362, 0x3CE, 0x43B}, /*MG 40M*/
1112 {0x3A, 0x1D, 0x75, 0x3A, 0xAF, 0xEA, 0x75, 0x15F, 0xAF, 0x1D4, 0x20E,
1113 0x249, 0x2BE, 0x30C, 0x36D, 0x3CF}, /*LG 40M*/
1114 {0x22, 0x11, 0x44, 0x22, 0x67, 0x89, 0x44, 0xCE, 0x67, 0x113, 0x135,
1115 0x158, 0x19D, 0x1CA, 0x204, 0x23D}, /*SG 20M*/
1116 {0x20, 0x10, 0x41, 0x20, 0x61, 0x82, 0x41, 0xC3, 0x61, 0x104, 0x124,
1117 0x145, 0x186, 0x1B1, 0x1E7, 0x21D}, /*MG 20M*/
1118 {0x1D, 0xE, 0x3A, 0x1D, 0x57, 0x75, 0x3A, 0xAF, 0x57, 0xEA, 0x107,
1119 0x124, 0x15F, 0x186, 0x1B6, 0x1E7} /*LG 20M*/
1120 };
1121
1122 #if 0
1123 // note: the value in the table is 2 multiplier of the actual rate
1124 t_u16 ax_tone_ru_rate_nss2[9][MCS_NUM_AX + 4] = {
1125 {0xF, 0x8, 0x1E, 0xF, 0x2D, 0x3C, 0x1E, 0x5A, 0x2D, 0x78, 0x87, 0x96,
1126 0xB4, 0xC8, 0xE1, 0xFA}, /*SG 106-tone*/
1127 {0xE, 0x7, 0x1D, 0xE, 0x2B, 0x39, 0x1D, 0x55, 0x2B, 0x72, 0x80, 0x8E,
1128 0xAA, 0xBD, 0xD5, 0xED}, /*MG 106-tone*/
1129 {0xD, 0x7, 0x1A, 0xD, 0x27, 0x33, 0x1A, 0x4D, 0x27, 0x66, 0x73, 0x80,
1130 0x99, 0xAA, 0xC0, 0xD5}, /*LG 106-tone*/
1131 {0x7, 0x4, 0xF, 0x7, 0x16, 0x1D, 0xF, 0x2A, 0x16, 0x39, 0x40, 0x47,
1132 0x55, 0x5F, 0x6A, 0x76}, /*SG 52-tone*/
1133 {0x7, 0x4, 0xE, 0x7, 0x14, 0x1B, 0xE, 0x28, 0x14, 0x36, 0x3C, 0x43,
1134 0x50, 0x59, 0x64, 0x70}, /*MG 52-tone*/
1135 {0x6, 0x3, 0xC, 0x6, 0x12, 0x18, 0xC, 0x24, 0x12, 0x30, 0x36, 0x3C,
1136 0x48, 0x50, 0x5A, 0x64}, /*LG 52-tone*/
1137 {0x4, 0x2, 0x7, 0x4, 0xB, 0xF, 0x7, 0x16, 0xB, 0x1D, 0x20, 0x22, 0x2B,
1138 0x2F, 0x35, 0x3B}, /*SG 26-tone*/
1139 {0x4, 0x2, 0x7, 0x4, 0xA, 0xE, 0x7, 0x14, 0xA, 0x1B, 0x1E, 0x22, 0x28,
1140 0x2D, 0x32, 0x38}, /*MG 26-tone*/
1141 {0x3, 0x2, 0x6, 0x3, 0x9, 0xC, 0x6, 0x12, 0x9, 0x18, 0x1B, 0x1E, 0x24,
1142 0x28, 0x2D, 0x32} /*LG 26-tone*/
1143 };
1144 #endif
1145
1146 /********************************************************
1147 * Local Functions
1148 ********************************************************/
1149 /**
1150 * @brief Find a character in a string.
1151 *
1152 * @param pmadapter A pointer to mlan_adapter structure
1153 * @param s A pointer to string
1154 * @param c Character to be located
1155 * @param n The length of string
1156 *
1157 * @return A pointer to the first occurrence of c in string, or MNULL if
1158 * c is not found.
1159 */
wlan_memchr(pmlan_adapter pmadapter,void * s,int c,int n)1160 static void *wlan_memchr(pmlan_adapter pmadapter, void *s, int c, int n)
1161 {
1162 const t_u8 *p = (t_u8 *)s;
1163
1164 ENTER();
1165
1166 while (n--) {
1167 if ((t_u8)c == *p++) {
1168 LEAVE();
1169 return (void *)(p - 1);
1170 }
1171 }
1172
1173 LEAVE();
1174 return MNULL;
1175 }
1176
1177 /**
1178 * @brief This function finds the CFP in
1179 * cfp_table_BG/A based on region/code and band parameter.
1180 *
1181 * @param pmadapter A pointer to mlan_adapter structure
1182 * @param region The region code
1183 * @param band The band
1184 * @param cfp_no A pointer to CFP number
1185 *
1186 * @return A pointer to CFP
1187 */
wlan_get_region_cfp_table(pmlan_adapter pmadapter,t_u8 region,t_u16 band,int * cfp_no)1188 static chan_freq_power_t *wlan_get_region_cfp_table(pmlan_adapter pmadapter,
1189 t_u8 region, t_u16 band,
1190 int *cfp_no)
1191 {
1192 t_u32 i;
1193 t_u8 cfp_bg, cfp_a;
1194
1195 ENTER();
1196
1197 cfp_bg = cfp_a = region;
1198 if (!region) {
1199 /* Invalid region code, use CFP code */
1200 cfp_bg = pmadapter->cfp_code_bg;
1201 cfp_a = pmadapter->cfp_code_a;
1202 }
1203
1204 if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
1205 /* Return the FW cfp table for requested region code, if
1206 * available. If region is not forced and the requested region
1207 * code is different, simply return the corresponding
1208 * pre-defined table.
1209 */
1210 if (pmadapter->otp_region && pmadapter->cfp_otp_bg) {
1211 if (pmadapter->otp_region->force_reg ||
1212 (cfp_bg ==
1213 (t_u8)pmadapter->otp_region->region_code)) {
1214 *cfp_no = pmadapter->tx_power_table_bg_rows;
1215 LEAVE();
1216 return pmadapter->cfp_otp_bg;
1217 }
1218 }
1219 for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
1220 PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i,
1221 cfp_table_BG[i].code);
1222 /* Check if region/code matches for BG bands */
1223 if (cfp_table_BG[i].code == cfp_bg) {
1224 /* Select by band */
1225 *cfp_no = cfp_table_BG[i].cfp_no;
1226 LEAVE();
1227 return cfp_table_BG[i].cfp;
1228 }
1229 }
1230 }
1231 if (band & (BAND_A | BAND_AN | BAND_AAC)) {
1232 /* Return the FW cfp table for requested region code */
1233 if (pmadapter->otp_region && pmadapter->cfp_otp_a) {
1234 if (pmadapter->otp_region->force_reg ||
1235 (cfp_a ==
1236 (t_u8)pmadapter->otp_region->region_code)) {
1237 *cfp_no = pmadapter->tx_power_table_a_rows;
1238 LEAVE();
1239 return pmadapter->cfp_otp_a;
1240 }
1241 }
1242 for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
1243 PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i,
1244 cfp_table_A[i].code);
1245 /* Check if region/code matches for A bands */
1246 if (cfp_table_A[i].code == cfp_a) {
1247 /* Select by band */
1248 *cfp_no = cfp_table_A[i].cfp_no;
1249 LEAVE();
1250 return cfp_table_A[i].cfp;
1251 }
1252 }
1253 }
1254 if (!region)
1255 PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n",
1256 band, cfp_bg, cfp_a);
1257 else
1258 PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band,
1259 region);
1260
1261 LEAVE();
1262 return MNULL;
1263 }
1264
1265 /**
1266 * @brief This function copies dynamic CFP elements from one table to another.
1267 * Only copy elements where channel numbers match.
1268 *
1269 * @param pmadapter A pointer to mlan_adapter structure
1270 * @param cfp Destination table
1271 * @param num_cfp Number of elements in dest table
1272 * @param cfp_src Source table
1273 * @param num_cfp_src Number of elements in source table
1274 */
wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,chan_freq_power_t * cfp,t_u8 num_cfp,chan_freq_power_t * cfp_src,t_u8 num_cfp_src)1275 static t_void wlan_cfp_copy_dynamic(pmlan_adapter pmadapter,
1276 chan_freq_power_t *cfp, t_u8 num_cfp,
1277 chan_freq_power_t *cfp_src,
1278 t_u8 num_cfp_src)
1279 {
1280 int i, j;
1281
1282 ENTER();
1283
1284 if (cfp == cfp_src) {
1285 LEAVE();
1286 return;
1287 }
1288
1289 /* first clear dest dynamic blacklisted entries */
1290 /* do not clear the flags */
1291 for (i = 0; i < num_cfp; i++) {
1292 cfp[i].dynamic.blacklist = MFALSE;
1293 cfp[i].dynamic.dfs_state = DFS_USABLE;
1294 }
1295
1296 /* copy dynamic blacklisted entries from source where channels match */
1297 if (cfp_src) {
1298 for (i = 0; i < num_cfp; i++)
1299 for (j = 0; j < num_cfp_src; j++)
1300 if (cfp[i].channel == cfp_src[j].channel) {
1301 cfp[i].dynamic.blacklist =
1302 cfp_src[j].dynamic.blacklist;
1303 cfp[i].dynamic.dfs_state =
1304 cfp_src[j].dynamic.dfs_state;
1305 break;
1306 }
1307 }
1308
1309 LEAVE();
1310 }
1311
1312 /********************************************************
1313 * Global Functions
1314 ********************************************************/
1315 /**
1316 * @brief This function converts region string to integer code
1317 *
1318 * @param pmadapter A pointer to mlan_adapter structure
1319 * @param country_code Country string
1320 * @param cfp_bg Pointer to buffer
1321 * @param cfp_a Pointer to buffer
1322 *
1323 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1324 */
wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,t_u8 * country_code,t_u8 * cfp_bg,t_u8 * cfp_a)1325 mlan_status wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter,
1326 t_u8 *country_code, t_u8 *cfp_bg,
1327 t_u8 *cfp_a)
1328 {
1329 t_u8 i;
1330
1331 ENTER();
1332
1333 if (pmadapter->otp_region) {
1334 if (!memcmp(pmadapter, pmadapter->otp_region->country_code,
1335 country_code, COUNTRY_CODE_LEN - 1)) {
1336 if (pmadapter->cfp_otp_bg)
1337 *cfp_bg = pmadapter->otp_region->region_code;
1338 if (pmadapter->cfp_otp_a)
1339 *cfp_a = pmadapter->otp_region->region_code;
1340 LEAVE();
1341 return MLAN_STATUS_SUCCESS;
1342 }
1343 }
1344 /* Look for code in mapping table */
1345 for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
1346 if (!memcmp(pmadapter, country_code_mapping[i].country_code,
1347 country_code, COUNTRY_CODE_LEN - 1)) {
1348 *cfp_bg = country_code_mapping[i].cfp_code_bg;
1349 *cfp_a = country_code_mapping[i].cfp_code_a;
1350 LEAVE();
1351 return MLAN_STATUS_SUCCESS;
1352 }
1353 }
1354
1355 /* If still not found, look for code in EU country code table */
1356 for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
1357 if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
1358 COUNTRY_CODE_LEN - 1)) {
1359 *cfp_bg = EU_CFP_CODE_BG;
1360 *cfp_a = EU_CFP_CODE_A;
1361 LEAVE();
1362 return MLAN_STATUS_SUCCESS;
1363 }
1364 }
1365
1366 LEAVE();
1367 return MLAN_STATUS_FAILURE;
1368 }
1369
1370 /**
1371 * @brief This function finds if given country code is in EU table
1372 *
1373 * @param pmadapter A pointer to mlan_adapter structure
1374 * @param country_code Country string
1375 *
1376 * @return MTRUE or MFALSE
1377 */
wlan_is_etsi_country(pmlan_adapter pmadapter,t_u8 * country_code)1378 t_bool wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
1379 {
1380 t_u8 i;
1381
1382 ENTER();
1383
1384 /* Look for code in EU country code table */
1385 for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
1386 if (!memcmp(pmadapter, eu_country_code_table[i], country_code,
1387 COUNTRY_CODE_LEN - 1)) {
1388 LEAVE();
1389 return MTRUE;
1390 }
1391 }
1392
1393 LEAVE();
1394 return MFALSE;
1395 }
1396
1397 /**
1398 * @brief This function adjust the antenna index
1399 *
1400 * V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
1401 * 8887: case1: 0 - 2.4G ant A, 1- 2.4G antB, 2-- 5G ant C
1402 * case2: 0 - 2.4G ant A, 1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
1403 * @param priv A pointer to mlan_private structure
1404 * @param prx_pd A pointer to the RxPD structure
1405 *
1406 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1407 */
wlan_adjust_antenna(pmlan_private priv,RxPD * prx_pd)1408 t_u8 wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
1409 {
1410 t_u8 antenna = prx_pd->antenna;
1411 #if defined(SD8887) || defined(SD8987)
1412 t_u32 rx_channel = (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
1413 #endif
1414 if (prx_pd->antenna == 0xff)
1415 return 0;
1416 if (priv->adapter->pcard_info->v16_fw_api) {
1417 if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
1418 antenna = 2;
1419 else if (antenna & MBIT(1))
1420 antenna = 1;
1421 else if (antenna & MBIT(0))
1422 antenna = 0;
1423 }
1424
1425 #if defined(SD8887) || defined(SD8987)
1426 #define ANTENNA_OFFSET 2
1427 if (MFALSE
1428 #ifdef SD8887
1429 || IS_SD8887(priv->adapter->card_type)
1430 #endif
1431 #ifdef SD8987
1432 || IS_SD8987(priv->adapter->card_type)
1433 #endif
1434 ) {
1435 if ((priv->adapter->antinfo & ANT_DIVERSITY_2G) &&
1436 (priv->adapter->antinfo & ANT_DIVERSITY_5G)) {
1437 #define MAX_2G_CHAN 14
1438 if (rx_channel > MAX_2G_CHAN)
1439 antenna += ANTENNA_OFFSET;
1440 }
1441 }
1442 #endif
1443
1444 return antenna;
1445 }
1446
1447 /**
1448 * @brief This function adjust the rate index
1449 *
1450 * @param priv A pointer to mlan_private structure
1451 * @param rx_rate rx rate
1452 * @param rate_info rate info
1453 * @return rate index
1454 */
wlan_adjust_data_rate(mlan_private * priv,t_u8 rx_rate,t_u8 rate_info)1455 t_u16 wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
1456 {
1457 t_u16 rate_index = 0;
1458 t_u8 bw = 0;
1459 t_u8 nss = 0;
1460 t_bool sgi_enable = 0;
1461 t_u8 gi = 0;
1462 #define MAX_MCS_NUM_AX 12
1463
1464 #define MAX_MCS_NUM_SUPP 16
1465 #define MAX_MCS_NUM_AC 10
1466 #define RATE_INDEX_MCS0 12
1467 bw = (rate_info & 0xC) >> 2;
1468 sgi_enable = (rate_info & 0x10) >> 4;
1469 if ((rate_info & 0x3) == 0) {
1470 rate_index = (rx_rate > MLAN_RATE_INDEX_OFDM0) ? rx_rate - 1 :
1471 rx_rate;
1472 } else if ((rate_info & 0x03) == 1) {
1473 rate_index = RATE_INDEX_MCS0 +
1474 MAX_MCS_NUM_SUPP * 2 * sgi_enable +
1475 MAX_MCS_NUM_SUPP * bw + rx_rate;
1476 } else if ((rate_info & 0x3) == 2) {
1477 if (IS_STREAM_2X2(priv->adapter->feature_control))
1478 nss = rx_rate >> 4; // 0:NSS1, 1:NSS2
1479 rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
1480 MAX_MCS_NUM_AC * 6 * sgi_enable +
1481 MAX_MCS_NUM_AC * 2 * bw + MAX_MCS_NUM_AC * nss +
1482 (rx_rate & 0x0f);
1483 } else if ((rate_info & 0x3) == 3) {
1484 gi = (rate_info & 0x10) >> 4 | (rate_info & 0x80) >> 6;
1485 if (IS_STREAM_2X2(priv->adapter->feature_control))
1486 nss = rx_rate >> 4; // 0:NSS1, 1:NSS2
1487 rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
1488 MAX_MCS_NUM_AC * 12 + MAX_MCS_NUM_AX * 6 * gi +
1489 MAX_MCS_NUM_AX * 2 * bw + MAX_MCS_NUM_AX * nss +
1490 (rx_rate & 0x0f);
1491 }
1492 return rate_index;
1493 }
1494
1495 #ifdef STA_SUPPORT
1496 #endif /* STA_SUPPORT */
1497
1498 /**
1499 * @brief convert TX rate_info from v14 to v15+ FW rate_info
1500 *
1501 * @param v14_rate_info v14 rate info
1502 *
1503 * @return v15+ rate info
1504 */
wlan_convert_v14_tx_rate_info(pmlan_private pmpriv,t_u8 v14_rate_info)1505 t_u8 wlan_convert_v14_tx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info)
1506 {
1507 t_u8 rate_info = 0;
1508
1509 if (!pmpriv->adapter->pcard_info->v14_fw_api) {
1510 PRINTM(MERROR, "%s: Not convert for this is not V14 FW\n",
1511 __func__);
1512 return v14_rate_info;
1513 }
1514
1515 rate_info = v14_rate_info & 0x01;
1516 /* band */
1517 rate_info |= (v14_rate_info & MBIT(1)) << 1;
1518 /* short GI */
1519 rate_info |= (v14_rate_info & MBIT(2)) << 2;
1520 return rate_info;
1521 }
1522
1523 /**
1524 * @brief convert RX rate_info from v14 to v15+ FW rate_info
1525 *
1526 * @param v14_rate_info v14 rate info
1527 *
1528 * @return v15+ rate info
1529 */
wlan_convert_v14_rx_rate_info(pmlan_private pmpriv,t_u8 v14_rate_info)1530 t_u8 wlan_convert_v14_rx_rate_info(pmlan_private pmpriv, t_u8 v14_rate_info)
1531 {
1532 t_u8 rate_info = 0;
1533 t_u8 mode = 0;
1534 t_u8 bw = 0;
1535 t_u8 sgi = 0;
1536
1537 if (!pmpriv->adapter->pcard_info->v14_fw_api) {
1538 PRINTM(MERROR, "%s: Not convert for this is not V14 FW\n",
1539 __func__);
1540 return v14_rate_info;
1541 }
1542
1543 mode = v14_rate_info & MBIT(0);
1544 bw = v14_rate_info & MBIT(1);
1545 sgi = (v14_rate_info & 0x04) >> 2;
1546
1547 rate_info = (mode & 0x01) | ((bw & 0x01) << 2) | ((sgi & 0x01) << 4);
1548
1549 return rate_info;
1550 }
1551
1552 /**
1553 * @brief Use index to get the data rate
1554 *
1555 * @param pmadapter A pointer to mlan_adapter structure
1556 * @param index The index of data rate
1557 * @param tx_rate_info Tx rate info
1558 * @param ext_rate_info Extend tx rate info
1559 *
1560 * @return Data rate or 0
1561 */
wlan_index_to_data_rate(pmlan_adapter pmadapter,t_u8 index,t_u8 tx_rate_info,t_u8 ext_rate_info)1562 t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index,
1563 t_u8 tx_rate_info, t_u8 ext_rate_info)
1564 {
1565 #define MCS_NUM_SUPP 16
1566 t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
1567 {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c,
1568 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c}, /*LG 40M*/
1569 {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78,
1570 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258}, /*SG 40M */
1571 {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34,
1572 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104}, /*LG 20M */
1573 {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39,
1574 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}}; /*SG 20M */
1575
1576 #define MCS_NUM_AC 10
1577 /* NSS 1. note: the value in the table is 2 multiplier of the actual
1578 * rate in other words, it is in the unit of 500 Kbs
1579 */
1580 t_u16 ac_mcs_rate_nss1[8][MCS_NUM_AC] = {
1581 {0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
1582 0x618}, /* LG 160M*/
1583 {0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
1584 0x6C6}, /* SG 160M*/
1585 {0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 0x249, 0x2BE,
1586 0x30C}, /* LG 80M */
1587 {0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 0x28A, 0x30C,
1588 0x363}, /* SG 80M */
1589 {0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x144,
1590 0x168}, /* LG 40M */
1591 {0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 0x12C, 0x168,
1592 0x190}, /* SG 40M */
1593 {0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C,
1594 0x00}, /* LG 20M */
1595 {0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE,
1596 0x00}, /* SG 20M */
1597 };
1598 /* NSS 2. note: the value in the table is 2 multiplier of the actual
1599 * rate
1600 */
1601 t_u16 ac_mcs_rate_nss2[8][MCS_NUM_AC] = {
1602 {0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 0x924, 0xAF8,
1603 0xC30}, /*LG 160M*/
1604 {0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 0xA28, 0xC30,
1605 0xD8B}, /*SG 160M*/
1606
1607 {0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C,
1608 0x618}, /*LG 80M*/
1609 {0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618,
1610 0x6C6}, /*SG 80M*/
1611 {0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 0x21C, 0x288,
1612 0x2D0}, /*LG 40M*/
1613 {0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 0x258, 0x2D0,
1614 0x320}, /*SG 40M*/
1615 {0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 0x138,
1616 0x00}, /*LG 20M*/
1617 {0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 0x15B,
1618 0x00}, /*SG 20M*/
1619 };
1620
1621 t_u32 rate = 0;
1622 t_u8 mcs_index = 0;
1623 t_u8 he_dcm = 0;
1624 // t_u8 he_tone = 0;
1625 t_u8 stbc = 0;
1626
1627 t_u8 bw = 0;
1628 t_u8 gi = 0;
1629
1630 ENTER();
1631
1632 PRINTM(MINFO, "%s:index=%d, tx_rate_info=%d, ext_rate_info=%d\n",
1633 __func__, index, tx_rate_info, ext_rate_info);
1634
1635 if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
1636 /* VHT rate */
1637 mcs_index = index & 0xF;
1638
1639 if (mcs_index > 9)
1640 mcs_index = 9;
1641
1642 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
1643 bw = (tx_rate_info & 0xC) >> 2;
1644 /* LGI: gi =0, SGI: gi = 1 */
1645 gi = (tx_rate_info & 0x10) >> 4;
1646 if ((index >> 4) == 1) {
1647 /* NSS = 2 */
1648 rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
1649 } else
1650 /* NSS = 1 */
1651 rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
1652 } else
1653
1654 if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE) {
1655 /* VHT rate */
1656 mcs_index = index & 0xF;
1657 he_dcm = ext_rate_info & MBIT(0);
1658
1659 if (mcs_index > MCS_NUM_AX - 1)
1660 mcs_index = MCS_NUM_AX - 1;
1661
1662 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
1663 bw = (tx_rate_info & (MBIT(3) | MBIT(2))) >> 2;
1664 /* BIT7:BIT4 0:0= 0.8us,0:1= 0.8us, 1:0=1.6us, 1:1=3.2us or
1665 * 0.8us
1666 */
1667 gi = (tx_rate_info & MBIT(4)) >> 4 |
1668 (tx_rate_info & MBIT(7)) >> 6;
1669 /* STBC: BIT5 in tx rate info */
1670 stbc = (tx_rate_info & MBIT(5)) >> 5;
1671
1672 if (gi > 3) {
1673 PRINTM(MERROR, "Invalid gi value");
1674 return 0;
1675 }
1676
1677 if ((gi == 3) && stbc && he_dcm) {
1678 gi = 0;
1679 stbc = 0;
1680 he_dcm = 0;
1681 }
1682 /* map to gi 0:0.8us,1:1.6us 2:3.2us*/
1683 if (gi > 0)
1684 gi = gi - 1;
1685
1686 //#ifdef ENABLE_802_11AX
1687 // TODO: hardcode he_tone here, wait for FW value ready.
1688 // he_tone = 4;
1689
1690 // he_tone = (ext_rate_info & 0xE) >> 1;
1691 //#endif
1692
1693 if ((index >> 4) == 1) {
1694 switch (mcs_index) {
1695 case 0:
1696 case 1:
1697 // #if 0
1698 // if (he_tone < 3) {
1699 // rate =
1700 //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2
1701 //+ he_dcm];
1702 // } else {
1703 // #endif
1704 rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1705 [mcs_index * 2 + he_dcm];
1706 break;
1707 case 2:
1708 // #if 0
1709 // if (he_tone < 3) {
1710 // rate =
1711 //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2];
1712 // } else {
1713 // #endif
1714 rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1715 [mcs_index * 2];
1716 break;
1717 case 3:
1718 case 4:
1719 // #if 0
1720 // if (he_tone < 3) {
1721 // rate =
1722 //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index*2
1723 //- 1 + he_dcm];
1724 // } else {
1725 // #endif
1726 rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1727 [mcs_index * 2 - 1 +
1728 he_dcm];
1729 break;
1730
1731 default:
1732 // #if 0
1733 // if (he_tone < 3) {
1734 // rate =
1735 //ax_tone_ru_rate_nss2[3*(2-he_tone)+gi][mcs_index
1736 //+ 4];
1737 // } else {
1738 // #endif
1739 rate = ax_mcs_rate_nss2[3 * (3 - bw) + gi]
1740 [mcs_index + 4];
1741 break;
1742 }
1743 } else {
1744 switch (mcs_index) {
1745 case 0:
1746 case 1:
1747 // #if 0
1748 // if (he_tone < 3) {
1749 // rate =
1750 //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2
1751 //+ he_dcm];
1752 // } else {
1753 // #endif
1754 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1755 [mcs_index * 2 + he_dcm];
1756 break;
1757 case 2:
1758 // #if 0
1759 // if (he_tone < 3) {
1760 // rate =
1761 //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2];
1762 // } else {
1763 // #endif
1764 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1765 [mcs_index * 2];
1766 break;
1767 case 3:
1768 case 4:
1769 // #if 0
1770 // if (he_tone < 3) {
1771 // rate =
1772 //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index*2
1773 //- 1 + he_dcm];
1774 // } else {
1775 // #endif
1776 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1777 [mcs_index * 2 - 1 +
1778 he_dcm];
1779 break;
1780
1781 default:
1782 // #if 0
1783 // if (he_tone < 3) {
1784 // rate =
1785 //ax_tone_ru_rate_nss1[3*(2-he_tone)+gi][mcs_index
1786 //+ 4];
1787 // } else {
1788 // #endif
1789 rate = ax_mcs_rate_nss1[3 * (3 - bw) + gi]
1790 [mcs_index + 4];
1791 break;
1792 }
1793 }
1794 } else if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
1795 /* HT rate */
1796 /* 20M: bw=0, 40M: bw=1 */
1797 bw = (tx_rate_info & 0xC) >> 2;
1798 /* LGI: gi =0, SGI: gi = 1 */
1799 gi = (tx_rate_info & 0x10) >> 4;
1800 if (index == MLAN_RATE_BITMAP_MCS0) {
1801 if (gi == 1)
1802 rate = 0x0D; /* MCS 32 SGI rate */
1803 else
1804 rate = 0x0C; /* MCS 32 LGI rate */
1805 } else if (index < MCS_NUM_SUPP) {
1806 if (bw <= 1)
1807 rate = mcs_rate[2 * (1 - bw) + gi][index];
1808 else
1809 rate = WlanDataRates[0];
1810 } else
1811 rate = WlanDataRates[0];
1812 } else {
1813 /* 11n non HT rates */
1814 if (index >= WLAN_SUPPORTED_RATES_EXT)
1815 index = 0;
1816 rate = WlanDataRates[index];
1817 }
1818 LEAVE();
1819 return rate;
1820 }
1821
1822 /**
1823 * @brief Use rate to get the index
1824 *
1825 * @param pmadapter A pointer to mlan_adapter structure
1826 * @param rate Data rate
1827 *
1828 * @return Index or 0
1829 */
wlan_data_rate_to_index(pmlan_adapter pmadapter,t_u32 rate)1830 t_u8 wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate)
1831 {
1832 t_u16 *ptr;
1833
1834 ENTER();
1835 if (rate) {
1836 ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8)rate,
1837 sizeof(WlanDataRates));
1838 if (ptr) {
1839 LEAVE();
1840 return (t_u8)(ptr - WlanDataRates);
1841 }
1842 }
1843 LEAVE();
1844 return 0;
1845 }
1846
1847 /**
1848 * @brief Get active data rates
1849 *
1850 * @param pmpriv A pointer to mlan_private structure
1851 * @param bss_mode The specified BSS mode (Infra/IBSS)
1852 * @param config_bands The specified band configuration
1853 * @param rates The buf to return the active rates
1854 *
1855 * @return The number of Rates
1856 */
wlan_get_active_data_rates(mlan_private * pmpriv,t_u32 bss_mode,t_u16 config_bands,WLAN_802_11_RATES rates)1857 t_u32 wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
1858 t_u16 config_bands, WLAN_802_11_RATES rates)
1859 {
1860 t_u32 k;
1861
1862 ENTER();
1863
1864 if (pmpriv->media_connected != MTRUE) {
1865 k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands,
1866 rates);
1867 } else {
1868 k = wlan_copy_rates(rates, 0,
1869 pmpriv->curr_bss_params.data_rates,
1870 pmpriv->curr_bss_params.num_of_rates);
1871 }
1872
1873 LEAVE();
1874 return k;
1875 }
1876
1877 #ifdef STA_SUPPORT
1878 /**
1879 * @brief This function search through all the regions cfp table to find the
1880 * channel, if the channel is found then gets the MIN txpower of the channel
1881 * present in all the regions.
1882 *
1883 * @param pmpriv A pointer to mlan_private structure
1884 * @param band band.
1885 * @param channel Channel number.
1886 *
1887 * @return The Tx power
1888 */
wlan_get_txpwr_of_chan_from_cfp(mlan_private * pmpriv,t_u16 band,t_u8 channel)1889 t_u8 wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u16 band,
1890 t_u8 channel)
1891 {
1892 t_u8 i = 0;
1893 t_u8 j = 0;
1894 t_u8 tx_power = 0;
1895 t_u32 cfp_no;
1896 chan_freq_power_t *cfp = MNULL;
1897 chan_freq_power_t *cfp_a = MNULL;
1898 t_u32 cfp_no_a;
1899
1900 ENTER();
1901
1902 if (band & (BAND_B | BAND_G)) {
1903 for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
1904 /* Get CFP */
1905 cfp = cfp_table_BG[i].cfp;
1906 cfp_no = cfp_table_BG[i].cfp_no;
1907 /* Find matching channel and get Tx power */
1908 for (j = 0; j < cfp_no; j++) {
1909 if ((cfp + j)->channel == channel) {
1910 if (tx_power != 0)
1911 tx_power = MIN(
1912 tx_power,
1913 (cfp + j)->max_tx_power);
1914 else
1915 tx_power =
1916 (t_u8)(cfp + j)
1917 ->max_tx_power;
1918 break;
1919 }
1920 }
1921 }
1922 }
1923
1924 if (band & BAND_A) {
1925 for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
1926 /* Get CFP */
1927 cfp_a = cfp_table_A[i].cfp;
1928 cfp_no_a = cfp_table_A[i].cfp_no;
1929 for (j = 0; j < cfp_no_a; j++) {
1930 if ((cfp_a + j)->channel == channel) {
1931 if (tx_power != 0)
1932 tx_power = MIN(
1933 tx_power,
1934 (cfp_a + j)
1935 ->max_tx_power);
1936 else
1937 tx_power = (t_u8)(
1938 (cfp_a + j)
1939 ->max_tx_power);
1940 break;
1941 }
1942 }
1943 }
1944 }
1945
1946 LEAVE();
1947 return tx_power;
1948 }
1949
1950 /**
1951 * @brief Get the channel frequency power info for a specific channel
1952 *
1953 * @param pmadapter A pointer to mlan_adapter structure
1954 * @param band It can be BAND_A, BAND_G or BAND_B
1955 * @param channel The channel to search for
1956 * @param region_channel A pointer to region_chan_t structure
1957 *
1958 * @return A pointer to chan_freq_power_t structure or
1959 * MNULL if not found.
1960 */
1961
1962 chan_freq_power_t *
wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,t_u16 band,t_u16 channel,region_chan_t * region_channel)1963 wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, t_u16 band,
1964 t_u16 channel, region_chan_t *region_channel)
1965 {
1966 region_chan_t *rc;
1967 chan_freq_power_t *cfp = MNULL;
1968 int i, j;
1969
1970 ENTER();
1971
1972 for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
1973 rc = ®ion_channel[j];
1974
1975 if (!rc->valid || !rc->pcfp)
1976 continue;
1977 switch (rc->band) {
1978 case BAND_A:
1979 switch (band) {
1980 case BAND_AN:
1981 case BAND_A | BAND_AN:
1982 case BAND_A | BAND_AN | BAND_AAC:
1983 /* Fall Through */
1984 case BAND_A: /* Matching BAND_A */
1985 break;
1986
1987 default:
1988 continue;
1989 }
1990 break;
1991 case BAND_B:
1992 case BAND_G:
1993 switch (band) {
1994 case BAND_GN:
1995 case BAND_B | BAND_G | BAND_GN:
1996 case BAND_G | BAND_GN:
1997 case BAND_GN | BAND_GAC:
1998 case BAND_B | BAND_G | BAND_GN | BAND_GAC:
1999 case BAND_G | BAND_GN | BAND_GAC:
2000 case BAND_B | BAND_G:
2001 /* Fall Through */
2002 case BAND_B: /* Matching BAND_B/G */
2003 /* Fall Through */
2004 case BAND_G:
2005 /* Fall Through */
2006 case 0:
2007 break;
2008 default:
2009 continue;
2010 }
2011 break;
2012 default:
2013 continue;
2014 }
2015 if (channel == FIRST_VALID_CHANNEL)
2016 cfp = &rc->pcfp[0];
2017 else {
2018 for (i = 0; i < rc->num_cfp; i++) {
2019 if (rc->pcfp[i].channel == channel) {
2020 cfp = &rc->pcfp[i];
2021 break;
2022 }
2023 }
2024 }
2025 }
2026
2027 if (!cfp && channel)
2028 PRINTM(MCMND, "%s: can not find cfp by band %d & channel %d\n",
2029 __func__, band, channel);
2030
2031 LEAVE();
2032 return cfp;
2033 }
2034
2035 /**
2036 * @brief Find the channel frequency power info for a specific channel
2037 *
2038 * @param pmadapter A pointer to mlan_adapter structure
2039 * @param band It can be BAND_A, BAND_G or BAND_B
2040 * @param channel The channel to search for
2041 *
2042 * @return A pointer to chan_freq_power_t structure or MNULL if not
2043 * found.
2044 */
wlan_find_cfp_by_band_and_channel(mlan_adapter * pmadapter,t_u16 band,t_u16 channel)2045 chan_freq_power_t *wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
2046 t_u16 band, t_u16 channel)
2047 {
2048 chan_freq_power_t *cfp = MNULL;
2049
2050 ENTER();
2051
2052 /* Any station(s) with 11D enabled */
2053 if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
2054 wlan_is_station) > 0)
2055 cfp = wlan_get_cfp_by_band_and_channel(
2056 pmadapter, band, channel, pmadapter->universal_channel);
2057 else
2058 cfp = wlan_get_cfp_by_band_and_channel(
2059 pmadapter, band, channel, pmadapter->region_channel);
2060
2061 LEAVE();
2062 return cfp;
2063 }
2064
2065 /**
2066 * @brief Find the channel frequency power info for a specific frequency
2067 *
2068 * @param pmadapter A pointer to mlan_adapter structure
2069 * @param band It can be BAND_A, BAND_G or BAND_B
2070 * @param freq The frequency to search for
2071 *
2072 * @return Pointer to chan_freq_power_t structure; MNULL if not found
2073 */
wlan_find_cfp_by_band_and_freq(mlan_adapter * pmadapter,t_u16 band,t_u32 freq)2074 chan_freq_power_t *wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter,
2075 t_u16 band, t_u32 freq)
2076 {
2077 chan_freq_power_t *cfp = MNULL;
2078 region_chan_t *rc;
2079 int i, j;
2080
2081 ENTER();
2082
2083 for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
2084 rc = &pmadapter->region_channel[j];
2085
2086 /* Any station(s) with 11D enabled */
2087 if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
2088 wlan_is_station) > 0)
2089 rc = &pmadapter->universal_channel[j];
2090
2091 if (!rc->valid || !rc->pcfp)
2092 continue;
2093 switch (rc->band) {
2094 case BAND_A:
2095 switch (band) {
2096 case BAND_AN:
2097 case BAND_A | BAND_AN:
2098 case BAND_A | BAND_AN | BAND_AAC:
2099 /* Fall Through */
2100 case BAND_A: /* Matching BAND_A */
2101 break;
2102 default:
2103 continue;
2104 }
2105 break;
2106 case BAND_B:
2107 case BAND_G:
2108 switch (band) {
2109 case BAND_GN:
2110 case BAND_B | BAND_G | BAND_GN:
2111 case BAND_G | BAND_GN:
2112 case BAND_GN | BAND_GAC:
2113 case BAND_B | BAND_G | BAND_GN | BAND_GAC:
2114 case BAND_G | BAND_GN | BAND_GAC:
2115 case BAND_B | BAND_G:
2116 /* Fall Through */
2117 case BAND_B:
2118 /* Fall Through */
2119 case BAND_G:
2120 /* Fall Through */
2121 case 0:
2122 break;
2123 default:
2124 continue;
2125 }
2126 break;
2127 default:
2128 continue;
2129 }
2130 for (i = 0; i < rc->num_cfp; i++) {
2131 if (rc->pcfp[i].freq == freq) {
2132 cfp = &rc->pcfp[i];
2133 break;
2134 }
2135 }
2136 }
2137
2138 if (!cfp && freq)
2139 PRINTM(MERROR, "%s: cannot find cfp by band %d & freq %d\n",
2140 __func__, band, freq);
2141
2142 LEAVE();
2143 return cfp;
2144 }
2145 #endif /* STA_SUPPORT */
2146
2147 /**
2148 * @brief Check if Rate Auto
2149 *
2150 * @param pmpriv A pointer to mlan_private structure
2151 *
2152 * @return MTRUE or MFALSE
2153 */
wlan_is_rate_auto(mlan_private * pmpriv)2154 t_u8 wlan_is_rate_auto(mlan_private *pmpriv)
2155 {
2156 t_u32 i;
2157 int rate_num = 0;
2158
2159 ENTER();
2160
2161 for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
2162 if (pmpriv->bitmap_rates[i])
2163 rate_num++;
2164
2165 LEAVE();
2166 if (rate_num > 1)
2167 return MTRUE;
2168 else
2169 return MFALSE;
2170 }
2171
2172 /**
2173 * @brief Covert Rate Bitmap to Rate index
2174 *
2175 * @param pmadapter Pointer to mlan_adapter structure
2176 * @param rate_bitmap Pointer to rate bitmap
2177 * @param size Size of the bitmap array
2178 *
2179 * @return Rate index
2180 */
wlan_get_rate_index(pmlan_adapter pmadapter,t_u16 * rate_bitmap,int size)2181 int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
2182 {
2183 int i;
2184
2185 ENTER();
2186
2187 for (i = 0; i < size * 8; i++) {
2188 if (rate_bitmap[i / 16] & (1 << (i % 16))) {
2189 LEAVE();
2190 return i;
2191 }
2192 }
2193
2194 LEAVE();
2195 return -1;
2196 }
2197
2198 /**
2199 * @brief Convert config_bands to B/G/A band
2200 *
2201 * @param config_bands The specified band configuration
2202 *
2203 * @return BAND_B|BAND_G|BAND_A
2204 */
wlan_convert_config_bands(t_u16 config_bands)2205 t_u16 wlan_convert_config_bands(t_u16 config_bands)
2206 {
2207 t_u16 bands = 0;
2208 if (config_bands & BAND_B)
2209 bands |= BAND_B;
2210 if (config_bands & BAND_G || config_bands & BAND_GN ||
2211 config_bands & BAND_GAC || config_bands & BAND_GAX)
2212 bands |= BAND_G;
2213 if (config_bands & BAND_A || config_bands & BAND_AN ||
2214 config_bands & BAND_AAC || config_bands & BAND_AAX)
2215 bands |= BAND_A;
2216 return bands;
2217 }
2218
2219 /**
2220 * @brief Get supported data rates
2221 *
2222 * @param pmpriv A pointer to mlan_private structure
2223 * @param bss_mode The specified BSS mode (Infra/IBSS)
2224 * @param config_bands The specified band configuration
2225 * @param rates The buf to return the supported rates
2226 *
2227 * @return The number of Rates
2228 */
wlan_get_supported_rates(mlan_private * pmpriv,t_u32 bss_mode,t_u16 config_bands,WLAN_802_11_RATES rates)2229 t_u32 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
2230 t_u16 config_bands, WLAN_802_11_RATES rates)
2231 {
2232 t_u32 k = 0;
2233 t_u16 bands = 0;
2234
2235 ENTER();
2236 bands = wlan_convert_config_bands(config_bands);
2237
2238 if (bss_mode == MLAN_BSS_MODE_INFRA) {
2239 /* Infra. mode */
2240 if (bands == BAND_B) {
2241 /* B only */
2242 PRINTM(MINFO, "Band: Infra B\n");
2243 k = wlan_copy_rates(rates, k, SupportedRates_B,
2244 sizeof(SupportedRates_B));
2245 } else if (bands == BAND_G) {
2246 /* G only */
2247 PRINTM(MINFO, "Band: Infra G\n");
2248 k = wlan_copy_rates(rates, k, SupportedRates_G,
2249 sizeof(SupportedRates_G));
2250
2251 } else if (bands & (BAND_B | BAND_G)) {
2252 /* BG only */
2253 PRINTM(MINFO, "Band: Infra BG\n");
2254 #ifdef WIFI_DIRECT_SUPPORT
2255 if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
2256 k = wlan_copy_rates(rates, k, SupportedRates_G,
2257 sizeof(SupportedRates_G));
2258 else
2259 #endif
2260 k = wlan_copy_rates(rates, k, SupportedRates_BG,
2261 sizeof(SupportedRates_BG));
2262 } else if (bands & BAND_A) {
2263 /* support A */
2264 PRINTM(MINFO, "Band: Infra A\n");
2265 k = wlan_copy_rates(rates, k, SupportedRates_A,
2266 sizeof(SupportedRates_A));
2267 }
2268 } else {
2269 /* Adhoc. mode */
2270 if (bands == BAND_B) {
2271 /* B only */
2272 PRINTM(MINFO, "Band: Adhoc B\n");
2273 k = wlan_copy_rates(rates, k, AdhocRates_B,
2274 sizeof(AdhocRates_B));
2275 } else if (bands == BAND_G) {
2276 /* G only */
2277 PRINTM(MINFO, "Band: Adhoc G\n");
2278 k = wlan_copy_rates(rates, k, AdhocRates_G,
2279 sizeof(AdhocRates_G));
2280
2281 } else if (bands & BAND_A) {
2282 /* support A */
2283 PRINTM(MINFO, "Band: Adhoc A\n");
2284 k = wlan_copy_rates(rates, k, AdhocRates_A,
2285 sizeof(AdhocRates_A));
2286
2287 } else {
2288 PRINTM(MINFO, "Band: Adhoc BG\n");
2289 k = wlan_copy_rates(rates, k, AdhocRates_BG,
2290 sizeof(AdhocRates_BG));
2291 }
2292 }
2293
2294 LEAVE();
2295 return k;
2296 }
2297
2298 #define COUNTRY_ID_US 0
2299 #define COUNTRY_ID_JP 1
2300 #define COUNTRY_ID_CN 2
2301 #define COUNTRY_ID_EU 3
2302 typedef struct _oper_bw_chan {
2303 /*non-global operating class*/
2304 t_u8 oper_class;
2305 /*global operating class*/
2306 t_u8 global_oper_class;
2307 /*bandwidth 0-20M 1-40M 2-80M 3-160M*/
2308 t_u8 bandwidth;
2309 /*channel list*/
2310 t_u8 channel_list[13];
2311 } oper_bw_chan;
2312
2313 /** oper class table for US*/
2314 static oper_bw_chan oper_bw_chan_us[] = {
2315 /** non-Global oper class, global oper class, bandwidth, channel list*/
2316 {1, 115, 0, {36, 40, 44, 48}},
2317 {2, 118, 0, {52, 56, 60, 64}},
2318 {3, 124, 0, {149, 153, 157, 161}},
2319 {4,
2320 121,
2321 0,
2322 {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
2323 {5, 125, 0, {149, 153, 157, 161, 165}},
2324 {12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
2325 {22, 116, 1, {36, 44}},
2326 {23, 119, 1, {52, 60}},
2327 {24, 122, 1, {100, 108, 116, 124, 132, 140}},
2328 {25, 126, 1, {149, 157}},
2329 {26, 126, 1, {149, 157}},
2330 {27, 117, 1, {40, 48}},
2331 {28, 120, 1, {56, 64}},
2332 {29, 123, 1, {104, 112, 120, 128, 136, 144}},
2333 {30, 127, 1, {153, 161}},
2334 {31, 127, 1, {153, 161}},
2335 {32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
2336 {33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
2337 {128, 128, 2, {42, 58, 106, 122, 138, 155}},
2338 {129, 129, 3, {50, 114}},
2339 {130, 130, 2, {42, 58, 106, 122, 138, 155}},
2340 };
2341 /** oper class table for EU*/
2342 static oper_bw_chan oper_bw_chan_eu[] = {
2343 /** non-global oper class,global oper class, bandwidth, channel list*/
2344 {1, 115, 0, {36, 40, 44, 48}},
2345 {2, 118, 0, {52, 56, 60, 64}},
2346 {3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2347 {4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
2348 {5, 116, 1, {36, 44}},
2349 {6, 119, 1, {52, 60}},
2350 {7, 122, 1, {100, 108, 116, 124, 132}},
2351 {8, 117, 1, {40, 48}},
2352 {9, 120, 1, {56, 64}},
2353 {10, 123, 1, {104, 112, 120, 128, 136}},
2354 {11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
2355 {12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
2356 {17, 125, 0, {149, 153, 157, 161, 165, 169}},
2357 {128, 128, 2, {42, 58, 106, 122, 138, 155}},
2358 {129, 129, 3, {50, 114}},
2359 {130, 130, 2, {42, 58, 106, 122, 138, 155}},
2360 };
2361 /** oper class table for Japan*/
2362 static oper_bw_chan oper_bw_chan_jp[] = {
2363 /** non-Global oper class,global oper class, bandwidth, channel list*/
2364 {1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
2365 {30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
2366 {31, 82, 0, {14}},
2367 {32, 118, 0, {52, 56, 60, 64}},
2368 {33, 118, 0, {52, 56, 60, 64}},
2369 {34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2370 {35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2371 {36, 116, 1, {36, 44}},
2372 {37, 119, 1, {52, 60}},
2373 {38, 119, 1, {52, 60}},
2374 {39, 122, 1, {100, 108, 116, 124, 132}},
2375 {40, 122, 1, {100, 108, 116, 124, 132}},
2376 {41, 117, 1, {40, 48}},
2377 {42, 120, 1, {56, 64}},
2378 {43, 120, 1, {56, 64}},
2379 {44, 123, 1, {104, 112, 120, 128, 136}},
2380 {45, 123, 1, {104, 112, 120, 128, 136}},
2381 {56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
2382 {57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
2383 {58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
2384 {128, 128, 2, {42, 58, 106, 122, 138, 155}},
2385 {129, 129, 3, {50, 114}},
2386 {130, 130, 2, {42, 58, 106, 122, 138, 155}},
2387 };
2388 /** oper class table for China*/
2389 static oper_bw_chan oper_bw_chan_cn[] = {
2390 /** non-Global oper class,global oper class, bandwidth, channel list*/
2391 {1, 115, 0, {36, 40, 44, 48}},
2392 {2, 118, 0, {52, 56, 60, 64}},
2393 {3, 125, 0, {149, 153, 157, 161, 165}},
2394 {4, 116, 1, {36, 44}},
2395 {5, 119, 1, {52, 60}},
2396 {6, 126, 1, {149, 157}},
2397 {7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
2398 {8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
2399 {9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
2400 {128, 128, 2, {42, 58, 106, 122, 138, 155}},
2401 {129, 129, 3, {50, 114}},
2402 {130, 130, 2, {42, 58, 106, 122, 138, 155}},
2403 };
2404
2405 /**
2406 * @brief Get non-global operaing class table according to country
2407 *
2408 * @param pmpriv A pointer to mlan_private structure
2409 * @param arraysize A pointer to table size
2410 *
2411 * @return A pointer to oper_bw_chan
2412 */
wlan_get_nonglobal_operclass_table(mlan_private * pmpriv,int * arraysize)2413 static oper_bw_chan *wlan_get_nonglobal_operclass_table(mlan_private *pmpriv,
2414 int *arraysize)
2415 {
2416 t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
2417 int country_id = 0;
2418 oper_bw_chan *poper_bw_chan = MNULL;
2419
2420 ENTER();
2421
2422 for (country_id = 0; country_id < 3; country_id++)
2423 if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
2424 country_code[country_id], COUNTRY_CODE_LEN - 1))
2425 break;
2426 if (country_id >= 3)
2427 country_id = COUNTRY_ID_US; /*Set default to US*/
2428 if (wlan_is_etsi_country(pmpriv->adapter,
2429 pmpriv->adapter->country_code))
2430 country_id = COUNTRY_ID_EU; /** Country in EU */
2431
2432 switch (country_id) {
2433 case COUNTRY_ID_US:
2434 poper_bw_chan = oper_bw_chan_us;
2435 *arraysize = sizeof(oper_bw_chan_us);
2436 break;
2437 case COUNTRY_ID_JP:
2438 poper_bw_chan = oper_bw_chan_jp;
2439 *arraysize = sizeof(oper_bw_chan_jp);
2440 break;
2441 case COUNTRY_ID_CN:
2442 poper_bw_chan = oper_bw_chan_cn;
2443 *arraysize = sizeof(oper_bw_chan_cn);
2444 break;
2445 case COUNTRY_ID_EU:
2446 poper_bw_chan = oper_bw_chan_eu;
2447 *arraysize = sizeof(oper_bw_chan_eu);
2448 break;
2449 default:
2450 PRINTM(MERROR, "Country not support!\n");
2451 break;
2452 }
2453
2454 LEAVE();
2455 return poper_bw_chan;
2456 }
2457
2458 /**
2459 * @brief Check validation of given channel and oper class
2460 *
2461 * @param pmpriv A pointer to mlan_private structure
2462 * @param channel Channel number
2463 * @param oper_class operating class
2464 *
2465 * @return MLAN_STATUS_PENDING --success, otherwise fail
2466 */
wlan_check_operclass_validation(mlan_private * pmpriv,t_u8 channel,t_u8 oper_class)2467 mlan_status wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
2468 t_u8 oper_class)
2469 {
2470 int arraysize = 0, i = 0, channum = 0;
2471 oper_bw_chan *poper_bw_chan = MNULL;
2472 t_u8 center_freq_idx = 0;
2473 t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
2474
2475 ENTER();
2476
2477 for (i = 0; i < (int)sizeof(center_freqs); i++) {
2478 if (channel == center_freqs[i]) {
2479 PRINTM(MERROR, "Invalid channel number %d!\n", channel);
2480 LEAVE();
2481 return MLAN_STATUS_FAILURE;
2482 }
2483 }
2484 if (oper_class <= 0 || oper_class > 130) {
2485 PRINTM(MERROR, "Invalid operating class!\n");
2486 LEAVE();
2487 return MLAN_STATUS_FAILURE;
2488 }
2489 if (oper_class >= 128) {
2490 center_freq_idx = wlan_get_center_freq_idx(
2491 pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
2492 channel = center_freq_idx;
2493 }
2494 poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
2495
2496 if (!poper_bw_chan) {
2497 PRINTM(MCMND, "Operating class table do not find!\n");
2498 LEAVE();
2499 return MLAN_STATUS_FAILURE;
2500 }
2501
2502 for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++) {
2503 if (poper_bw_chan[i].oper_class == oper_class ||
2504 poper_bw_chan[i].global_oper_class == oper_class) {
2505 for (channum = 0;
2506 channum <
2507 (int)sizeof(poper_bw_chan[i].channel_list);
2508 channum++) {
2509 if (poper_bw_chan[i].channel_list[channum] &&
2510 poper_bw_chan[i].channel_list[channum] ==
2511 channel) {
2512 LEAVE();
2513 return MLAN_STATUS_SUCCESS;
2514 }
2515 }
2516 }
2517 }
2518
2519 PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
2520 oper_class, channel);
2521 LEAVE();
2522 return MLAN_STATUS_FAILURE;
2523 }
2524
2525 /**
2526 * @brief Get current operating class from channel and bandwidth
2527 *
2528 * @param pmpriv A pointer to mlan_private structure
2529 * @param channel Channel number
2530 * @param bw Bandwidth
2531 * @param oper_class A pointer to current operating class
2532 *
2533 * @return MLAN_STATUS_PENDING --success, otherwise fail
2534 */
wlan_get_curr_oper_class(mlan_private * pmpriv,t_u8 channel,t_u8 bw,t_u8 * oper_class)2535 mlan_status wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel,
2536 t_u8 bw, t_u8 *oper_class)
2537 {
2538 oper_bw_chan *poper_bw_chan = MNULL;
2539 t_u8 center_freq_idx = 0;
2540 t_u8 center_freqs[] = {42, 50, 58, 106, 114, 122, 138, 155};
2541 int i = 0, arraysize = 0, channum = 0;
2542
2543 ENTER();
2544
2545 poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
2546
2547 if (!poper_bw_chan) {
2548 PRINTM(MCMND, "Operating class table do not find!\n");
2549 LEAVE();
2550 return MLAN_STATUS_FAILURE;
2551 }
2552 for (i = 0; i < (int)sizeof(center_freqs); i++) {
2553 if (channel == center_freqs[i]) {
2554 PRINTM(MERROR, "Invalid channel number %d!\n", channel);
2555 LEAVE();
2556 return MLAN_STATUS_FAILURE;
2557 }
2558 }
2559 if (bw == BW_80MHZ) {
2560 center_freq_idx = wlan_get_center_freq_idx(
2561 pmpriv, BAND_AAC, channel, CHANNEL_BW_80MHZ);
2562 channel = center_freq_idx;
2563 }
2564
2565 for (i = 0; i < (int)(arraysize / sizeof(oper_bw_chan)); i++) {
2566 if (poper_bw_chan[i].bandwidth == bw) {
2567 for (channum = 0;
2568 channum <
2569 (int)(sizeof(poper_bw_chan[i].channel_list));
2570 channum++) {
2571 if (poper_bw_chan[i].channel_list[channum] &&
2572 poper_bw_chan[i].channel_list[channum] ==
2573 channel) {
2574 *oper_class =
2575 poper_bw_chan[i].oper_class;
2576 return MLAN_STATUS_SUCCESS;
2577 }
2578 }
2579 }
2580 }
2581
2582 PRINTM(MCMND, "Operating class not found!\n");
2583 LEAVE();
2584 return MLAN_STATUS_FAILURE;
2585 }
2586
2587 /**
2588 * @brief Add Supported operating classes IE
2589 *
2590 * @param pmpriv A pointer to mlan_private structure
2591 * @param pptlv_out A pointer to TLV to fill in
2592 * @param curr_oper_class Current operating class
2593 *
2594 * @return Length
2595 */
wlan_add_supported_oper_class_ie(mlan_private * pmpriv,t_u8 ** pptlv_out,t_u8 curr_oper_class)2596 int wlan_add_supported_oper_class_ie(mlan_private *pmpriv, t_u8 **pptlv_out,
2597 t_u8 curr_oper_class)
2598 {
2599 t_u8 oper_class_us[] = {1, 2, 3, 4, 5, 12, 22, 23, 24, 25, 26,
2600 27, 28, 29, 30, 31, 32, 33, 128, 129, 130};
2601 t_u8 oper_class_eu[] = {1, 2, 3, 4, 5, 6, 7, 8,
2602 9, 10, 11, 12, 17, 128, 129, 130};
2603 t_u8 oper_class_jp[] = {1, 30, 31, 32, 33, 34, 35, 36,
2604 37, 38, 39, 40, 41, 42, 43, 44,
2605 45, 56, 57, 58, 128, 129, 130};
2606 t_u8 oper_class_cn[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 129, 130};
2607 t_u8 country_code[][COUNTRY_CODE_LEN] = {"US", "JP", "CN"};
2608 int country_id = 0, ret = 0;
2609 MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
2610
2611 ENTER();
2612
2613 for (country_id = 0; country_id < 3; country_id++)
2614 if (!memcmp(pmpriv->adapter, pmpriv->adapter->country_code,
2615 country_code[country_id], COUNTRY_CODE_LEN - 1))
2616 break;
2617 if (country_id >= 3)
2618 country_id = COUNTRY_ID_US; /*Set default to US*/
2619 if (wlan_is_etsi_country(pmpriv->adapter,
2620 pmpriv->adapter->country_code))
2621 country_id = COUNTRY_ID_EU; /** Country in EU */
2622 poper_class = (MrvlIETypes_SuppOperClass_t *)*pptlv_out;
2623 memset(pmpriv->adapter, poper_class, 0,
2624 sizeof(MrvlIETypes_SuppOperClass_t));
2625 poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
2626 if (country_id == COUNTRY_ID_US) {
2627 poper_class->header.len = sizeof(oper_class_us);
2628 memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2629 oper_class_us, sizeof(oper_class_us),
2630 poper_class->header.len);
2631 } else if (country_id == COUNTRY_ID_JP) {
2632 poper_class->header.len = sizeof(oper_class_jp);
2633 memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2634 oper_class_jp, sizeof(oper_class_jp),
2635 poper_class->header.len);
2636 } else if (country_id == COUNTRY_ID_CN) {
2637 poper_class->header.len = sizeof(oper_class_cn);
2638 memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2639 oper_class_cn, sizeof(oper_class_cn),
2640 poper_class->header.len);
2641 } else if (country_id == COUNTRY_ID_EU) {
2642 poper_class->header.len = sizeof(oper_class_eu);
2643 memcpy_ext(pmpriv->adapter, &poper_class->oper_class,
2644 oper_class_eu, sizeof(oper_class_eu),
2645 poper_class->header.len);
2646 }
2647 poper_class->current_oper_class = curr_oper_class;
2648 poper_class->header.len += sizeof(poper_class->current_oper_class);
2649 DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class,
2650 sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
2651 ret = sizeof(MrvlIEtypesHeader_t) + poper_class->header.len;
2652 *pptlv_out += ret;
2653 poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
2654
2655 LEAVE();
2656 return ret;
2657 }
2658
2659 /**
2660 * @brief This function sets region table.
2661 *
2662 * @param pmpriv A pointer to mlan_private structure
2663 * @param region The region code
2664 * @param band The band
2665 *
2666 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2667 */
wlan_set_regiontable(mlan_private * pmpriv,t_u8 region,t_u16 band)2668 mlan_status wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u16 band)
2669 {
2670 mlan_adapter *pmadapter = pmpriv->adapter;
2671 int i = 0, j;
2672 chan_freq_power_t *cfp;
2673 int cfp_no;
2674 region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];
2675 t_u8 cfp_code_bg = region;
2676 t_u8 cfp_code_a = region;
2677
2678 ENTER();
2679
2680 memcpy_ext(pmadapter, region_chan_old, pmadapter->region_channel,
2681 sizeof(pmadapter->region_channel), sizeof(region_chan_old));
2682 memset(pmadapter, pmadapter->region_channel, 0,
2683 sizeof(pmadapter->region_channel));
2684
2685 if (band & (BAND_B | BAND_G | BAND_GN)) {
2686 if (pmadapter->cfp_code_bg)
2687 cfp_code_bg = pmadapter->cfp_code_bg;
2688 PRINTM(MCMND, "%s: 2.4G 0x%x\n", __func__, cfp_code_bg);
2689 cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
2690 BAND_G | BAND_B | BAND_GN,
2691 &cfp_no);
2692 if (cfp) {
2693 pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
2694 pmadapter->region_channel[i].pcfp = cfp;
2695 } else {
2696 PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
2697 region);
2698 LEAVE();
2699 return MLAN_STATUS_FAILURE;
2700 }
2701 pmadapter->region_channel[i].valid = MTRUE;
2702 pmadapter->region_channel[i].region = region;
2703 if (band & BAND_GN)
2704 pmadapter->region_channel[i].band = BAND_G;
2705 else
2706 pmadapter->region_channel[i].band =
2707 (band & BAND_G) ? BAND_G : BAND_B;
2708
2709 for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
2710 if (region_chan_old[j].band & (BAND_B | BAND_G))
2711 break;
2712 }
2713
2714 if ((j < MAX_REGION_CHANNEL_NUM) &&
2715 (region_chan_old[j].valid == MTRUE)) {
2716 wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
2717 region_chan_old[j].pcfp,
2718 region_chan_old[j].num_cfp);
2719 } else if (cfp) {
2720 wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
2721 }
2722 i++;
2723 }
2724 if (band & (BAND_A | BAND_AN | BAND_AAC)) {
2725 if (pmadapter->cfp_code_a)
2726 cfp_code_a = pmadapter->cfp_code_a;
2727 PRINTM(MCMND, "%s: 5G 0x%x\n", __func__, cfp_code_a);
2728 cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
2729 &cfp_no);
2730 if (cfp) {
2731 pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
2732 pmadapter->region_channel[i].pcfp = cfp;
2733 } else {
2734 PRINTM(MERROR, "wrong region code %#x in Band A\n",
2735 region);
2736 LEAVE();
2737 return MLAN_STATUS_FAILURE;
2738 }
2739 pmadapter->region_channel[i].valid = MTRUE;
2740 pmadapter->region_channel[i].region = region;
2741 pmadapter->region_channel[i].band = BAND_A;
2742
2743 for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
2744 if (region_chan_old[j].band & BAND_A)
2745 break;
2746 }
2747 if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid) {
2748 wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
2749 region_chan_old[j].pcfp,
2750 region_chan_old[j].num_cfp);
2751 } else if (cfp) {
2752 wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
2753 }
2754 i++;
2755 }
2756 LEAVE();
2757 return MLAN_STATUS_SUCCESS;
2758 }
2759
2760 /**
2761 * @brief Get if radar detection is enabled or not on a certain channel
2762 *
2763 * @param priv Private driver information structure
2764 * @param chnl Channel to determine radar detection requirements
2765 *
2766 * @return
2767 * - MTRUE if radar detection is required
2768 * - MFALSE otherwise
2769 */
wlan_get_cfp_radar_detect(mlan_private * priv,t_u8 chnl)2770 t_bool wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
2771 {
2772 int i, j;
2773 t_bool required = MFALSE;
2774 chan_freq_power_t *pcfp = MNULL;
2775
2776 ENTER();
2777
2778 /*get the cfp table first*/
2779 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2780 if (priv->adapter->region_channel[i].band == BAND_A) {
2781 pcfp = priv->adapter->region_channel[i].pcfp;
2782 break;
2783 }
2784 }
2785
2786 if (!pcfp) {
2787 /* This means operation in BAND-A is not support, we can
2788 * just return false here, it's harmless
2789 */
2790 goto done;
2791 }
2792
2793 /*get the radar detection requirements according to chan num*/
2794 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2795 if (pcfp[j].channel == chnl) {
2796 required = pcfp[j].passive_scan_or_radar_detect;
2797 break;
2798 }
2799 }
2800
2801 done:
2802 LEAVE();
2803 return required;
2804 }
2805
2806 /**
2807 * @brief Get if scan type is passive or not on a certain channel for b/g band
2808 *
2809 * @param priv Private driver information structure
2810 * @param chnl Channel to determine scan type
2811 *
2812 * @return
2813 * - MTRUE if scan type is passive
2814 * - MFALSE otherwise
2815 */
wlan_bg_scan_type_is_passive(mlan_private * priv,t_u8 chnl)2816 t_bool wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
2817 {
2818 int i, j;
2819 t_bool passive = MFALSE;
2820 chan_freq_power_t *pcfp = MNULL;
2821
2822 ENTER();
2823
2824 /*get the cfp table first*/
2825 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2826 if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) {
2827 pcfp = priv->adapter->region_channel[i].pcfp;
2828 break;
2829 }
2830 }
2831
2832 if (!pcfp) {
2833 /*This means operation in BAND-B or BAND_G is not support, we
2834 * can just return false here
2835 */
2836 goto done;
2837 }
2838
2839 /*get the bg scan type according to chan num*/
2840 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2841 if (pcfp[j].channel == chnl) {
2842 passive = pcfp[j].passive_scan_or_radar_detect;
2843 break;
2844 }
2845 }
2846
2847 done:
2848 LEAVE();
2849 return passive;
2850 }
2851
2852 /**
2853 * @brief Get if a channel is NO_IR (passive) or not
2854 *
2855 * @param priv Private driver information structure
2856 * @param band Band to check
2857 * @param chan Channel to check
2858 *
2859 * @return
2860 * - MTRUE if channel is passive
2861 * - MFALSE otherwise
2862 */
2863
wlan_is_chan_passive(mlan_private * priv,t_u16 band,t_u8 chan)2864 t_bool wlan_is_chan_passive(mlan_private *priv, t_u16 band, t_u8 chan)
2865 {
2866 int i, j;
2867 t_bool passive = MFALSE;
2868 chan_freq_power_t *pcfp = MNULL;
2869
2870 ENTER();
2871
2872 /* get the cfp table first */
2873 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2874 if (priv->adapter->region_channel[i].band & band) {
2875 pcfp = priv->adapter->region_channel[i].pcfp;
2876 break;
2877 }
2878 }
2879
2880 if (pcfp) {
2881 /* check table according to chan num */
2882 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2883 if (pcfp[j].channel == chan) {
2884 if (pcfp[j].dynamic.flags & NXP_CHANNEL_PASSIVE)
2885 passive = MTRUE;
2886 break;
2887 }
2888 }
2889 }
2890
2891 LEAVE();
2892 return passive;
2893 }
2894
2895 /**
2896 * @brief Get if a channel is disabled or not
2897 *
2898 * @param priv Private driver information structure
2899 * @param band Band to check
2900 * @param chan Channel to check
2901 *
2902 * @return
2903 * - MTRUE if channel is disabled
2904 * - MFALSE otherwise
2905 */
2906
wlan_is_chan_disabled(mlan_private * priv,t_u16 band,t_u8 chan)2907 t_bool wlan_is_chan_disabled(mlan_private *priv, t_u16 band, t_u8 chan)
2908 {
2909 int i, j;
2910 t_bool disabled = MFALSE;
2911 chan_freq_power_t *pcfp = MNULL;
2912
2913 ENTER();
2914
2915 /* get the cfp table first */
2916 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2917 if (priv->adapter->region_channel[i].band & band) {
2918 pcfp = priv->adapter->region_channel[i].pcfp;
2919 break;
2920 }
2921 }
2922
2923 if (pcfp) {
2924 /* check table according to chan num */
2925 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2926 if (pcfp[j].channel == chan) {
2927 if (pcfp[j].dynamic.flags &
2928 NXP_CHANNEL_DISABLED)
2929 disabled = MTRUE;
2930 break;
2931 }
2932 }
2933 }
2934
2935 LEAVE();
2936 return disabled;
2937 }
2938
2939 /**
2940 * @brief Get if a channel is blacklisted or not
2941 *
2942 * @param priv Private driver information structure
2943 * @param band Band to check
2944 * @param chan Channel to check
2945 *
2946 * @return
2947 * - MTRUE if channel is blacklisted
2948 * - MFALSE otherwise
2949 */
2950
wlan_is_chan_blacklisted(mlan_private * priv,t_u16 band,t_u8 chan)2951 t_bool wlan_is_chan_blacklisted(mlan_private *priv, t_u16 band, t_u8 chan)
2952 {
2953 int i, j;
2954 t_bool blacklist = MFALSE;
2955 chan_freq_power_t *pcfp = MNULL;
2956
2957 ENTER();
2958
2959 /*get the cfp table first*/
2960 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
2961 if (priv->adapter->region_channel[i].band & band) {
2962 pcfp = priv->adapter->region_channel[i].pcfp;
2963 break;
2964 }
2965 }
2966
2967 if (pcfp) {
2968 /*check table according to chan num*/
2969 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
2970 if (pcfp[j].channel == chan) {
2971 blacklist = pcfp[j].dynamic.blacklist;
2972 break;
2973 }
2974 }
2975 }
2976
2977 LEAVE();
2978 return blacklist;
2979 }
2980
2981 /**
2982 * @brief Set a channel as blacklisted or not
2983 *
2984 * @param priv Private driver information structure
2985 * @param band Band to check
2986 * @param chan Channel to check
2987 * @param bl Blacklist if MTRUE
2988 *
2989 * @return
2990 * - MTRUE if channel setting is updated
2991 * - MFALSE otherwise
2992 */
2993
wlan_set_chan_blacklist(mlan_private * priv,t_u16 band,t_u8 chan,t_bool bl)2994 t_bool wlan_set_chan_blacklist(mlan_private *priv, t_u16 band, t_u8 chan,
2995 t_bool bl)
2996 {
2997 int i, j;
2998 t_bool set_bl = MFALSE;
2999 chan_freq_power_t *pcfp = MNULL;
3000
3001 ENTER();
3002
3003 /*get the cfp table first*/
3004 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3005 if (priv->adapter->region_channel[i].band & band) {
3006 pcfp = priv->adapter->region_channel[i].pcfp;
3007 break;
3008 }
3009 }
3010
3011 if (pcfp) {
3012 /*check table according to chan num*/
3013 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3014 if (pcfp[j].channel == chan) {
3015 pcfp[j].dynamic.blacklist = bl;
3016 set_bl = MTRUE;
3017 break;
3018 }
3019 }
3020 }
3021
3022 LEAVE();
3023 return set_bl;
3024 }
3025
3026 /**
3027 * @brief Set channel's dfs state
3028 *
3029 * @param priv Private driver information structure
3030 * @param band Band to check
3031 * @param chan Channel to check
3032 * @param dfs_state dfs state
3033 *
3034 * @return N/A
3035 */
wlan_set_chan_dfs_state(mlan_private * priv,t_u16 band,t_u8 chan,dfs_state_t dfs_state)3036 t_void wlan_set_chan_dfs_state(mlan_private *priv, t_u16 band, t_u8 chan,
3037 dfs_state_t dfs_state)
3038 {
3039 int i, j;
3040 chan_freq_power_t *pcfp = MNULL;
3041
3042 ENTER();
3043
3044 /*get the cfp table first*/
3045 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3046 if (priv->adapter->region_channel[i].band & band) {
3047 pcfp = priv->adapter->region_channel[i].pcfp;
3048 break;
3049 }
3050 }
3051
3052 if (pcfp) {
3053 /*check table according to chan num*/
3054 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3055 if (pcfp[j].channel == chan) {
3056 pcfp[j].dynamic.dfs_state = dfs_state;
3057 break;
3058 }
3059 }
3060 }
3061
3062 LEAVE();
3063 }
3064
3065 /**
3066 * @brief get channel's dfs state
3067 *
3068 * @param priv Private driver information structure
3069 * @param band Band to check
3070 * @param chan Channel to check
3071 *
3072 * @return channel's dfs state
3073 */
wlan_get_chan_dfs_state(mlan_private * priv,t_u16 band,t_u8 chan)3074 dfs_state_t wlan_get_chan_dfs_state(mlan_private *priv, t_u16 band, t_u8 chan)
3075 {
3076 int i, j;
3077 chan_freq_power_t *pcfp = MNULL;
3078 dfs_state_t dfs_state = DFS_USABLE;
3079
3080 ENTER();
3081
3082 /*get the cfp table first*/
3083 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3084 if (priv->adapter->region_channel[i].band & band) {
3085 pcfp = priv->adapter->region_channel[i].pcfp;
3086 break;
3087 }
3088 }
3089
3090 if (pcfp) {
3091 /*check table according to chan num*/
3092 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3093 if (pcfp[j].channel == chan) {
3094 dfs_state = pcfp[j].dynamic.dfs_state;
3095 break;
3096 }
3097 }
3098 }
3099
3100 LEAVE();
3101 return dfs_state;
3102 }
3103
3104 /**
3105 * @brief reset all channel's dfs state
3106 *
3107 * @param priv Private driver information structure
3108 * @param band Band to check
3109 * @param dfs_state dfs state
3110 *
3111 * @return N/A
3112 */
wlan_reset_all_chan_dfs_state(mlan_private * priv,t_u16 band,dfs_state_t dfs_state)3113 t_void wlan_reset_all_chan_dfs_state(mlan_private *priv, t_u16 band,
3114 dfs_state_t dfs_state)
3115 {
3116 int i, j;
3117 chan_freq_power_t *pcfp = MNULL;
3118
3119 ENTER();
3120
3121 /*get the cfp table first*/
3122 for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
3123 if (priv->adapter->region_channel[i].band & band) {
3124 pcfp = priv->adapter->region_channel[i].pcfp;
3125 break;
3126 }
3127 }
3128
3129 if (pcfp) {
3130 /*check table according to chan num*/
3131 for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
3132 pcfp[j].dynamic.dfs_state = dfs_state;
3133 }
3134 }
3135
3136 LEAVE();
3137 }
3138
3139 /**
3140 * @brief Convert rateid in IEEE format to MRVL format
3141 *
3142 * @param priv Private driver information structure
3143 * @param IeeeMacRate Rate in terms of IEEE format
3144 * @param pmbuf A pointer to packet buffer
3145 *
3146 * @return
3147 * Rate ID in terms of MRVL format
3148 */
wlan_ieee_rateid_to_mrvl_rateid(mlan_private * priv,t_u16 IeeeMacRate,t_u8 * dst_mac)3149 t_u8 wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
3150 t_u8 *dst_mac)
3151 {
3152 /* Set default rate ID to RATEID_DBPSK1Mbps */
3153 t_u8 mrvlRATEID = 0;
3154 const rate_map *rate_tbl = rate_map_table_1x1;
3155 t_u32 cnt = sizeof(rate_map_table_1x1) / sizeof(rate_map);
3156 t_u8 skip_nss2 = MTRUE;
3157 t_u32 i = 0;
3158 IEEEtypes_HTCap_t *htcap = MNULL;
3159 t_u8 tx_mcs_supp = GET_TXMCSSUPP(priv->usr_dev_mcs_support);
3160 #ifdef UAP_SUPPORT
3161 psta_node sta_ptr = MNULL;
3162 #endif
3163
3164 ENTER();
3165
3166 if (priv->adapter->hw_dev_mcs_support == HT_STREAM_MODE_2X2) {
3167 rate_tbl = rate_map_table_2x2;
3168 cnt = sizeof(rate_map_table_2x2) / sizeof(rate_map);
3169 }
3170
3171 #ifdef UAP_SUPPORT
3172 if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
3173 if (!dst_mac) {
3174 LEAVE();
3175 return mrvlRATEID;
3176 }
3177 sta_ptr = (sta_node *)util_peek_list(
3178 priv->adapter->pmoal_handle, &priv->sta_list,
3179 priv->adapter->callbacks.moal_spin_lock,
3180 priv->adapter->callbacks.moal_spin_unlock);
3181 if (!sta_ptr) {
3182 LEAVE();
3183 return mrvlRATEID;
3184 }
3185 while (sta_ptr != (sta_node *)&priv->sta_list) {
3186 if (memcmp(priv->adapter, dst_mac, sta_ptr->mac_addr,
3187 MLAN_MAC_ADDR_LENGTH)) {
3188 htcap = &(sta_ptr->HTcap);
3189 break;
3190 }
3191 sta_ptr = sta_ptr->pnext;
3192 }
3193 }
3194 #endif
3195 #ifdef STA_SUPPORT
3196 if (priv->bss_role == MLAN_BSS_ROLE_STA)
3197 htcap = priv->curr_bss_params.bss_descriptor.pht_cap;
3198 #endif
3199 if (htcap) {
3200 /* If user configure tx to 2x2 and peer device rx is 2x2 */
3201 if (tx_mcs_supp >= 2 && htcap->ht_cap.supported_mcs_set[1])
3202 skip_nss2 = MFALSE;
3203 }
3204
3205 for (i = 0; i < cnt; i++) {
3206 if (rate_tbl[i].nss && skip_nss2)
3207 continue;
3208 if (rate_tbl[i].rate == IeeeMacRate) {
3209 mrvlRATEID = rate_tbl[i].id;
3210 break;
3211 }
3212 }
3213
3214 return mrvlRATEID;
3215 }
3216
3217 /**
3218 * @brief Convert rateid in MRVL format to IEEE format
3219 *
3220 * @param IeeeMacRate Rate in terms of MRVL format
3221 *
3222 * @return
3223 * Rate ID in terms of IEEE format
3224 */
wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)3225 t_u8 wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
3226 {
3227 return rateUnit_500Kbps[rate];
3228 }
3229
3230 /**
3231 * @brief sort cfp otp table
3232 *
3233 * @param pmapdater a pointer to mlan_adapter structure
3234 *
3235 * @return
3236 * None
3237 */
wlan_sort_cfp_otp_table(mlan_adapter * pmadapter)3238 static void wlan_sort_cfp_otp_table(mlan_adapter *pmadapter)
3239 {
3240 t_u8 c, d;
3241 chan_freq_power_t *ch1;
3242 chan_freq_power_t *ch2;
3243 chan_freq_power_t swap;
3244
3245 if (pmadapter->tx_power_table_a_rows <= 1)
3246 return;
3247 for (c = 0; c < pmadapter->tx_power_table_a_rows - 1; c++) {
3248 for (d = 0; d < pmadapter->tx_power_table_a_rows - c - 1; d++) {
3249 ch1 = (chan_freq_power_t *)(pmadapter->cfp_otp_a + d);
3250 ch2 = (chan_freq_power_t *)(pmadapter->cfp_otp_a + d +
3251 1);
3252 if (ch1->channel > ch2->channel) {
3253 memcpy_ext(pmadapter, &swap, ch1,
3254 sizeof(chan_freq_power_t),
3255 sizeof(chan_freq_power_t));
3256 memcpy_ext(pmadapter, ch1, ch2,
3257 sizeof(chan_freq_power_t),
3258 sizeof(chan_freq_power_t));
3259 memcpy_ext(pmadapter, ch2, &swap,
3260 sizeof(chan_freq_power_t),
3261 sizeof(chan_freq_power_t));
3262 }
3263 }
3264 }
3265 }
3266
3267 /**
3268 * @brief Update CFP tables and power tables from FW
3269 *
3270 * @param priv Private driver information structure
3271 * @param buf Pointer to the buffer holding TLV data
3272 * from 0x242 command response.
3273 * @param buf_left bufsize
3274 *
3275 * @return
3276 * None
3277 */
wlan_add_fw_cfp_tables(pmlan_private pmpriv,t_u8 * buf,t_u16 buf_left)3278 void wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
3279 {
3280 mlan_adapter *pmadapter = pmpriv->adapter;
3281 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
3282 MrvlIEtypesHeader_t *head;
3283 t_u16 tlv;
3284 t_u16 tlv_buf_len;
3285 t_u16 tlv_buf_left;
3286 t_u16 i;
3287 int k = 0, rows, cols;
3288 t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
3289 t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
3290 t_u8 *tlv_buf;
3291 t_u8 *data;
3292 t_u8 *tmp;
3293 mlan_status ret;
3294
3295 ENTER();
3296
3297 if (!buf) {
3298 PRINTM(MERROR, "CFP table update failed!\n");
3299 goto out;
3300 }
3301 if (pmadapter->otp_region) {
3302 memset(pmadapter, pmadapter->region_channel, 0,
3303 sizeof(pmadapter->region_channel));
3304 wlan_free_fw_cfp_tables(pmadapter);
3305 }
3306 pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
3307 pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
3308 pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
3309 pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
3310 tlv_buf = (t_u8 *)buf;
3311 tlv_buf_left = buf_left;
3312
3313 while (tlv_buf_left >= sizeof(*head)) {
3314 head = (MrvlIEtypesHeader_t *)tlv_buf;
3315 tlv = wlan_le16_to_cpu(head->type);
3316 tlv_buf_len = wlan_le16_to_cpu(head->len);
3317
3318 if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
3319 break;
3320 data = (t_u8 *)head + sizeof(*head);
3321
3322 switch (tlv) {
3323 case TLV_TYPE_REGION_INFO:
3324 /* Skip adding fw region info if it already exists or
3325 * if this TLV has no set data
3326 */
3327 if (*data == 0)
3328 break;
3329 if (pmadapter->otp_region)
3330 break;
3331
3332 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
3333 sizeof(otp_region_info_t),
3334 MLAN_MEM_DEF,
3335 (t_u8 **)&pmadapter->otp_region);
3336 if (ret != MLAN_STATUS_SUCCESS ||
3337 !pmadapter->otp_region) {
3338 PRINTM(MERROR,
3339 "Memory allocation for the otp region info struct failed!\n");
3340 break;
3341 }
3342 /* Save region info values from OTP in the otp_region
3343 * structure
3344 */
3345 memcpy_ext(pmadapter, pmadapter->otp_region, data,
3346 sizeof(otp_region_info_t),
3347 sizeof(otp_region_info_t));
3348 data += sizeof(otp_region_info_t);
3349 /* Get pre-defined cfp tables corresponding to the
3350 * region code in OTP
3351 */
3352 for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
3353 if (cfp_table_BG[i].code ==
3354 pmadapter->otp_region->region_code) {
3355 max_tx_pwr_bg = (cfp_table_BG[i].cfp)
3356 ->max_tx_power;
3357 break;
3358 }
3359 }
3360 for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
3361 if (cfp_table_A[i].code ==
3362 pmadapter->otp_region->region_code) {
3363 max_tx_pwr_a = (cfp_table_A[i].cfp)
3364 ->max_tx_power;
3365 break;
3366 }
3367 }
3368 /* Update the region code and the country code in
3369 * pmadapter
3370 */
3371 pmadapter->region_code =
3372 pmadapter->otp_region->region_code;
3373 pmadapter->country_code[0] =
3374 pmadapter->otp_region->country_code[0];
3375 pmadapter->country_code[1] =
3376 pmadapter->otp_region->country_code[1];
3377 pmadapter->country_code[2] = '\0';
3378 pmadapter->domain_reg.country_code[0] =
3379 pmadapter->otp_region->country_code[0];
3380 pmadapter->domain_reg.country_code[1] =
3381 pmadapter->otp_region->country_code[1];
3382 pmadapter->domain_reg.country_code[2] = '\0';
3383 PRINTM(MCMND,
3384 "OTP region: region_code=%d %c%c dfs_region=%d\n",
3385 pmadapter->otp_region->region_code,
3386 pmadapter->country_code[0],
3387 pmadapter->country_code[1],
3388 pmadapter->otp_region->dfs_region);
3389 pmadapter->cfp_code_bg =
3390 pmadapter->otp_region->region_code;
3391 pmadapter->cfp_code_a =
3392 pmadapter->otp_region->region_code;
3393 break;
3394 case TLV_TYPE_CHAN_ATTR_CFG:
3395 /* Skip adding fw cfp tables if they already exist or
3396 * if this TLV has no set data
3397 */
3398 if (*data == 0)
3399 break;
3400 if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
3401 break;
3402 }
3403
3404 ret = pcb->moal_malloc(
3405 pmadapter->pmoal_handle,
3406 pmadapter->tx_power_table_bg_rows *
3407 sizeof(chan_freq_power_t),
3408 MLAN_MEM_DEF, (t_u8 **)&pmadapter->cfp_otp_bg);
3409 if (ret != MLAN_STATUS_SUCCESS ||
3410 !pmadapter->cfp_otp_bg) {
3411 PRINTM(MERROR,
3412 "Memory allocation for storing otp bg table data failed!\n");
3413 break;
3414 }
3415 /* Save channel usability flags from OTP data in the fw
3416 * cfp bg table and set frequency and max_tx_power
3417 * values
3418 */
3419 for (i = 0; i < pmadapter->tx_power_table_bg_rows;
3420 i++) {
3421 (pmadapter->cfp_otp_bg + i)->channel = *data;
3422 if (*data == 14)
3423 (pmadapter->cfp_otp_bg + i)->freq =
3424 2484;
3425 else
3426 (pmadapter->cfp_otp_bg + i)->freq =
3427 2412 + 5 * (*data - 1);
3428 (pmadapter->cfp_otp_bg + i)->max_tx_power =
3429 max_tx_pwr_bg;
3430 data++;
3431 (pmadapter->cfp_otp_bg + i)->dynamic.flags =
3432 *data;
3433 if (*data & NXP_CHANNEL_DFS)
3434 (pmadapter->cfp_otp_bg + i)
3435 ->passive_scan_or_radar_detect =
3436 MTRUE;
3437 PRINTM(MCMD_D,
3438 "OTP Region (BG): chan=%d flags=0x%x\n",
3439 (pmadapter->cfp_otp_bg + i)->channel,
3440 (pmadapter->cfp_otp_bg + i)
3441 ->dynamic.flags);
3442 data++;
3443 }
3444 ret = pcb->moal_malloc(
3445 pmadapter->pmoal_handle,
3446 pmadapter->tx_power_table_a_rows *
3447 sizeof(chan_freq_power_t),
3448 MLAN_MEM_DEF, (t_u8 **)&pmadapter->cfp_otp_a);
3449 if (ret != MLAN_STATUS_SUCCESS ||
3450 !pmadapter->cfp_otp_a) {
3451 PRINTM(MERROR,
3452 "Memory allocation for storing otp a table data failed!\n");
3453 break;
3454 }
3455 /* Save channel usability flags from OTP data in the fw
3456 * cfp a table and set frequency and max_tx_power values
3457 */
3458 for (i = 0; i < pmadapter->tx_power_table_a_rows; i++) {
3459 (pmadapter->cfp_otp_a + i)->channel = *data;
3460 if (*data < 183)
3461 /* 5GHz channels */
3462 (pmadapter->cfp_otp_a + i)->freq =
3463 5035 + 5 * (*data - 7);
3464 else
3465 /* 4GHz channels */
3466 (pmadapter->cfp_otp_a + i)->freq =
3467 4915 + 5 * (*data - 183);
3468 (pmadapter->cfp_otp_a + i)->max_tx_power =
3469 max_tx_pwr_a;
3470 data++;
3471 (pmadapter->cfp_otp_a + i)->dynamic.flags =
3472 *data;
3473 (pmadapter->cfp_otp_a + i)->dynamic.dfs_state =
3474 DFS_USABLE;
3475 if (*data & NXP_CHANNEL_DFS)
3476 (pmadapter->cfp_otp_a + i)
3477 ->passive_scan_or_radar_detect =
3478 MTRUE;
3479 PRINTM(MCMD_D,
3480 "OTP Region (A): chan=%d flags=0x%x\n",
3481 (pmadapter->cfp_otp_a + i)->channel,
3482 (pmadapter->cfp_otp_a + i)
3483 ->dynamic.flags);
3484
3485 data++;
3486 }
3487 break;
3488 case TLV_TYPE_POWER_TABLE:
3489 /* Skip adding fw power tables if this TLV has no data
3490 * or if they already exists but force reg rule is set
3491 * in the otp
3492 */
3493 if (*data == 0)
3494 break;
3495 if (pmadapter->otp_region &&
3496 pmadapter->otp_region->force_reg &&
3497 pmadapter->tx_power_table_bg)
3498 break;
3499
3500 /* Save the tlv data in power tables for band BG and A
3501 */
3502 tmp = data;
3503 i = 0;
3504 while ((i <
3505 pmadapter->tx_power_table_bg_rows *
3506 pmadapter->tx_power_table_bg_cols) &&
3507 (i < tlv_buf_len)) {
3508 i++;
3509 tmp++;
3510 }
3511 if (!pmadapter->tx_power_table_bg) {
3512 ret = pcb->moal_malloc(
3513 pmadapter->pmoal_handle, i,
3514 MLAN_MEM_DEF,
3515 (t_u8 **)&pmadapter->tx_power_table_bg);
3516 if (ret != MLAN_STATUS_SUCCESS ||
3517 !pmadapter->tx_power_table_bg) {
3518 PRINTM(MERROR,
3519 "Memory allocation for the BG-band power table failed!\n");
3520 break;
3521 }
3522 }
3523 memcpy_ext(pmadapter, pmadapter->tx_power_table_bg,
3524 data, i, i);
3525 pmadapter->tx_power_table_bg_size = i;
3526 data += i;
3527 i = 0;
3528 while ((i < pmadapter->tx_power_table_a_rows *
3529 pmadapter->tx_power_table_a_cols) &&
3530 (i < (tlv_buf_len -
3531 pmadapter->tx_power_table_bg_size))) {
3532 i++;
3533 }
3534 if (!pmadapter->tx_power_table_a) {
3535 ret = pcb->moal_malloc(
3536 pmadapter->pmoal_handle, i,
3537 MLAN_MEM_DEF,
3538 (t_u8 **)&pmadapter->tx_power_table_a);
3539 if (ret != MLAN_STATUS_SUCCESS ||
3540 !pmadapter->tx_power_table_a) {
3541 PRINTM(MERROR,
3542 "Memory allocation for the A-band power table failed!\n");
3543 break;
3544 }
3545 }
3546 memcpy_ext(pmadapter, pmadapter->tx_power_table_a, data,
3547 i, i);
3548 pmadapter->tx_power_table_a_size = i;
3549 break;
3550 case TLV_TYPE_POWER_TABLE_ATTR:
3551 pmadapter->tx_power_table_bg_rows =
3552 ((power_table_attr_t *)data)->rows_2g;
3553 pmadapter->tx_power_table_bg_cols =
3554 ((power_table_attr_t *)data)->cols_2g;
3555 pmadapter->tx_power_table_a_rows =
3556 ((power_table_attr_t *)data)->rows_5g;
3557 pmadapter->tx_power_table_a_cols =
3558 ((power_table_attr_t *)data)->cols_5g;
3559 PRINTM(MCMD_D,
3560 "OTP region: bg_row=%d,bg_cols=%d a_row=%d, a_cols=%d\n",
3561 pmadapter->tx_power_table_bg_rows,
3562 pmadapter->tx_power_table_bg_cols,
3563 pmadapter->tx_power_table_a_rows,
3564 pmadapter->tx_power_table_a_cols);
3565 break;
3566 default:
3567 break;
3568 }
3569 tlv_buf += (sizeof(*head) + tlv_buf_len);
3570 tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
3571 }
3572 if (!pmadapter->cfp_otp_bg || !pmadapter->tx_power_table_bg)
3573 goto out;
3574 /* Set remaining flags for BG */
3575 rows = pmadapter->tx_power_table_bg_rows;
3576 cols = pmadapter->tx_power_table_bg_cols;
3577
3578 for (i = 0; i < rows; i++) {
3579 k = (i * cols) + 1;
3580 if ((pmadapter->cfp_otp_bg + i)->dynamic.flags &
3581 NXP_CHANNEL_DISABLED)
3582 continue;
3583
3584 if (pmadapter->tx_power_table_bg[k + MOD_CCK] == 0)
3585 (pmadapter->cfp_otp_bg + i)->dynamic.flags |=
3586 NXP_CHANNEL_NO_CCK;
3587
3588 if (pmadapter->tx_power_table_bg[k + MOD_OFDM_PSK] == 0 &&
3589 pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM16] == 0 &&
3590 pmadapter->tx_power_table_bg[k + MOD_OFDM_QAM64] == 0) {
3591 (pmadapter->cfp_otp_bg + i)->dynamic.flags |=
3592 NXP_CHANNEL_NO_OFDM;
3593 }
3594 }
3595 if (pmadapter->cfp_otp_a)
3596 wlan_sort_cfp_otp_table(pmadapter);
3597 out:
3598 LEAVE();
3599 }
3600
3601 /**
3602 * @brief This function deallocates otp cfp and power tables memory.
3603 *
3604 * @param pmadapter A pointer to mlan_adapter structure
3605 */
wlan_free_fw_cfp_tables(mlan_adapter * pmadapter)3606 void wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
3607 {
3608 pmlan_callbacks pcb;
3609
3610 ENTER();
3611
3612 pcb = &pmadapter->callbacks;
3613 if (pmadapter->otp_region)
3614 pcb->moal_mfree(pmadapter->pmoal_handle,
3615 (t_u8 *)pmadapter->otp_region);
3616 if (pmadapter->cfp_otp_bg)
3617 pcb->moal_mfree(pmadapter->pmoal_handle,
3618 (t_u8 *)pmadapter->cfp_otp_bg);
3619 if (pmadapter->tx_power_table_bg)
3620 pcb->moal_mfree(pmadapter->pmoal_handle,
3621 (t_u8 *)pmadapter->tx_power_table_bg);
3622 pmadapter->otp_region = MNULL;
3623 pmadapter->cfp_otp_bg = MNULL;
3624 pmadapter->tx_power_table_bg = MNULL;
3625 pmadapter->tx_power_table_bg_size = 0;
3626 if (pmadapter->cfp_otp_a)
3627 pcb->moal_mfree(pmadapter->pmoal_handle,
3628 (t_u8 *)pmadapter->cfp_otp_a);
3629 if (pmadapter->tx_power_table_a)
3630 pcb->moal_mfree(pmadapter->pmoal_handle,
3631 (t_u8 *)pmadapter->tx_power_table_a);
3632 pmadapter->cfp_otp_a = MNULL;
3633 pmadapter->tx_power_table_a = MNULL;
3634 pmadapter->tx_power_table_a_size = 0;
3635 LEAVE();
3636 }
3637
3638 /**
3639 * @brief Get DFS chan list
3640 *
3641 * @param pmadapter Pointer to mlan_adapter
3642 * @param pioctl_req Pointer to mlan_ioctl_req
3643 *
3644 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3645 */
wlan_get_cfp_table(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3646 mlan_status wlan_get_cfp_table(pmlan_adapter pmadapter,
3647 pmlan_ioctl_req pioctl_req)
3648 {
3649 mlan_ds_misc_cfg *ds_misc_cfg = MNULL;
3650 mlan_status ret = MLAN_STATUS_FAILURE;
3651 chan_freq_power_t *cfp = MNULL;
3652 t_u32 cfp_no = 0;
3653
3654 ENTER();
3655 if (pioctl_req) {
3656 ds_misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3657 if (pioctl_req->action == MLAN_ACT_GET) {
3658 cfp = wlan_get_region_cfp_table(
3659 pmadapter, pmadapter->region_code,
3660 ds_misc_cfg->param.cfp.band, &cfp_no);
3661 if (cfp) {
3662 ds_misc_cfg->param.cfp.num_chan = cfp_no;
3663 memcpy_ext(pmadapter,
3664 ds_misc_cfg->param.cfp.cfp_tbl, cfp,
3665 cfp_no * sizeof(chan_freq_power_t),
3666 cfp_no * sizeof(chan_freq_power_t));
3667 }
3668 ret = MLAN_STATUS_SUCCESS;
3669 }
3670 }
3671 LEAVE();
3672 return ret;
3673 }
3674
3675 /**
3676 * @brief Get power tables and cfp tables for set region code
3677 * into the IOCTL request buffer
3678 *
3679 * @param pmadapter Private mlan adapter structure
3680 * @param pioctl_req Pointer to the IOCTL request structure
3681 *
3682 * @return success, otherwise fail
3683 *
3684 */
wlan_get_cfpinfo(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3685 mlan_status wlan_get_cfpinfo(pmlan_adapter pmadapter,
3686 pmlan_ioctl_req pioctl_req)
3687 {
3688 chan_freq_power_t *cfp_bg = MNULL;
3689 t_u32 cfp_no_bg = 0;
3690 chan_freq_power_t *cfp_a = MNULL;
3691 t_u32 cfp_no_a = 0;
3692 t_u8 cfp_code_a = pmadapter->region_code;
3693 t_u8 cfp_code_bg = pmadapter->region_code;
3694 t_u32 len = 0, size = 0;
3695 t_u8 *req_buf, *tmp;
3696 mlan_status ret = MLAN_STATUS_SUCCESS;
3697
3698 ENTER();
3699
3700 if (!pioctl_req || !pioctl_req->pbuf) {
3701 PRINTM(MERROR, "MLAN IOCTL information is not present!\n");
3702 ret = MLAN_STATUS_FAILURE;
3703 goto out;
3704 }
3705 /* Calculate the total response size required to return region,
3706 * country codes, cfp tables and power tables
3707 */
3708 size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
3709 /* Add size to store region, country and environment codes */
3710 size += sizeof(t_u32);
3711 if (pmadapter->cfp_code_bg)
3712 cfp_code_bg = pmadapter->cfp_code_bg;
3713
3714 /* Get cfp table and its size corresponding to the region code */
3715 cfp_bg = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
3716 BAND_G | BAND_B, &cfp_no_bg);
3717 size += cfp_no_bg * sizeof(chan_freq_power_t);
3718 if (pmadapter->cfp_code_a)
3719 cfp_code_a = pmadapter->cfp_code_a;
3720 cfp_a = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
3721 &cfp_no_a);
3722 size += cfp_no_a * sizeof(chan_freq_power_t);
3723 if (pmadapter->otp_region)
3724 size += sizeof(pmadapter->otp_region->environment);
3725
3726 /* Get power table size */
3727 if (pmadapter->tx_power_table_bg) {
3728 size += pmadapter->tx_power_table_bg_size;
3729 /* Add size to store table size, rows and cols */
3730 size += 3 * sizeof(t_u32);
3731 }
3732 if (pmadapter->tx_power_table_a) {
3733 size += pmadapter->tx_power_table_a_size;
3734 size += 3 * sizeof(t_u32);
3735 }
3736 /* Check information buffer length of MLAN IOCTL */
3737 if (pioctl_req->buf_len < size) {
3738 PRINTM(MWARN,
3739 "MLAN IOCTL information buffer length is too short.\n");
3740 pioctl_req->buf_len_needed = size;
3741 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3742 ret = MLAN_STATUS_RESOURCE;
3743 goto out;
3744 }
3745 /* Copy the total size of region code, country code and environment
3746 * in first four bytes of the IOCTL request buffer and then copy
3747 * codes respectively in following bytes
3748 */
3749 req_buf = (t_u8 *)pioctl_req->pbuf;
3750 size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
3751 if (pmadapter->otp_region)
3752 size += sizeof(pmadapter->otp_region->environment);
3753 tmp = (t_u8 *)&size;
3754 memcpy_ext(pmadapter, req_buf, tmp, sizeof(size), sizeof(size));
3755 len += sizeof(size);
3756 memcpy_ext(pmadapter, req_buf + len, &pmadapter->region_code,
3757 sizeof(pmadapter->region_code),
3758 sizeof(pmadapter->region_code));
3759 len += sizeof(pmadapter->region_code);
3760 memcpy_ext(pmadapter, req_buf + len, &pmadapter->country_code,
3761 sizeof(pmadapter->country_code),
3762 sizeof(pmadapter->country_code));
3763 len += sizeof(pmadapter->country_code);
3764 if (pmadapter->otp_region) {
3765 memcpy_ext(pmadapter, req_buf + len,
3766 &pmadapter->otp_region->environment,
3767 sizeof(pmadapter->otp_region->environment),
3768 sizeof(pmadapter->otp_region->environment));
3769 len += sizeof(pmadapter->otp_region->environment);
3770 }
3771 /* copy the cfp table size followed by the entire table */
3772 if (!cfp_bg)
3773 goto out;
3774 size = cfp_no_bg * sizeof(chan_freq_power_t);
3775 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3776 len += sizeof(size);
3777 memcpy_ext(pmadapter, req_buf + len, cfp_bg, size, size);
3778 len += size;
3779 if (!cfp_a)
3780 goto out;
3781 size = cfp_no_a * sizeof(chan_freq_power_t);
3782 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3783 len += sizeof(size);
3784 memcpy_ext(pmadapter, req_buf + len, cfp_a, size, size);
3785 len += size;
3786 /* Copy the size of the power table, number of rows, number of cols
3787 * and the entire power table
3788 */
3789 if (!pmadapter->tx_power_table_bg)
3790 goto out;
3791 size = pmadapter->tx_power_table_bg_size;
3792 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3793 len += sizeof(size);
3794
3795 /* No. of rows */
3796 size = pmadapter->tx_power_table_bg_rows;
3797 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3798 len += sizeof(size);
3799
3800 /* No. of cols */
3801 size = pmadapter->tx_power_table_bg_size /
3802 pmadapter->tx_power_table_bg_rows;
3803 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3804 len += sizeof(size);
3805 memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
3806 pmadapter->tx_power_table_bg_size,
3807 pmadapter->tx_power_table_bg_size);
3808 len += pmadapter->tx_power_table_bg_size;
3809 if (!pmadapter->tx_power_table_a)
3810 goto out;
3811 size = pmadapter->tx_power_table_a_size;
3812 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3813 len += sizeof(size);
3814
3815 /* No. of rows */
3816 size = pmadapter->tx_power_table_a_rows;
3817 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3818 len += sizeof(size);
3819
3820 /* No. of cols */
3821 size = pmadapter->tx_power_table_a_size /
3822 pmadapter->tx_power_table_a_rows;
3823 memcpy_ext(pmadapter, req_buf + len, tmp, sizeof(size), sizeof(size));
3824 len += sizeof(size);
3825 memcpy_ext(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
3826 pmadapter->tx_power_table_a_size,
3827 pmadapter->tx_power_table_a_size);
3828 len += pmadapter->tx_power_table_a_size;
3829 out:
3830 if (pioctl_req)
3831 pioctl_req->data_read_written = len;
3832
3833 LEAVE();
3834 return ret;
3835 }
3836