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