mirror of
https://github.com/nxp-imx/mwifiex.git
synced 2024-11-01 05:25:21 +00:00
3120 lines
92 KiB
C
3120 lines
92 KiB
C
|
/**
|
||
|
* @file mlan_cfp.c
|
||
|
*
|
||
|
* @brief This file contains WLAN client mode channel, frequency and power
|
||
|
* related code
|
||
|
*
|
||
|
* Copyright (C) 2009-2019, Marvell International Ltd.
|
||
|
*
|
||
|
* This software file (the "File") is distributed by Marvell International
|
||
|
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||
|
* (the "License"). You may use, redistribute and/or modify this File in
|
||
|
* accordance with the terms and conditions of the License, a copy of which
|
||
|
* is available by writing to the Free Software Foundation, Inc.,
|
||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||
|
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||
|
*
|
||
|
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||
|
* this warranty disclaimer.
|
||
|
*/
|
||
|
|
||
|
/*************************************************************
|
||
|
Change Log:
|
||
|
04/16/2009: initial version
|
||
|
************************************************************/
|
||
|
|
||
|
#include "mlan.h"
|
||
|
#include "mlan_util.h"
|
||
|
#include "mlan_fw.h"
|
||
|
#include "mlan_join.h"
|
||
|
#include "mlan_main.h"
|
||
|
|
||
|
/********************************************************
|
||
|
Local Variables
|
||
|
********************************************************/
|
||
|
|
||
|
/** 100mW */
|
||
|
#define WLAN_TX_PWR_DEFAULT 20
|
||
|
/** 100mW */
|
||
|
#define WLAN_TX_PWR_00_DEFAULT 20
|
||
|
/** 100mW */
|
||
|
#define WLAN_TX_PWR_US_DEFAULT 20
|
||
|
/** 100mW */
|
||
|
#define WLAN_TX_PWR_JP_BG_DEFAULT 20
|
||
|
/** 200mW */
|
||
|
#define WLAN_TX_PWR_JP_A_DEFAULT 23
|
||
|
/** 100mW */
|
||
|
#define WLAN_TX_PWR_FR_100MW 20
|
||
|
/** 10mW */
|
||
|
#define WLAN_TX_PWR_FR_10MW 10
|
||
|
/** 100mW */
|
||
|
#define WLAN_TX_PWR_EMEA_DEFAULT 20
|
||
|
/** 2000mW */
|
||
|
#define WLAN_TX_PWR_CN_2000MW 33
|
||
|
/** 200mW */
|
||
|
#define WLAN_TX_PWR_200MW 23
|
||
|
/** 1000mW */
|
||
|
#define WLAN_TX_PWR_1000MW 30
|
||
|
/** 30mW */
|
||
|
#define WLAN_TX_PWR_SP_30MW 14
|
||
|
/** 60mW */
|
||
|
#define WLAN_TX_PWR_SP_60MW 17
|
||
|
/** 25mW */
|
||
|
#define WLAN_TX_PWR_25MW 14
|
||
|
/** 250mW */
|
||
|
#define WLAN_TX_PWR_250MW 24
|
||
|
|
||
|
/** Region code mapping */
|
||
|
typedef struct _country_code_mapping {
|
||
|
/** Region */
|
||
|
t_u8 country_code[COUNTRY_CODE_LEN];
|
||
|
/** Code for B/G CFP table */
|
||
|
t_u8 cfp_code_bg;
|
||
|
/** Code for A CFP table */
|
||
|
t_u8 cfp_code_a;
|
||
|
} country_code_mapping_t;
|
||
|
|
||
|
#define EU_CFP_CODE_BG 0x30
|
||
|
#define EU_CFP_CODE_A 0x30
|
||
|
|
||
|
/** Region code mapping table */
|
||
|
static country_code_mapping_t country_code_mapping[] = {
|
||
|
{"US", 0x10, 0x10}, /* US FCC */
|
||
|
{"CA", 0x10, 0x20}, /* IC Canada */
|
||
|
{"SG", 0x10, 0x10}, /* Singapore */
|
||
|
{"EU", 0x30, 0x30}, /* ETSI */
|
||
|
{"AU", 0x30, 0x30}, /* Australia */
|
||
|
{"KR", 0x30, 0x30}, /* Republic Of Korea */
|
||
|
{"JP", 0xFF, 0x40}, /* Japan */
|
||
|
{"CN", 0x30, 0x50}, /* China */
|
||
|
{"BR", 0x01, 0x09}, /* Brazil */
|
||
|
{"RU", 0x30, 0x0f}, /* Russia */
|
||
|
{"IN", 0x10, 0x06}, /* India */
|
||
|
{"MY", 0x30, 0x06}, /* Malaysia */
|
||
|
};
|
||
|
|
||
|
/** Country code for ETSI */
|
||
|
static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
|
||
|
"AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY",
|
||
|
"CZ", "DK", "EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS",
|
||
|
"IE", "IT", "KR", "LV", "LI", "LT", "LU", "MT", "MD", "MC",
|
||
|
"ME", "NL", "NO", "PL", "RO", "RU", "SM", "RS", "SI", "SK",
|
||
|
"ES", "SE", "CH", "TR", "UA", "UK", "GB"
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The structure for Channel-Frequency-Power table
|
||
|
*/
|
||
|
typedef struct _cfp_table {
|
||
|
/** Region or Code */
|
||
|
t_u8 code;
|
||
|
/** Frequency/Power */
|
||
|
chan_freq_power_t *cfp;
|
||
|
/** No of CFP flag */
|
||
|
int cfp_no;
|
||
|
} cfp_table_t;
|
||
|
|
||
|
/* Format { Channel, Frequency (MHz), MaxTxPower } */
|
||
|
/** Band: 'B/G', Region: USA FCC/Canada IC */
|
||
|
static chan_freq_power_t channel_freq_power_US_BG[] = {
|
||
|
{1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'B/G', Region: Europe ETSI/China */
|
||
|
static chan_freq_power_t channel_freq_power_EU_BG[] = {
|
||
|
{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'B/G', Region: Japan */
|
||
|
static chan_freq_power_t channel_freq_power_JPN41_BG[] = {
|
||
|
{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'B/G', Region: Japan */
|
||
|
static chan_freq_power_t channel_freq_power_JPN40_BG[] = {
|
||
|
{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'B/G', Region: Japan */
|
||
|
static chan_freq_power_t channel_freq_power_JPNFE_BG[] = {
|
||
|
{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE},
|
||
|
{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}
|
||
|
};
|
||
|
|
||
|
/** Band : 'B/G', Region: Brazil */
|
||
|
static chan_freq_power_t channel_freq_power_BR_BG[] = {
|
||
|
{1, 2412, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{2, 2417, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{3, 2422, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{4, 2427, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{5, 2432, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{6, 2437, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{7, 2442, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{8, 2447, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{9, 2452, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{10, 2457, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{11, 2462, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{12, 2467, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{13, 2472, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
};
|
||
|
|
||
|
/** Band : 'B/G', Region: Special */
|
||
|
static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = {
|
||
|
{1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE},
|
||
|
{14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The 2.4GHz CFP tables
|
||
|
*/
|
||
|
static cfp_table_t cfp_table_BG[] = {
|
||
|
{
|
||
|
0x01, /* Brazil */
|
||
|
channel_freq_power_BR_BG,
|
||
|
NELEMENTS(channel_freq_power_BR_BG),
|
||
|
},
|
||
|
{0x10, /* US FCC */
|
||
|
channel_freq_power_US_BG,
|
||
|
NELEMENTS(channel_freq_power_US_BG),
|
||
|
},
|
||
|
{0x20, /* CANADA IC */
|
||
|
channel_freq_power_US_BG,
|
||
|
NELEMENTS(channel_freq_power_US_BG),
|
||
|
},
|
||
|
{0x30, /* EU */
|
||
|
channel_freq_power_EU_BG,
|
||
|
NELEMENTS(channel_freq_power_EU_BG),
|
||
|
},
|
||
|
{0x40, /* JAPAN */
|
||
|
channel_freq_power_JPN40_BG,
|
||
|
NELEMENTS(channel_freq_power_JPN40_BG),
|
||
|
},
|
||
|
{0x41, /* JAPAN */
|
||
|
channel_freq_power_JPN41_BG,
|
||
|
NELEMENTS(channel_freq_power_JPN41_BG),
|
||
|
},
|
||
|
{0x50, /* China */
|
||
|
channel_freq_power_EU_BG,
|
||
|
NELEMENTS(channel_freq_power_EU_BG),
|
||
|
},
|
||
|
{
|
||
|
0xfe, /* JAPAN */
|
||
|
channel_freq_power_JPNFE_BG,
|
||
|
NELEMENTS(channel_freq_power_JPNFE_BG),
|
||
|
},
|
||
|
{0xff, /* Special */
|
||
|
channel_freq_power_SPECIAL_BG,
|
||
|
NELEMENTS(channel_freq_power_SPECIAL_BG),
|
||
|
},
|
||
|
/* Add new region here */
|
||
|
};
|
||
|
|
||
|
/** Number of the CFP tables for 2.4GHz */
|
||
|
#define MLAN_CFP_TABLE_SIZE_BG (NELEMENTS(cfp_table_BG))
|
||
|
|
||
|
/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
|
||
|
/** Band: 'A', Region: World FCC */
|
||
|
|
||
|
/* Format { Channel, Frequency (MHz), MaxTxPower, DFS } */
|
||
|
/** Band: 'A', Region: USA FCC */
|
||
|
static chan_freq_power_t channel_freq_power_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{120, 5600, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{124, 5620, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{128, 5640, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Canada IC */
|
||
|
static chan_freq_power_t channel_freq_power_CAN_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{100, 5500, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{104, 5520, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{108, 5540, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{112, 5560, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{116, 5580, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{132, 5660, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{136, 5680, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{140, 5700, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{144, 5720, WLAN_TX_PWR_US_DEFAULT, MTRUE},
|
||
|
{149, 5745, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_US_DEFAULT, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_US_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Europe ETSI */
|
||
|
static chan_freq_power_t channel_freq_power_EU_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{100, 5500, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{104, 5520, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{108, 5540, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{112, 5560, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{116, 5580, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{120, 5600, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{124, 5620, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{128, 5640, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{132, 5660, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{136, 5680, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{140, 5700, WLAN_TX_PWR_EMEA_DEFAULT, MTRUE},
|
||
|
{149, 5745, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Japan */
|
||
|
static chan_freq_power_t channel_freq_power_JPN_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_JP_A_DEFAULT, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{100, 5500, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{104, 5520, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{108, 5540, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{112, 5560, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{116, 5580, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{120, 5600, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{124, 5620, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{128, 5640, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{132, 5660, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{136, 5680, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE},
|
||
|
{140, 5700, WLAN_TX_PWR_JP_A_DEFAULT, MTRUE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: China */
|
||
|
static chan_freq_power_t channel_freq_power_CN_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{149, 5745, WLAN_TX_PWR_CN_2000MW, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_CN_2000MW, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_CN_2000MW, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_CN_2000MW, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', NULL */
|
||
|
static chan_freq_power_t channel_freq_power_NULL_A[] = {
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Spain/Austria/Brazil */
|
||
|
static chan_freq_power_t channel_freq_power_SPN2_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_200MW, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_200MW, MTRUE},
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Brazil */
|
||
|
static chan_freq_power_t channel_freq_power_BR1_A[] = {
|
||
|
{100, 5500, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{104, 5520, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{108, 5540, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{112, 5560, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{116, 5580, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{120, 5600, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{124, 5620, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{128, 5640, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{132, 5660, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{136, 5680, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
{140, 5700, WLAN_TX_PWR_250MW, MTRUE},
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Brazil */
|
||
|
static chan_freq_power_t channel_freq_power_BR2_A[] = {
|
||
|
{149, 5745, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_1000MW, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_1000MW, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Region: Russia */
|
||
|
static chan_freq_power_t channel_freq_power_RU_A[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{132, 5660, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{136, 5680, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{140, 5700, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */
|
||
|
static chan_freq_power_t channel_freq_power_low_band[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */
|
||
|
static chan_freq_power_t channel_freq_power_lower_middle_band[] = {
|
||
|
{52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */
|
||
|
static chan_freq_power_t channel_freq_power_upper_middle_band[] = {
|
||
|
{100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
{140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE},
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */
|
||
|
static chan_freq_power_t channel_freq_power_high_band[] = {
|
||
|
{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and
|
||
|
* High band (5725-5850 MHz) channels */
|
||
|
static chan_freq_power_t channel_freq_power_low_high_band[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/** Band: 'A', Code: 6, Low band (5150-5250 MHz) and
|
||
|
* mid low (5260-5320) and High band (5725-5850 MHz) channels */
|
||
|
static chan_freq_power_t channel_freq_power_low_middle_high_band[] = {
|
||
|
{36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{52, 5260, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{56, 5280, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{60, 5300, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{64, 5320, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE},
|
||
|
{165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The 5GHz CFP tables
|
||
|
*/
|
||
|
static cfp_table_t cfp_table_A[] = {
|
||
|
{0x1, /* Low band (5150-5250 MHz) channels */
|
||
|
channel_freq_power_low_band,
|
||
|
NELEMENTS(channel_freq_power_low_band)
|
||
|
},
|
||
|
{0x2, /* Lower middle band (5250-5350 MHz) channels */
|
||
|
channel_freq_power_lower_middle_band,
|
||
|
NELEMENTS(channel_freq_power_lower_middle_band)
|
||
|
},
|
||
|
{0x3, /* Upper middle band (5470-5725 MHz) channels */
|
||
|
channel_freq_power_upper_middle_band,
|
||
|
NELEMENTS(channel_freq_power_upper_middle_band)
|
||
|
},
|
||
|
{0x4, /* High band (5725-5850 MHz) channels */
|
||
|
channel_freq_power_high_band,
|
||
|
NELEMENTS(channel_freq_power_high_band)
|
||
|
},
|
||
|
{0x5, /* Low band (5150-5250 MHz) and
|
||
|
High band (5725-5850 MHz) channels */
|
||
|
channel_freq_power_low_high_band,
|
||
|
NELEMENTS(channel_freq_power_low_high_band)
|
||
|
},
|
||
|
{0x6, /* Low band (5150-5250 MHz)
|
||
|
Mid band (5260-5320) and
|
||
|
High band (5725-5850 MHz) channels */
|
||
|
channel_freq_power_low_middle_high_band,
|
||
|
NELEMENTS(channel_freq_power_low_middle_high_band)
|
||
|
},
|
||
|
{0x09, /* SPAIN/Austria/Brazil */
|
||
|
channel_freq_power_SPN2_A,
|
||
|
NELEMENTS(channel_freq_power_SPN2_A),
|
||
|
},
|
||
|
{0x0c, /* Brazil */
|
||
|
channel_freq_power_BR1_A,
|
||
|
NELEMENTS(channel_freq_power_BR1_A),
|
||
|
},
|
||
|
{0x0e, /* Brazil */
|
||
|
channel_freq_power_BR2_A,
|
||
|
NELEMENTS(channel_freq_power_BR2_A),
|
||
|
},
|
||
|
{0x0f, /* Russia */
|
||
|
channel_freq_power_RU_A,
|
||
|
NELEMENTS(channel_freq_power_RU_A),
|
||
|
},
|
||
|
{0x10, /* US FCC */
|
||
|
channel_freq_power_A,
|
||
|
NELEMENTS(channel_freq_power_A),
|
||
|
},
|
||
|
{0x20, /* CANADA IC */
|
||
|
channel_freq_power_CAN_A,
|
||
|
NELEMENTS(channel_freq_power_CAN_A),
|
||
|
},
|
||
|
{0x30, /* EU */
|
||
|
channel_freq_power_EU_A,
|
||
|
NELEMENTS(channel_freq_power_EU_A),
|
||
|
},
|
||
|
{0x40, /* JAPAN */
|
||
|
channel_freq_power_JPN_A,
|
||
|
NELEMENTS(channel_freq_power_JPN_A),
|
||
|
},
|
||
|
{0x41, /* JAPAN */
|
||
|
channel_freq_power_JPN_A,
|
||
|
NELEMENTS(channel_freq_power_JPN_A),
|
||
|
},
|
||
|
{0x50, /* China */
|
||
|
channel_freq_power_CN_A,
|
||
|
NELEMENTS(channel_freq_power_CN_A),
|
||
|
},
|
||
|
{0xfe, /* JAPAN */
|
||
|
channel_freq_power_NULL_A,
|
||
|
NELEMENTS(channel_freq_power_NULL_A),
|
||
|
},
|
||
|
{0xff, /* Special */
|
||
|
channel_freq_power_JPN_A,
|
||
|
NELEMENTS(channel_freq_power_JPN_A),
|
||
|
},
|
||
|
/* Add new region here */
|
||
|
};
|
||
|
|
||
|
/** Number of the CFP tables for 5GHz */
|
||
|
#define MLAN_CFP_TABLE_SIZE_A (NELEMENTS(cfp_table_A))
|
||
|
|
||
|
enum {
|
||
|
RATEID_DBPSK1Mbps, //(0)
|
||
|
RATEID_DQPSK2Mbps, //(1)
|
||
|
RATEID_CCK5_5Mbps, //(2)
|
||
|
RATEID_CCK11Mbps, //(3)
|
||
|
RATEID_CCK22Mbps, //(4)
|
||
|
RATEID_OFDM6Mbps, //(5)
|
||
|
RATEID_OFDM9Mbps, //(6)
|
||
|
RATEID_OFDM12Mbps, //(7)
|
||
|
RATEID_OFDM18Mbps, //(8)
|
||
|
RATEID_OFDM24Mbps, //(9)
|
||
|
RATEID_OFDM36Mbps, //(10)
|
||
|
RATEID_OFDM48Mbps, //(11)
|
||
|
RATEID_OFDM54Mbps, //(12)
|
||
|
RATEID_OFDM72Mbps, //(13)
|
||
|
};
|
||
|
|
||
|
static const t_u8 rateUnit_500Kbps[] = {
|
||
|
(10 / 5), /* 1Mbps */
|
||
|
(20 / 5), /* 2Mbps */
|
||
|
|
||
|
(55 / 5), /* 5.5Mbps */
|
||
|
(110 / 5), /* 11Mbps */
|
||
|
(10 / 5), /* 22Mbps, intentionally set to 1Mbps because it's not available */
|
||
|
|
||
|
(60 / 5), /* 6Mbps */
|
||
|
(90 / 5), /* 9Mbps */
|
||
|
(120 / 5), /* 12Mbps */
|
||
|
(180 / 5), /* 18Mbps */
|
||
|
(240 / 5), /* 24Mbps */
|
||
|
(360 / 5), /* 36Mbps */
|
||
|
(480 / 5), /* 48Mbps */
|
||
|
(540 / 5), /* 54Mbps */
|
||
|
(60 / 5), /* 72Mbps intentionally set to 6Mbps because it's not available */
|
||
|
};
|
||
|
|
||
|
typedef struct _rate_map {
|
||
|
/** Rate, in 0.5Mbps */
|
||
|
t_u32 rate;
|
||
|
/** Mrvl rate id, refer to RATEID_XXX in FW */
|
||
|
t_u32 id;
|
||
|
/** nss: 0-nss1, 1-nss2 */
|
||
|
t_u8 nss;
|
||
|
} rate_map;
|
||
|
|
||
|
/** If user configure to 1x1 or we found peer device only support 1x1,
|
||
|
* then we need skip the nss1 part when map to Mrvl rate.
|
||
|
*/
|
||
|
const rate_map rate_map_table_2x2[] = {
|
||
|
/* LG <--> Mrvl rate idx */
|
||
|
{2, 0, 0}, //RATEID_DBPSK1Mbps
|
||
|
{4, 1, 0}, //RATEID_DQPSK2Mbps
|
||
|
{11, 2, 0}, //RATEID_CCK5_5Mbps
|
||
|
{22, 3, 0}, //RATEID_CCK11Mbps
|
||
|
{44, 4, 0}, //RATEID_CCK22Mbps
|
||
|
{12, 5, 0}, //RATEID_OFDM6Mbps
|
||
|
{18, 6, 0}, //RATEID_OFDM9Mbps
|
||
|
{24, 7, 0}, //RATEID_OFDM12Mbps
|
||
|
{36, 8, 0}, //RATEID_OFDM18Mbps
|
||
|
{48, 9, 0}, //RATEID_OFDM24Mbps
|
||
|
{72, 10, 0}, //RATEID_OFDM36Mbps
|
||
|
{96, 11, 0}, //RATEID_OFDM48Mbps
|
||
|
{108, 12, 0}, //RATEID_OFDM54Mbps
|
||
|
{144, 13, 0}, //RATEID_OFDM72Mbps
|
||
|
|
||
|
/* HT bw20 <--> Mrvl rate idx - nss2 */
|
||
|
{26, 22, 1}, //RATEID_MCS8_13Mbps
|
||
|
{52, 23, 1}, //RATEID_MCS9_26Mbps
|
||
|
{78, 24, 1}, //RATEID_MCS10_39Mbps
|
||
|
{104, 25, 1}, //RATEID_MCS11_52Mbps
|
||
|
{156, 26, 1}, //RATEID_MCS12_78Mbps
|
||
|
{208, 27, 1}, //RATEID_MCS13_104Mbps
|
||
|
{234, 28, 1}, //RATEID_MCS14_117Mbps
|
||
|
{260, 29, 1}, //RATEID_MCS15_130Mbps
|
||
|
/* HT bw20 <--> Mrvl rate idx - nss1 */
|
||
|
{13, 14, 0}, //RATEID_MCS0_6d5Mbps
|
||
|
{26, 15, 0}, //RATEID_MCS1_13Mbps
|
||
|
{39, 16, 0}, //RATEID_MCS2_19d5Mbps
|
||
|
{52, 17, 0}, //RATEID_MCS3_26Mbps
|
||
|
{78, 18, 0}, //RATEID_MCS4_39Mbps
|
||
|
{104, 19, 0}, //RATEID_MCS5_52Mbps
|
||
|
{117, 20, 0}, //RATEID_MCS6_58d5Mbps
|
||
|
{130, 21, 0}, //RATEID_MCS7_65Mbps
|
||
|
|
||
|
/* HT bw40<--> Mrvl rate idx - nss2 */
|
||
|
{54, 39, 1}, //RATEID_MCS8BW40_27Mbps
|
||
|
{108, 40, 1}, //RATEID_MCS9BW40_54Mbps
|
||
|
{162, 41, 1}, //RATEID_MCS10BW40_81Mbps
|
||
|
{216, 42, 1}, //RATEID_MCS11BW40_108Mbps
|
||
|
{324, 43, 1}, //RATEID_MCS12BW40_162Mbps
|
||
|
{432, 44, 1}, //RATEID_MCS13BW40_216Mbps
|
||
|
{486, 45, 1}, //RATEID_MCS14BW40_243Mbps
|
||
|
{540, 46, 1}, //RATEID_MCS15BW40_270Mbps
|
||
|
/* HT bw40<--> Mrvl rate idx - nss1 */
|
||
|
{12, 30, 0}, //RATEID_MCS32BW40_6Mbps
|
||
|
{27, 31, 0}, //RATEID_MCS0BW40_13d5Mbps
|
||
|
{54, 32, 0}, //RATEID_MCS1BW40_27Mbps
|
||
|
{81, 33, 0}, //RATEID_MCS2BW40_40d5Mbps
|
||
|
{108, 34, 0}, //RATEID_MCS3BW40_54Mbps
|
||
|
{162, 35, 0}, //RATEID_MCS4BW40_81Mbps
|
||
|
{216, 36, 0}, //RATEID_MCS5BW40_108Mbps
|
||
|
{243, 37, 0}, //RATEID_MCS6BW40_121d5Mbps
|
||
|
{270, 38, 0}, //RATEID_MCS7BW40_135Mbps
|
||
|
|
||
|
/* VHT bw20<--> Mrvl rate idx - nss2 */
|
||
|
{26, 57, 1}, //RATEID_VHT_MCS0_2SS_BW20 13 Mbps
|
||
|
{52, 58, 1}, //RATEID_VHT_MCS1_2SS_BW20 26 Mbps
|
||
|
{78, 59, 1}, //RATEID_VHT_MCS2_2SS_BW20 39 Mbps
|
||
|
{104, 60, 1}, //RATEID_VHT_MCS3_2SS_BW20 52 Mbps
|
||
|
{156, 61, 1}, //RATEID_VHT_MCS4_2SS_BW20 78 Mbps
|
||
|
{208, 62, 1}, //RATEID_VHT_MCS5_2SS_BW20 104 Mbps
|
||
|
{234, 63, 1}, //RATEID_VHT_MCS6_2SS_BW20 117 Mbps
|
||
|
{260, 64, 1}, //RATEID_VHT_MCS7_2SS_BW20 130 Mbps
|
||
|
{312, 65, 1}, //RATEID_VHT_MCS8_2SS_BW20 156 Mbps
|
||
|
{0, 66, 1}, //RATEID_VHT_MCS9_2SS_BW20 173.3 Mbps(INVALID)
|
||
|
/* VHT bw20<--> Mrvl rate idx - nss1 */
|
||
|
{13, 47, 0}, //RATEID_VHT_MCS0_1SS_BW20 6.5 Mbps
|
||
|
{26, 48, 0}, //RATEID_VHT_MCS1_1SS_BW20 13 Mbps
|
||
|
{39, 49, 0}, //RATEID_VHT_MCS2_1SS_BW20 19.5 Mbps
|
||
|
{52, 50, 0}, //RATEID_VHT_MCS3_1SS_BW20 26 Mbps
|
||
|
{78, 51, 0}, //RATEID_VHT_MCS4_1SS_BW20 39 Mbps
|
||
|
{104, 52, 0}, //RATEID_VHT_MCS5_1SS_BW20 52 Mbps
|
||
|
{117, 53, 0}, //RATEID_VHT_MCS6_1SS_BW20 58.5 Mbps
|
||
|
{130, 54, 0}, //RATEID_VHT_MCS7_1SS_BW20 65 Mbps
|
||
|
{156, 55, 0}, //RATEID_VHT_MCS8_1SS_BW20 78 Mbps
|
||
|
{0, 56, 0}, //RATEID_VHT_MCS9_1SS_BW20 86.7 Mbps(INVALID)
|
||
|
|
||
|
/* VHT bw40<--> Mrvl rate idx - nss2 */
|
||
|
{54, 77, 1}, //RATEID_VHT_MCS0_2SS_BW40 27 Mbps
|
||
|
{108, 78, 1}, //RATEID_VHT_MCS1_2SS_BW40 54 Mbps
|
||
|
{162, 79, 1}, //RATEID_VHT_MCS2_2SS_BW40 81 Mbps
|
||
|
{216, 80, 1}, //RATEID_VHT_MCS3_2SS_BW40 108 Mbps
|
||
|
{324, 81, 1}, //RATEID_VHT_MCS4_2SS_BW40 162 Mbps
|
||
|
{432, 82, 1}, //RATEID_VHT_MCS5_2SS_BW40 216 Mbps
|
||
|
{486, 83, 1}, //RATEID_VHT_MCS6_2SS_BW40 243 Mbps
|
||
|
{540, 84, 1}, //RATEID_VHT_MCS7_2SS_BW40 270 Mbps
|
||
|
{648, 85, 1}, //RATEID_VHT_MCS8_2SS_BW40 324 Mbps
|
||
|
{720, 86, 1}, //RATEID_VHT_MCS9_2SS_BW40 360 Mbps
|
||
|
/* VHT bw40<--> Mrvl rate idx - nss1 */
|
||
|
{27, 67, 0}, //RATEID_VHT_MCS0_1SS_BW40 13.5 Mbps
|
||
|
{54, 68, 0}, //RATEID_VHT_MCS1_1SS_BW40 27 Mbps
|
||
|
{81, 69, 0}, //RATEID_VHT_MCS2_1SS_BW40 40.5 Mbps
|
||
|
{108, 70, 0}, //RATEID_VHT_MCS3_1SS_BW40 54 Mbps
|
||
|
{162, 71, 0}, //RATEID_VHT_MCS4_1SS_BW40 81 Mbps
|
||
|
{216, 72, 0}, //RATEID_VHT_MCS5_1SS_BW40 108 Mbps
|
||
|
{243, 73, 0}, //RATEID_VHT_MCS6_1SS_BW40 121.5 Mbps
|
||
|
{270, 74, 0}, //RATEID_VHT_MCS7_1SS_BW40 135 Mbps
|
||
|
{324, 75, 0}, //RATEID_VHT_MCS8_1SS_BW40 162 Mbps
|
||
|
{360, 76, 0}, //RATEID_VHT_MCS9_1SS_BW40 180 Mbps
|
||
|
|
||
|
/* VHT bw80<--> Mrvl rate idx - nss2 */
|
||
|
{117, 97, 1}, //RATEID_VHT_MCS0_2SS_BW80 58.5 Mbps
|
||
|
{234, 98, 1}, //RATEID_VHT_MCS1_2SS_BW80 117 Mbps
|
||
|
{350, 99, 1}, //RATEID_VHT_MCS2_2SS_BW80 175 Mbps
|
||
|
{468, 100, 1}, //RATEID_VHT_MCS3_2SS_BW80 234 Mbps
|
||
|
{702, 101, 1}, //RATEID_VHT_MCS4_2SS_BW80 351 Mbps
|
||
|
{936, 102, 1}, //RATEID_VHT_MCS5_2SS_BW80 468 Mbps
|
||
|
{1053, 103, 1}, //RATEID_VHT_MCS6_2SS_BW80 526.5 Mbps
|
||
|
{1170, 104, 1}, //RATEID_VHT_MCS7_2SS_BW80 585 Mbps
|
||
|
{1404, 105, 1}, //RATEID_VHT_MCS8_2SS_BW80 702 Mbps
|
||
|
{1560, 106, 1}, //RATEID_VHT_MCS9_2SS_BW80 780 Mbps
|
||
|
/* VHT bw80<--> Mrvl rate idx - nss1 */
|
||
|
{58, 87, 0}, //RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could correspond to 58
|
||
|
{59, 87, 0}, //RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3*2 could correspond to 59 too
|
||
|
{117, 88, 0}, //RATEID_VHT_MCS1_1SS_BW80 58.5 Mbps
|
||
|
{175, 89, 0}, //RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could correspond to 175
|
||
|
{176, 89, 0}, //RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could correspond to 176 too
|
||
|
{234, 90, 0}, //RATEID_VHT_MCS3_1SS_BW80 117 Mbps
|
||
|
{351, 91, 0}, //RATEID_VHT_MCS4_1SS_BW80 175.5 Mbps
|
||
|
{468, 92, 0}, //RATEID_VHT_MCS5_1SS_BW80 234 Mbps
|
||
|
{526, 93, 0}, //RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could correspond to 526
|
||
|
{527, 93, 0}, //RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could correspond to 527 too
|
||
|
{585, 94, 0}, //RATEID_VHT_MCS7_1SS_BW80 292.5 Mbps
|
||
|
{702, 95, 0}, //RATEID_VHT_MCS8_1SS_BW80 351 Mbps
|
||
|
{780, 96, 0}, //RATEID_VHT_MCS9_1SS_BW80 390 Mbps
|
||
|
};
|
||
|
|
||
|
/** rate_map_table_1x1 is based on rate_map_table_2x2 and remove nss2 part.
|
||
|
* For the chip who only support 1x1, Mrvl rate idx define is different with 2x2 in FW
|
||
|
* We need redefine a bitrate to Mrvl rate idx table for 1x1 chip.
|
||
|
*/
|
||
|
const rate_map rate_map_table_1x1[] = {
|
||
|
/* LG <--> Mrvl rate idx */
|
||
|
{2, 0, 0}, //RATEID_DBPSK1Mbps
|
||
|
{4, 1, 0}, //RATEID_DQPSK2Mbps
|
||
|
{11, 2, 0}, //RATEID_CCK5_5Mbps
|
||
|
{22, 3, 0}, //RATEID_CCK11Mbps
|
||
|
{44, 4, 0}, //RATEID_CCK22Mbps
|
||
|
{12, 5, 0}, //RATEID_OFDM6Mbps
|
||
|
{18, 6, 0}, //RATEID_OFDM9Mbps
|
||
|
{24, 7, 0}, //RATEID_OFDM12Mbps
|
||
|
{36, 8, 0}, //RATEID_OFDM18Mbps
|
||
|
{48, 9, 0}, //RATEID_OFDM24Mbps
|
||
|
{72, 10, 0}, //RATEID_OFDM36Mbps
|
||
|
{96, 11, 0}, //RATEID_OFDM48Mbps
|
||
|
{108, 12, 0}, //RATEID_OFDM54Mbps
|
||
|
{144, 13, 0}, //RATEID_OFDM72Mbps
|
||
|
|
||
|
/* HT bw20 <--> Mrvl rate idx */
|
||
|
{13, 14, 0}, //RATEID_MCS0_6d5Mbps
|
||
|
{26, 15, 0}, //RATEID_MCS1_13Mbps
|
||
|
{39, 16, 0}, //RATEID_MCS2_19d5Mbps
|
||
|
{52, 17, 0}, //RATEID_MCS3_26Mbps
|
||
|
{78, 18, 0}, //RATEID_MCS4_39Mbps
|
||
|
{104, 19, 0}, //RATEID_MCS5_52Mbps
|
||
|
{117, 20, 0}, //RATEID_MCS6_58d5Mbps
|
||
|
{130, 21, 0}, //RATEID_MCS7_65Mbps
|
||
|
|
||
|
/* HT bw40<--> Mrvl rate idx */
|
||
|
{12, 22, 0}, //RATEID_MCS32BW40_6Mbps, for 1x1 start from 22
|
||
|
{27, 23, 0}, //RATEID_MCS0BW40_13d5Mbps
|
||
|
{54, 24, 0}, //RATEID_MCS1BW40_27Mbps
|
||
|
{81, 25, 0}, //RATEID_MCS2BW40_40d5Mbps
|
||
|
{108, 26, 0}, //RATEID_MCS3BW40_54Mbps
|
||
|
{162, 27, 0}, //RATEID_MCS4BW40_81Mbps
|
||
|
{216, 28, 0}, //RATEID_MCS5BW40_108Mbps
|
||
|
{243, 29, 0}, //RATEID_MCS6BW40_121d5Mbps
|
||
|
{270, 30, 0}, //RATEID_MCS7BW40_135Mbps
|
||
|
|
||
|
/* VHT bw20<--> Mrvl rate idx */
|
||
|
{13, 31, 0}, //RATEID_VHT_MCS0_1SS_BW20 6.5 Mbps
|
||
|
{26, 32, 0}, //RATEID_VHT_MCS1_1SS_BW20 13 Mbps
|
||
|
{39, 33, 0}, //RATEID_VHT_MCS2_1SS_BW20 19.5 Mbps
|
||
|
{52, 34, 0}, //RATEID_VHT_MCS3_1SS_BW20 26 Mbps
|
||
|
{78, 35, 0}, //RATEID_VHT_MCS4_1SS_BW20 39 Mbps
|
||
|
{104, 36, 0}, //RATEID_VHT_MCS5_1SS_BW20 52 Mbps
|
||
|
{117, 37, 0}, //RATEID_VHT_MCS6_1SS_BW20 58.5 Mbps
|
||
|
{130, 38, 0}, //RATEID_VHT_MCS7_1SS_BW20 65 Mbps
|
||
|
{156, 39, 0}, //RATEID_VHT_MCS8_1SS_BW20 78 Mbps
|
||
|
{0, 40, 0}, //RATEID_VHT_MCS9_1SS_BW20 86.7 Mbps(INVALID)
|
||
|
|
||
|
/* VHT bw40<--> Mrvl rate idx */
|
||
|
{27, 41, 0}, //RATEID_VHT_MCS0_1SS_BW40 13.5 Mbps
|
||
|
{54, 42, 0}, //RATEID_VHT_MCS1_1SS_BW40 27 Mbps
|
||
|
{81, 43, 0}, //RATEID_VHT_MCS2_1SS_BW40 40.5 Mbps
|
||
|
{108, 44, 0}, //RATEID_VHT_MCS3_1SS_BW40 54 Mbps
|
||
|
{162, 45, 0}, //RATEID_VHT_MCS4_1SS_BW40 81 Mbps
|
||
|
{216, 46, 0}, //RATEID_VHT_MCS5_1SS_BW40 108 Mbps
|
||
|
{243, 47, 0}, //RATEID_VHT_MCS6_1SS_BW40 121.5 Mbps
|
||
|
{270, 48, 0}, //RATEID_VHT_MCS7_1SS_BW40 135 Mbps
|
||
|
{324, 49, 0}, //RATEID_VHT_MCS8_1SS_BW40 162 Mbps
|
||
|
{360, 50, 0}, //RATEID_VHT_MCS9_1SS_BW40 180 Mbps
|
||
|
|
||
|
/* VHT bw80<--> Mrvl rate idx */
|
||
|
{58, 51, 0}, //RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could correspond to 58
|
||
|
{59, 51, 0}, //RATEID_VHT_MCS0_1SS_BW80 29.3 Mbps, 29.3x2 could correspond to 59 too
|
||
|
{117, 52, 0}, //RATEID_VHT_MCS1_1SS_BW80 58.5 Mbps
|
||
|
{175, 53, 0}, //RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could correspond to 175
|
||
|
{176, 53, 0}, //RATEID_VHT_MCS2_1SS_BW80 87.8 Mbps, 87.8x2 could correspond to 176 too
|
||
|
{234, 54, 0}, //RATEID_VHT_MCS3_1SS_BW80 117 Mbps
|
||
|
{351, 55, 0}, //RATEID_VHT_MCS4_1SS_BW80 175.5 Mbps
|
||
|
{468, 56, 0}, //RATEID_VHT_MCS5_1SS_BW80 234 Mbps
|
||
|
{526, 57, 0}, //RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could correspond to 526
|
||
|
{527, 57, 0}, //RATEID_VHT_MCS6_1SS_BW80 263.3 Mbps, 263.3x2 could correspond to 527 too
|
||
|
{585, 58, 0}, //RATEID_VHT_MCS7_1SS_BW80 292.5 Mbps
|
||
|
{702, 59, 0}, //RATEID_VHT_MCS8_1SS_BW80 351 Mbps
|
||
|
{780, 60, 0}, //RATEID_VHT_MCS9_1SS_BW80 390 Mbps
|
||
|
};
|
||
|
|
||
|
/********************************************************
|
||
|
Global Variables
|
||
|
********************************************************/
|
||
|
/**
|
||
|
* The table to keep region code
|
||
|
*/
|
||
|
t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = {
|
||
|
0x10, 0x20, 0x30, 0x40, 0x41, 0x50, 0xfe, 0xff
|
||
|
};
|
||
|
|
||
|
/** The table to keep CFP code for BG */
|
||
|
t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { };
|
||
|
|
||
|
/** The table to keep CFP code for A */
|
||
|
t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
|
||
|
|
||
|
/**
|
||
|
* The rates supported for ad-hoc B mode
|
||
|
*/
|
||
|
t_u8 AdhocRates_B[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
|
||
|
|
||
|
/**
|
||
|
* The rates supported for ad-hoc G mode
|
||
|
*/
|
||
|
t_u8 AdhocRates_G[G_SUPPORTED_RATES] = {
|
||
|
0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported for ad-hoc BG mode
|
||
|
*/
|
||
|
t_u8 AdhocRates_BG[BG_SUPPORTED_RATES] = {
|
||
|
0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
|
||
|
0x60, 0x6c, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported in A mode for ad-hoc
|
||
|
*/
|
||
|
t_u8 AdhocRates_A[A_SUPPORTED_RATES] = {
|
||
|
0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported in A mode (used for BAND_A)
|
||
|
*/
|
||
|
t_u8 SupportedRates_A[A_SUPPORTED_RATES] = {
|
||
|
0x0c, 0x12, 0x18, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported by the card
|
||
|
*/
|
||
|
t_u16 WlanDataRates[WLAN_SUPPORTED_RATES_EXT] = {
|
||
|
0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
|
||
|
0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
|
||
|
0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75,
|
||
|
0x82, 0x0C, 0x1B, 0x36, 0x51, 0x6C, 0xA2,
|
||
|
0xD8, 0xF3, 0x10E, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported in B mode
|
||
|
*/
|
||
|
t_u8 SupportedRates_B[B_SUPPORTED_RATES] = {
|
||
|
0x02, 0x04, 0x0b, 0x16, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported in G mode (BAND_G, BAND_G|BAND_GN)
|
||
|
*/
|
||
|
t_u8 SupportedRates_G[G_SUPPORTED_RATES] = {
|
||
|
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported in BG mode (BAND_B|BAND_G, BAND_B|BAND_G|BAND_GN)
|
||
|
*/
|
||
|
t_u8 SupportedRates_BG[BG_SUPPORTED_RATES] = {
|
||
|
0x02, 0x04, 0x0b, 0x0c, 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
|
||
|
0x60, 0x6c, 0x00
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The rates supported in N mode
|
||
|
*/
|
||
|
t_u8 SupportedRates_N[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
|
||
|
|
||
|
/********************************************************
|
||
|
Local Functions
|
||
|
********************************************************/
|
||
|
/**
|
||
|
* @brief Find a character in a string.
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param s A pointer to string
|
||
|
* @param c Character to be located
|
||
|
* @param n The length of string
|
||
|
*
|
||
|
* @return A pointer to the first occurrence of c in string, or MNULL if c is not found.
|
||
|
*/
|
||
|
static void *
|
||
|
wlan_memchr(pmlan_adapter pmadapter, void *s, int c, int n)
|
||
|
{
|
||
|
const t_u8 *p = (t_u8 *)s;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
while (n--) {
|
||
|
if ((t_u8)c == *p++) {
|
||
|
LEAVE();
|
||
|
return (void *)(p - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return MNULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief This function finds the CFP in
|
||
|
* cfp_table_BG/A based on region/code and band parameter.
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param region The region code
|
||
|
* @param band The band
|
||
|
* @param cfp_no A pointer to CFP number
|
||
|
*
|
||
|
* @return A pointer to CFP
|
||
|
*/
|
||
|
static chan_freq_power_t *
|
||
|
wlan_get_region_cfp_table(pmlan_adapter pmadapter, t_u8 region, t_u8 band,
|
||
|
int *cfp_no)
|
||
|
{
|
||
|
t_u32 i;
|
||
|
t_u8 cfp_bg, cfp_a;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
cfp_bg = cfp_a = region;
|
||
|
if (!region) {
|
||
|
/* Invalid region code, use CFP code */
|
||
|
cfp_bg = pmadapter->cfp_code_bg;
|
||
|
cfp_a = pmadapter->cfp_code_a;
|
||
|
}
|
||
|
if (band & (BAND_B | BAND_G | BAND_GN | BAND_GAC)) {
|
||
|
/* Return the FW cfp table for requested region code, if available.
|
||
|
* If region is not forced and the requested region code is different,
|
||
|
* simply return the corresponding pre-defined table.
|
||
|
*/
|
||
|
if (pmadapter->otp_region && pmadapter->cfp_otp_bg) {
|
||
|
if (pmadapter->otp_region->force_reg ||
|
||
|
(cfp_bg ==
|
||
|
(t_u8)pmadapter->otp_region->region_code)) {
|
||
|
*cfp_no = pmadapter->tx_power_table_bg_rows;
|
||
|
LEAVE();
|
||
|
return pmadapter->cfp_otp_bg;
|
||
|
}
|
||
|
}
|
||
|
for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
|
||
|
PRINTM(MINFO, "cfp_table_BG[%d].code=%d\n", i,
|
||
|
cfp_table_BG[i].code);
|
||
|
/* Check if region/code matches for BG bands */
|
||
|
if (cfp_table_BG[i].code == cfp_bg) {
|
||
|
/* Select by band */
|
||
|
*cfp_no = cfp_table_BG[i].cfp_no;
|
||
|
LEAVE();
|
||
|
return cfp_table_BG[i].cfp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (band & (BAND_A | BAND_AN | BAND_AAC)) {
|
||
|
/* Return the FW cfp table for requested region code */
|
||
|
if (pmadapter->otp_region && pmadapter->cfp_otp_a) {
|
||
|
if (pmadapter->otp_region->force_reg ||
|
||
|
(cfp_a ==
|
||
|
(t_u8)pmadapter->otp_region->region_code)) {
|
||
|
*cfp_no = pmadapter->tx_power_table_a_rows;
|
||
|
LEAVE();
|
||
|
return pmadapter->cfp_otp_a;
|
||
|
}
|
||
|
}
|
||
|
for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
|
||
|
PRINTM(MINFO, "cfp_table_A[%d].code=%d\n", i,
|
||
|
cfp_table_A[i].code);
|
||
|
/* Check if region/code matches for A bands */
|
||
|
if (cfp_table_A[i].code == cfp_a) {
|
||
|
/* Select by band */
|
||
|
*cfp_no = cfp_table_A[i].cfp_no;
|
||
|
LEAVE();
|
||
|
return cfp_table_A[i].cfp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!region)
|
||
|
PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n",
|
||
|
band, cfp_bg, cfp_a);
|
||
|
else
|
||
|
PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band,
|
||
|
region);
|
||
|
|
||
|
LEAVE();
|
||
|
return MNULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief This function copies dynamic CFP elements from one table to another.
|
||
|
* Only copy elements where channel numbers match.
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param cfp Destination table
|
||
|
* @param num_cfp Number of elements in dest table
|
||
|
* @param cfp_src Source table
|
||
|
* @param num_cfp_src Number of elements in source table
|
||
|
*/
|
||
|
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)
|
||
|
{
|
||
|
int i, j;
|
||
|
ENTER();
|
||
|
|
||
|
/* first clear dest dynamic blacklisted entries */
|
||
|
for (i = 0; i < num_cfp; i++)
|
||
|
cfp[i].dynamic.blacklist = MFALSE;
|
||
|
|
||
|
/* copy dynamic blacklisted entries from source where channels match */
|
||
|
if (cfp_src) {
|
||
|
for (i = 0; i < num_cfp; i++)
|
||
|
for (j = 0; j < num_cfp_src; j++)
|
||
|
if (cfp[i].channel == cfp_src[j].channel) {
|
||
|
cfp[i].dynamic.blacklist =
|
||
|
cfp_src[j].dynamic.blacklist;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
}
|
||
|
|
||
|
/********************************************************
|
||
|
Global Functions
|
||
|
********************************************************/
|
||
|
/**
|
||
|
* @brief This function converts region string to integer code
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param country_code Country string
|
||
|
* @param cfp_bg Pointer to buffer
|
||
|
* @param cfp_a Pointer to buffer
|
||
|
*
|
||
|
* @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
|
||
|
*/
|
||
|
mlan_status
|
||
|
wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter, t_u8 *country_code,
|
||
|
t_u8 *cfp_bg, t_u8 *cfp_a)
|
||
|
{
|
||
|
t_u8 i;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/* Look for code in mapping table */
|
||
|
for (i = 0; i < NELEMENTS(country_code_mapping); i++) {
|
||
|
if (!memcmp(pmadapter, country_code_mapping[i].country_code,
|
||
|
country_code, COUNTRY_CODE_LEN - 1)) {
|
||
|
*cfp_bg = country_code_mapping[i].cfp_code_bg;
|
||
|
*cfp_a = country_code_mapping[i].cfp_code_a;
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* If still not found, look for code in EU country code table */
|
||
|
for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
|
||
|
if (!memcmp(pmadapter, eu_country_code_table[i],
|
||
|
country_code, COUNTRY_CODE_LEN - 1)) {
|
||
|
*cfp_bg = EU_CFP_CODE_BG;
|
||
|
*cfp_a = EU_CFP_CODE_A;
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief This function finds if given country code is in EU table
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param country_code Country string
|
||
|
*
|
||
|
* @return MTRUE or MFALSE
|
||
|
*/
|
||
|
t_bool
|
||
|
wlan_is_etsi_country(pmlan_adapter pmadapter, t_u8 *country_code)
|
||
|
{
|
||
|
|
||
|
t_u8 i;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/* Look for code in EU country code table */
|
||
|
for (i = 0; i < NELEMENTS(eu_country_code_table); i++) {
|
||
|
if (!memcmp(pmadapter, eu_country_code_table[i],
|
||
|
country_code, COUNTRY_CODE_LEN - 1)) {
|
||
|
LEAVE();
|
||
|
return MTRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return MFALSE;
|
||
|
}
|
||
|
|
||
|
#define BAND_MASK_5G 0x03
|
||
|
#define ANTENNA_OFFSET 2
|
||
|
/**
|
||
|
* @brief This function adjust the antenna index
|
||
|
*
|
||
|
* V16_FW_API: Bit0: ant A, Bit 1:ant B, Bit0 & Bit 1: A+B
|
||
|
* 8887: case1: 0 - 2.4G ant A, 1- 2.4G antB, 2-- 5G ant C
|
||
|
* case2: 0 - 2.4G ant A, 1- 2.4G antB, 0x80- 5G antA, 0x81-5G ant B
|
||
|
* @param priv A pointer to mlan_private structure
|
||
|
* @param prx_pd A pointer to the RxPD structure
|
||
|
*
|
||
|
* @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_adjust_antenna(pmlan_private priv, RxPD *prx_pd)
|
||
|
{
|
||
|
t_u8 antenna = prx_pd->antenna;
|
||
|
if (prx_pd->antenna == 0xff)
|
||
|
return 0;
|
||
|
if ((antenna & MBIT(0)) && (antenna & MBIT(1)))
|
||
|
antenna = 2;
|
||
|
else if (antenna & MBIT(1))
|
||
|
antenna = 1;
|
||
|
else if (antenna & MBIT(0))
|
||
|
antenna = 0;
|
||
|
|
||
|
return antenna;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief This function adjust the rate index
|
||
|
*
|
||
|
* @param priv A pointer to mlan_private structure
|
||
|
* @param rx_rate rx rate
|
||
|
* @param rate_info rate info
|
||
|
* @return rate index
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_adjust_data_rate(mlan_private *priv, t_u8 rx_rate, t_u8 rate_info)
|
||
|
{
|
||
|
t_u8 rate_index = 0;
|
||
|
t_u8 bw = 0;
|
||
|
t_u8 nss = 0;
|
||
|
t_bool sgi_enable = 0;
|
||
|
|
||
|
#define MAX_MCS_NUM_SUPP 16
|
||
|
|
||
|
#define MAX_MCS_NUM_AC 10
|
||
|
#define RATE_INDEX_MCS0 12
|
||
|
bw = (rate_info & 0xC) >> 2;
|
||
|
sgi_enable = (rate_info & 0x10) >> 4;
|
||
|
if ((rate_info & 0x3) == 0) {
|
||
|
rate_index =
|
||
|
(rx_rate >
|
||
|
MLAN_RATE_INDEX_OFDM0) ? rx_rate - 1 : rx_rate;
|
||
|
} else if ((rate_info & 0x03) == 1) {
|
||
|
rate_index = RATE_INDEX_MCS0 +
|
||
|
MAX_MCS_NUM_SUPP * 2 * sgi_enable +
|
||
|
MAX_MCS_NUM_SUPP * bw + rx_rate;
|
||
|
} else if ((rate_info & 0x3) == 2) {
|
||
|
nss = rx_rate >> 4; //0:NSS1, 1:NSS2
|
||
|
rate_index = RATE_INDEX_MCS0 + MAX_MCS_NUM_SUPP * 4 +
|
||
|
MAX_MCS_NUM_AC * 6 * sgi_enable +
|
||
|
MAX_MCS_NUM_AC * 2 * bw + MAX_MCS_NUM_AC * nss +
|
||
|
(rx_rate & 0x0f);
|
||
|
}
|
||
|
return rate_index;
|
||
|
}
|
||
|
|
||
|
#ifdef STA_SUPPORT
|
||
|
#endif /* STA_SUPPORT */
|
||
|
|
||
|
/**
|
||
|
* @brief convert ht_info to rate_info
|
||
|
*
|
||
|
* @param ht_info ht info
|
||
|
*
|
||
|
* @return rate info
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_convert_v14_rate_ht_info(t_u8 ht_info)
|
||
|
{
|
||
|
t_u8 rate_info = 0;
|
||
|
rate_info = ht_info & 0x01;
|
||
|
/* band */
|
||
|
rate_info |= (ht_info & MBIT(1)) << 1;
|
||
|
/* short GI */
|
||
|
rate_info |= (ht_info & MBIT(2)) << 2;
|
||
|
return rate_info;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Use index to get the data rate
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param index The index of data rate
|
||
|
* @param tx_rate_info Tx rate info
|
||
|
*
|
||
|
* @return Data rate or 0
|
||
|
*/
|
||
|
t_u32
|
||
|
wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 tx_rate_info)
|
||
|
{
|
||
|
#define MCS_NUM_SUPP 16
|
||
|
t_u16 mcs_rate[4][MCS_NUM_SUPP] = {
|
||
|
{0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c}, /*LG 40M */
|
||
|
{0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258}, /*SG 40M */
|
||
|
{0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104}, /*LG 20M */
|
||
|
{0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39,
|
||
|
0x56, 0x73, 0xad, 0xe7, 0x104, 0x120}
|
||
|
}; /*SG 20M */
|
||
|
|
||
|
#define MCS_NUM_AC 10
|
||
|
/* NSS 1. note: the value in the table is 2 multiplier of the actual rate
|
||
|
* in other words, it is in the unit of 500 Kbs
|
||
|
*/
|
||
|
t_u16 ac_mcs_rate_nss1[8][MCS_NUM_AC] = {
|
||
|
{0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C, 0x618}, /* LG 160M */
|
||
|
{0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618, 0x6C6}, /* SG 160M */
|
||
|
{0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 0x249, 0x2BE, 0x30C}, /* LG 80M */
|
||
|
{0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 0x28A, 0x30C, 0x363}, /* SG 80M */
|
||
|
{0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x144, 0x168}, /* LG 40M */
|
||
|
{0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 0x12C, 0x168, 0x190}, /* SG 40M */
|
||
|
{0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00}, /* LG 20M */
|
||
|
{0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00}, /* SG 20M */
|
||
|
};
|
||
|
/* NSS 2. note: the value in the table is 2 multiplier of the actual rate */
|
||
|
t_u16 ac_mcs_rate_nss2[8][MCS_NUM_AC] = {
|
||
|
{0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 0x924, 0xAF8, 0xC30}, /*LG 160M */
|
||
|
{0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 0xA28, 0xC30, 0xD8B}, /*SG 160M */
|
||
|
|
||
|
{0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 0x492, 0x57C, 0x618}, /*LG 80M */
|
||
|
{0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 0x514, 0x618, 0x6C6}, /*SG 80M */
|
||
|
{0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 0x21C, 0x288, 0x2D0}, /*LG 40M */
|
||
|
{0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 0x258, 0x2D0, 0x320}, /*SG 40M */
|
||
|
{0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 0x138, 0x00}, /*LG 20M */
|
||
|
{0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 0x15B, 0x00}, /*SG 20M */
|
||
|
};
|
||
|
|
||
|
t_u32 rate = 0;
|
||
|
t_u8 mcs_index = 0;
|
||
|
t_u8 bw = 0;
|
||
|
t_u8 gi = 0;
|
||
|
ENTER();
|
||
|
|
||
|
if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_VHT) {
|
||
|
/* VHT rate */
|
||
|
mcs_index = index & 0xF;
|
||
|
|
||
|
if (mcs_index > 9)
|
||
|
mcs_index = 9;
|
||
|
|
||
|
/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
|
||
|
bw = (tx_rate_info & 0xC) >> 2;
|
||
|
/* LGI: gi =0, SGI: gi = 1 */
|
||
|
gi = (tx_rate_info & 0x10) >> 4;
|
||
|
if ((index >> 4) == 1) {
|
||
|
/* NSS = 2 */
|
||
|
rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
|
||
|
} else
|
||
|
/* NSS = 1 */
|
||
|
rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
|
||
|
} else if ((tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
|
||
|
/* HT rate */
|
||
|
/* 20M: bw=0, 40M: bw=1 */
|
||
|
bw = (tx_rate_info & 0xC) >> 2;
|
||
|
/* LGI: gi =0, SGI: gi = 1 */
|
||
|
gi = (tx_rate_info & 0x10) >> 4;
|
||
|
if (index == MLAN_RATE_BITMAP_MCS0) {
|
||
|
if (gi == 1)
|
||
|
rate = 0x0D; /* MCS 32 SGI rate */
|
||
|
else
|
||
|
rate = 0x0C; /* MCS 32 LGI rate */
|
||
|
} else if (index < MCS_NUM_SUPP) {
|
||
|
if (bw <= 1)
|
||
|
rate = mcs_rate[2 * (1 - bw) + gi][index];
|
||
|
else
|
||
|
rate = WlanDataRates[0];
|
||
|
} else
|
||
|
rate = WlanDataRates[0];
|
||
|
} else {
|
||
|
/* 11n non HT rates */
|
||
|
if (index >= WLAN_SUPPORTED_RATES_EXT)
|
||
|
index = 0;
|
||
|
rate = WlanDataRates[index];
|
||
|
}
|
||
|
LEAVE();
|
||
|
return rate;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Use rate to get the index
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param rate Data rate
|
||
|
*
|
||
|
* @return Index or 0
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_data_rate_to_index(pmlan_adapter pmadapter, t_u32 rate)
|
||
|
{
|
||
|
t_u16 *ptr;
|
||
|
|
||
|
ENTER();
|
||
|
if (rate) {
|
||
|
ptr = wlan_memchr(pmadapter, WlanDataRates, (t_u8)rate,
|
||
|
sizeof(WlanDataRates));
|
||
|
if (ptr) {
|
||
|
LEAVE();
|
||
|
return (t_u8)(ptr - WlanDataRates);
|
||
|
}
|
||
|
}
|
||
|
LEAVE();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get active data rates
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param bss_mode The specified BSS mode (Infra/IBSS)
|
||
|
* @param config_bands The specified band configuration
|
||
|
* @param rates The buf to return the active rates
|
||
|
*
|
||
|
* @return The number of Rates
|
||
|
*/
|
||
|
t_u32
|
||
|
wlan_get_active_data_rates(mlan_private *pmpriv, t_u32 bss_mode,
|
||
|
t_u8 config_bands, WLAN_802_11_RATES rates)
|
||
|
{
|
||
|
t_u32 k;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
if (pmpriv->media_connected != MTRUE) {
|
||
|
k = wlan_get_supported_rates(pmpriv, bss_mode, config_bands,
|
||
|
rates);
|
||
|
} else {
|
||
|
k = wlan_copy_rates(rates, 0,
|
||
|
pmpriv->curr_bss_params.data_rates,
|
||
|
pmpriv->curr_bss_params.num_of_rates);
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return k;
|
||
|
}
|
||
|
|
||
|
#ifdef STA_SUPPORT
|
||
|
/**
|
||
|
* @brief This function search through all the regions cfp table to find the channel,
|
||
|
* if the channel is found then gets the MIN txpower of the channel
|
||
|
* present in all the regions.
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param channel Channel number.
|
||
|
*
|
||
|
* @return The Tx power
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_get_txpwr_of_chan_from_cfp(mlan_private *pmpriv, t_u8 channel)
|
||
|
{
|
||
|
t_u8 i = 0;
|
||
|
t_u8 j = 0;
|
||
|
t_u8 tx_power = 0;
|
||
|
t_u32 cfp_no;
|
||
|
chan_freq_power_t *cfp = MNULL;
|
||
|
chan_freq_power_t *cfp_a = MNULL;
|
||
|
t_u32 cfp_no_a;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
|
||
|
/* Get CFP */
|
||
|
cfp = cfp_table_BG[i].cfp;
|
||
|
cfp_no = cfp_table_BG[i].cfp_no;
|
||
|
/* Find matching channel and get Tx power */
|
||
|
for (j = 0; j < cfp_no; j++) {
|
||
|
if ((cfp + j)->channel == channel) {
|
||
|
if (tx_power != 0)
|
||
|
tx_power =
|
||
|
MIN(tx_power,
|
||
|
(cfp + j)->max_tx_power);
|
||
|
else
|
||
|
tx_power =
|
||
|
(t_u8)(cfp + j)->max_tx_power;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
|
||
|
/* Get CFP */
|
||
|
cfp_a = cfp_table_A[i].cfp;
|
||
|
cfp_no_a = cfp_table_A[i].cfp_no;
|
||
|
for (j = 0; j < cfp_no_a; j++) {
|
||
|
if ((cfp_a + j)->channel == channel) {
|
||
|
if (tx_power != 0)
|
||
|
tx_power =
|
||
|
MIN(tx_power,
|
||
|
(cfp_a + j)->max_tx_power);
|
||
|
else
|
||
|
tx_power =
|
||
|
(t_u8)((cfp_a +
|
||
|
j)->max_tx_power);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return tx_power;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get the channel frequency power info for a specific channel
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param band It can be BAND_A, BAND_G or BAND_B
|
||
|
* @param channel The channel to search for
|
||
|
* @param region_channel A pointer to region_chan_t structure
|
||
|
*
|
||
|
* @return A pointer to chan_freq_power_t structure or MNULL if not found.
|
||
|
*/
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
region_chan_t *rc;
|
||
|
chan_freq_power_t *cfp = MNULL;
|
||
|
int i, j;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
|
||
|
rc = ®ion_channel[j];
|
||
|
|
||
|
if (!rc->valid || !rc->pcfp)
|
||
|
continue;
|
||
|
switch (rc->band) {
|
||
|
case BAND_A:
|
||
|
switch (band) {
|
||
|
case BAND_AN:
|
||
|
case BAND_A | BAND_AN:
|
||
|
case BAND_A | BAND_AN | BAND_AAC:
|
||
|
case BAND_A: /* Matching BAND_A */
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
case BAND_B:
|
||
|
case BAND_G:
|
||
|
switch (band) {
|
||
|
case BAND_GN:
|
||
|
case BAND_B | BAND_G | BAND_GN:
|
||
|
case BAND_G | BAND_GN:
|
||
|
case BAND_GN | BAND_GAC:
|
||
|
case BAND_B | BAND_G | BAND_GN | BAND_GAC:
|
||
|
case BAND_G | BAND_GN | BAND_GAC:
|
||
|
case BAND_B | BAND_G:
|
||
|
case BAND_B: /* Matching BAND_B/G */
|
||
|
case BAND_G:
|
||
|
case 0:
|
||
|
break;
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
if (channel == FIRST_VALID_CHANNEL)
|
||
|
cfp = &rc->pcfp[0];
|
||
|
else {
|
||
|
for (i = 0; i < rc->num_cfp; i++) {
|
||
|
if (rc->pcfp[i].channel == channel) {
|
||
|
cfp = &rc->pcfp[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cfp && channel)
|
||
|
PRINTM(MCMND, "wlan_get_cfp_by_band_and_channel(): cannot find "
|
||
|
"cfp by band %d & channel %d\n", band, channel);
|
||
|
|
||
|
LEAVE();
|
||
|
return cfp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Find the channel frequency power info for a specific channel
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param band It can be BAND_A, BAND_G or BAND_B
|
||
|
* @param channel The channel to search for
|
||
|
*
|
||
|
* @return A pointer to chan_freq_power_t structure or MNULL if not found.
|
||
|
*/
|
||
|
chan_freq_power_t *
|
||
|
wlan_find_cfp_by_band_and_channel(mlan_adapter *pmadapter,
|
||
|
t_u8 band, t_u16 channel)
|
||
|
{
|
||
|
chan_freq_power_t *cfp = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/* Any station(s) with 11D enabled */
|
||
|
if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
|
||
|
wlan_is_station) > 0)
|
||
|
cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel,
|
||
|
pmadapter->
|
||
|
universal_channel);
|
||
|
else
|
||
|
cfp = wlan_get_cfp_by_band_and_channel(pmadapter, band, channel,
|
||
|
pmadapter->
|
||
|
region_channel);
|
||
|
|
||
|
LEAVE();
|
||
|
return cfp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Find the channel frequency power info for a specific frequency
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
* @param band It can be BAND_A, BAND_G or BAND_B
|
||
|
* @param freq The frequency to search for
|
||
|
*
|
||
|
* @return Pointer to chan_freq_power_t structure; MNULL if not found
|
||
|
*/
|
||
|
chan_freq_power_t *
|
||
|
wlan_find_cfp_by_band_and_freq(mlan_adapter *pmadapter, t_u8 band, t_u32 freq)
|
||
|
{
|
||
|
chan_freq_power_t *cfp = MNULL;
|
||
|
region_chan_t *rc;
|
||
|
int i, j;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
|
||
|
rc = &pmadapter->region_channel[j];
|
||
|
|
||
|
/* Any station(s) with 11D enabled */
|
||
|
if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
|
||
|
wlan_is_station) > 0)
|
||
|
rc = &pmadapter->universal_channel[j];
|
||
|
|
||
|
if (!rc->valid || !rc->pcfp)
|
||
|
continue;
|
||
|
switch (rc->band) {
|
||
|
case BAND_A:
|
||
|
switch (band) {
|
||
|
case BAND_AN:
|
||
|
case BAND_A | BAND_AN:
|
||
|
case BAND_A | BAND_AN | BAND_AAC:
|
||
|
case BAND_A: /* Matching BAND_A */
|
||
|
break;
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
case BAND_B:
|
||
|
case BAND_G:
|
||
|
switch (band) {
|
||
|
case BAND_GN:
|
||
|
case BAND_B | BAND_G | BAND_GN:
|
||
|
case BAND_G | BAND_GN:
|
||
|
case BAND_GN | BAND_GAC:
|
||
|
case BAND_B | BAND_G | BAND_GN | BAND_GAC:
|
||
|
case BAND_G | BAND_GN | BAND_GAC:
|
||
|
case BAND_B | BAND_G:
|
||
|
case BAND_B:
|
||
|
case BAND_G:
|
||
|
case 0:
|
||
|
break;
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
for (i = 0; i < rc->num_cfp; i++) {
|
||
|
if (rc->pcfp[i].freq == freq) {
|
||
|
cfp = &rc->pcfp[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cfp && freq)
|
||
|
PRINTM(MERROR,
|
||
|
"wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
|
||
|
"band %d & freq %d\n", band, freq);
|
||
|
|
||
|
LEAVE();
|
||
|
return cfp;
|
||
|
}
|
||
|
#endif /* STA_SUPPORT */
|
||
|
|
||
|
/**
|
||
|
* @brief Check if Rate Auto
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
*
|
||
|
* @return MTRUE or MFALSE
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_is_rate_auto(mlan_private *pmpriv)
|
||
|
{
|
||
|
t_u32 i;
|
||
|
int rate_num = 0;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates); i++)
|
||
|
if (pmpriv->bitmap_rates[i])
|
||
|
rate_num++;
|
||
|
|
||
|
LEAVE();
|
||
|
if (rate_num > 1)
|
||
|
return MTRUE;
|
||
|
else
|
||
|
return MFALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Covert Rate Bitmap to Rate index
|
||
|
*
|
||
|
* @param pmadapter Pointer to mlan_adapter structure
|
||
|
* @param rate_bitmap Pointer to rate bitmap
|
||
|
* @param size Size of the bitmap array
|
||
|
*
|
||
|
* @return Rate index
|
||
|
*/
|
||
|
int
|
||
|
wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 *rate_bitmap, int size)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (i = 0; i < size * 8; i++) {
|
||
|
if (rate_bitmap[i / 16] & (1 << (i % 16))) {
|
||
|
LEAVE();
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get supported data rates
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param bss_mode The specified BSS mode (Infra/IBSS)
|
||
|
* @param config_bands The specified band configuration
|
||
|
* @param rates The buf to return the supported rates
|
||
|
*
|
||
|
* @return The number of Rates
|
||
|
*/
|
||
|
t_u32
|
||
|
wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode,
|
||
|
t_u8 config_bands, WLAN_802_11_RATES rates)
|
||
|
{
|
||
|
t_u32 k = 0;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
if (bss_mode == MLAN_BSS_MODE_INFRA) {
|
||
|
/* Infra. mode */
|
||
|
switch (config_bands) {
|
||
|
case (t_u8)BAND_B:
|
||
|
PRINTM(MINFO, "Infra Band=%d SupportedRates_B\n",
|
||
|
config_bands);
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_B,
|
||
|
sizeof(SupportedRates_B));
|
||
|
break;
|
||
|
case (t_u8)BAND_G:
|
||
|
case BAND_G | BAND_GN:
|
||
|
case BAND_G | BAND_GN | BAND_GAC:
|
||
|
PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
|
||
|
config_bands);
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_G,
|
||
|
sizeof(SupportedRates_G));
|
||
|
break;
|
||
|
case BAND_B | BAND_G:
|
||
|
case BAND_A | BAND_B | BAND_G:
|
||
|
case BAND_A | BAND_B:
|
||
|
case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
|
||
|
case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
|
||
|
case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | BAND_GAC:
|
||
|
case BAND_B | BAND_G | BAND_GN:
|
||
|
case BAND_B | BAND_G | BAND_GN | BAND_GAC:
|
||
|
PRINTM(MINFO, "Infra band=%d SupportedRates_BG\n",
|
||
|
config_bands);
|
||
|
#ifdef WIFI_DIRECT_SUPPORT
|
||
|
if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_G,
|
||
|
sizeof(SupportedRates_G));
|
||
|
else
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_BG,
|
||
|
sizeof(SupportedRates_BG));
|
||
|
#else
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_BG,
|
||
|
sizeof(SupportedRates_BG));
|
||
|
#endif
|
||
|
break;
|
||
|
case BAND_A:
|
||
|
case BAND_A | BAND_G:
|
||
|
PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
|
||
|
config_bands);
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_A,
|
||
|
sizeof(SupportedRates_A));
|
||
|
break;
|
||
|
case BAND_AN:
|
||
|
case BAND_A | BAND_AN:
|
||
|
case BAND_A | BAND_G | BAND_AN | BAND_GN:
|
||
|
case BAND_A | BAND_AN | BAND_AAC:
|
||
|
case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
|
||
|
PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
|
||
|
config_bands);
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_A,
|
||
|
sizeof(SupportedRates_A));
|
||
|
break;
|
||
|
case BAND_GN:
|
||
|
case BAND_GN | BAND_GAC:
|
||
|
PRINTM(MINFO, "Infra band=%d SupportedRates_N\n",
|
||
|
config_bands);
|
||
|
k = wlan_copy_rates(rates, k, SupportedRates_N,
|
||
|
sizeof(SupportedRates_N));
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
/* Ad-hoc mode */
|
||
|
switch (config_bands) {
|
||
|
case (t_u8)BAND_B:
|
||
|
PRINTM(MINFO, "Band: Adhoc B\n");
|
||
|
k = wlan_copy_rates(rates, k, AdhocRates_B,
|
||
|
sizeof(AdhocRates_B));
|
||
|
break;
|
||
|
case (t_u8)BAND_G:
|
||
|
PRINTM(MINFO, "Band: Adhoc G only\n");
|
||
|
k = wlan_copy_rates(rates, k, AdhocRates_G,
|
||
|
sizeof(AdhocRates_G));
|
||
|
break;
|
||
|
case BAND_B | BAND_G:
|
||
|
PRINTM(MINFO, "Band: Adhoc BG\n");
|
||
|
k = wlan_copy_rates(rates, k, AdhocRates_BG,
|
||
|
sizeof(AdhocRates_BG));
|
||
|
break;
|
||
|
case BAND_A:
|
||
|
case BAND_A | BAND_AN | BAND_AAC:
|
||
|
PRINTM(MINFO, "Band: Adhoc A\n");
|
||
|
k = wlan_copy_rates(rates, k, AdhocRates_A,
|
||
|
sizeof(AdhocRates_A));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return k;
|
||
|
}
|
||
|
|
||
|
#define COUNTRY_ID_US 0
|
||
|
#define COUNTRY_ID_JP 1
|
||
|
#define COUNTRY_ID_CN 2
|
||
|
#define COUNTRY_ID_EU 3
|
||
|
typedef struct _oper_bw_chan {
|
||
|
/*non-global operating class */
|
||
|
t_u8 oper_class;
|
||
|
/*global operating class */
|
||
|
t_u8 global_oper_class;
|
||
|
/*bandwidth 0-20M 1-40M 2-80M 3-160M */
|
||
|
t_u8 bandwidth;
|
||
|
/*channel list */
|
||
|
t_u8 channel_list[13];
|
||
|
} oper_bw_chan;
|
||
|
|
||
|
/** oper class table for US*/
|
||
|
static oper_bw_chan oper_bw_chan_us[] = {
|
||
|
/** non-Global oper class, global oper class, bandwidth, channel list*/
|
||
|
{1, 115, 0, {36, 40, 44, 48}},
|
||
|
{2, 118, 0, {52, 56, 60, 64}},
|
||
|
{3, 124, 0, {149, 153, 157, 161}},
|
||
|
{4, 121, 0,
|
||
|
{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144}},
|
||
|
{5, 125, 0, {149, 153, 157, 161, 165}},
|
||
|
{12, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}},
|
||
|
{22, 116, 1, {36, 44}},
|
||
|
{23, 119, 1, {52, 60}},
|
||
|
{24, 122, 1, {100, 108, 116, 124, 132, 140}},
|
||
|
{25, 126, 1, {149, 157}},
|
||
|
{26, 126, 1, {149, 157}},
|
||
|
{27, 117, 1, {40, 48}},
|
||
|
{28, 120, 1, {56, 64}},
|
||
|
{29, 123, 1, {104, 112, 120, 128, 136, 144}},
|
||
|
{30, 127, 1, {153, 161}},
|
||
|
{31, 127, 1, {153, 161}},
|
||
|
{32, 83, 1, {1, 2, 3, 4, 5, 6, 7}},
|
||
|
{33, 84, 1, {5, 6, 7, 8, 9, 10, 11}},
|
||
|
{128, 128, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
{129, 129, 3, {50, 114}},
|
||
|
{130, 130, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
};
|
||
|
|
||
|
/** oper class table for EU*/
|
||
|
static oper_bw_chan oper_bw_chan_eu[] = {
|
||
|
/** non-global oper class,global oper class, bandwidth, channel list*/
|
||
|
{1, 115, 0, {36, 40, 44, 48}},
|
||
|
{2, 118, 0, {52, 56, 60, 64}},
|
||
|
{3, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
|
||
|
{4, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
|
||
|
{5, 116, 1, {36, 44}},
|
||
|
{6, 119, 1, {52, 60}},
|
||
|
{7, 122, 1, {100, 108, 116, 124, 132}},
|
||
|
{8, 117, 1, {40, 48}},
|
||
|
{9, 120, 1, {56, 64}},
|
||
|
{10, 123, 1, {104, 112, 120, 128, 136}},
|
||
|
{11, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
|
||
|
{12, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
|
||
|
{17, 125, 0, {149, 153, 157, 161, 165, 169}},
|
||
|
{128, 128, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
{129, 129, 3, {50, 114}},
|
||
|
{130, 130, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
};
|
||
|
|
||
|
/** oper class table for Japan*/
|
||
|
static oper_bw_chan oper_bw_chan_jp[] = {
|
||
|
/** non-Global oper class,global oper class, bandwidth, channel list*/
|
||
|
{1, 115, 0, {34, 38, 42, 46, 36, 40, 44, 48}},
|
||
|
{30, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
|
||
|
{31, 82, 0, {14}},
|
||
|
{32, 118, 0, {52, 56, 60, 64}},
|
||
|
{33, 118, 0, {52, 56, 60, 64}},
|
||
|
{34, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
|
||
|
{35, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
|
||
|
{36, 116, 1, {36, 44}},
|
||
|
{37, 119, 1, {52, 60}},
|
||
|
{38, 119, 1, {52, 60}},
|
||
|
{39, 122, 1, {100, 108, 116, 124, 132}},
|
||
|
{40, 122, 1, {100, 108, 116, 124, 132}},
|
||
|
{41, 117, 1, {40, 48}},
|
||
|
{42, 120, 1, {56, 64}},
|
||
|
{43, 120, 1, {56, 64}},
|
||
|
{44, 123, 1, {104, 112, 120, 128, 136}},
|
||
|
{45, 123, 1, {104, 112, 120, 128, 136}},
|
||
|
{56, 83, 1, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
|
||
|
{57, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
|
||
|
{58, 121, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}},
|
||
|
{128, 128, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
{129, 129, 3, {50, 114}},
|
||
|
{130, 130, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
};
|
||
|
|
||
|
/** oper class table for China*/
|
||
|
static oper_bw_chan oper_bw_chan_cn[] = {
|
||
|
/** non-Global oper class,global oper class, bandwidth, channel list*/
|
||
|
{1, 115, 0, {36, 40, 44, 48}},
|
||
|
{2, 118, 0, {52, 56, 60, 64}},
|
||
|
{3, 125, 0, {149, 153, 157, 161, 165}},
|
||
|
{4, 116, 1, {36, 44}},
|
||
|
{5, 119, 1, {52, 60}},
|
||
|
{6, 126, 1, {149, 157}},
|
||
|
{7, 81, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}},
|
||
|
{8, 83, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9}},
|
||
|
{9, 84, 1, {5, 6, 7, 8, 9, 10, 11, 12, 13}},
|
||
|
{128, 128, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
{129, 129, 3, {50, 114}},
|
||
|
{130, 130, 2, {42, 58, 106, 122, 138, 155}},
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @brief Get non-global operaing class table according to country
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param arraysize A pointer to table size
|
||
|
*
|
||
|
* @return A pointer to oper_bw_chan
|
||
|
*/
|
||
|
oper_bw_chan *
|
||
|
wlan_get_nonglobal_operclass_table(mlan_private *pmpriv, int *arraysize)
|
||
|
{
|
||
|
t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
|
||
|
int country_id = 0;
|
||
|
oper_bw_chan *poper_bw_chan = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (country_id = 0; country_id < 3; country_id++)
|
||
|
if (!memcmp
|
||
|
(pmpriv->adapter, pmpriv->adapter->country_code,
|
||
|
country_code[country_id], COUNTRY_CODE_LEN - 1))
|
||
|
break;
|
||
|
if (country_id >= 3)
|
||
|
country_id = COUNTRY_ID_US; /*Set default to US */
|
||
|
if (wlan_is_etsi_country
|
||
|
(pmpriv->adapter, pmpriv->adapter->country_code))
|
||
|
country_id = COUNTRY_ID_EU;
|
||
|
/** Country in EU */
|
||
|
|
||
|
switch (country_id) {
|
||
|
case COUNTRY_ID_US:
|
||
|
poper_bw_chan = oper_bw_chan_us;
|
||
|
*arraysize = sizeof(oper_bw_chan_us);
|
||
|
break;
|
||
|
case COUNTRY_ID_JP:
|
||
|
poper_bw_chan = oper_bw_chan_jp;
|
||
|
*arraysize = sizeof(oper_bw_chan_jp);
|
||
|
break;
|
||
|
case COUNTRY_ID_CN:
|
||
|
poper_bw_chan = oper_bw_chan_cn;
|
||
|
*arraysize = sizeof(oper_bw_chan_cn);
|
||
|
break;
|
||
|
case COUNTRY_ID_EU:
|
||
|
poper_bw_chan = oper_bw_chan_eu;
|
||
|
*arraysize = sizeof(oper_bw_chan_eu);
|
||
|
break;
|
||
|
default:
|
||
|
PRINTM(MERROR, "Country not support!\n");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return poper_bw_chan;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check validation of given channel and oper class
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param channel Channel number
|
||
|
* @param oper_class operating class
|
||
|
*
|
||
|
* @return MLAN_STATUS_PENDING --success, otherwise fail
|
||
|
*/
|
||
|
mlan_status
|
||
|
wlan_check_operclass_validation(mlan_private *pmpriv, t_u8 channel,
|
||
|
t_u8 oper_class)
|
||
|
{
|
||
|
int arraysize = 0, i = 0, channum = 0;
|
||
|
oper_bw_chan *poper_bw_chan = MNULL;
|
||
|
t_u8 center_freq_idx = 0;
|
||
|
t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (i = 0; i < sizeof(center_freqs); i++) {
|
||
|
if (channel == center_freqs[i]) {
|
||
|
PRINTM(MERROR, "Invalid channel number %d!\n", channel);
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
}
|
||
|
if (oper_class <= 0 || oper_class > 130) {
|
||
|
PRINTM(MERROR, "Invalid operating class!\n");
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
if (oper_class >= 128) {
|
||
|
center_freq_idx =
|
||
|
wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
|
||
|
CHANNEL_BW_80MHZ);
|
||
|
channel = center_freq_idx;
|
||
|
}
|
||
|
poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
|
||
|
|
||
|
if (!poper_bw_chan) {
|
||
|
PRINTM(MCMND, "Operating class table do not find!\n");
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
|
||
|
if (poper_bw_chan[i].oper_class == oper_class ||
|
||
|
poper_bw_chan[i].global_oper_class == oper_class) {
|
||
|
for (channum = 0;
|
||
|
channum < sizeof(poper_bw_chan[i].channel_list);
|
||
|
channum++) {
|
||
|
if (poper_bw_chan[i].channel_list[channum] &&
|
||
|
poper_bw_chan[i].channel_list[channum] ==
|
||
|
channel) {
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PRINTM(MCMND, "Operating class %d do not match channel %d!\n",
|
||
|
oper_class, channel);
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get current operating class from channel and bandwidth
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param channel Channel number
|
||
|
* @param bw Bandwidth
|
||
|
* @param oper_class A pointer to current operating class
|
||
|
*
|
||
|
* @return MLAN_STATUS_PENDING --success, otherwise fail
|
||
|
*/
|
||
|
mlan_status
|
||
|
wlan_get_curr_oper_class(mlan_private *pmpriv, t_u8 channel, t_u8 bw,
|
||
|
t_u8 *oper_class)
|
||
|
{
|
||
|
oper_bw_chan *poper_bw_chan = MNULL;
|
||
|
t_u8 center_freq_idx = 0;
|
||
|
t_u8 center_freqs[] = { 42, 50, 58, 106, 114, 122, 138, 155 };
|
||
|
int i = 0, arraysize = 0, channum = 0;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
poper_bw_chan = wlan_get_nonglobal_operclass_table(pmpriv, &arraysize);
|
||
|
|
||
|
if (!poper_bw_chan) {
|
||
|
PRINTM(MCMND, "Operating class table do not find!\n");
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
for (i = 0; i < sizeof(center_freqs); i++) {
|
||
|
if (channel == center_freqs[i]) {
|
||
|
PRINTM(MERROR, "Invalid channel number %d!\n", channel);
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
}
|
||
|
if (bw == BW_80MHZ) {
|
||
|
center_freq_idx =
|
||
|
wlan_get_center_freq_idx(pmpriv, BAND_AAC, channel,
|
||
|
CHANNEL_BW_80MHZ);
|
||
|
channel = center_freq_idx;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < arraysize / sizeof(oper_bw_chan); i++) {
|
||
|
if (poper_bw_chan[i].bandwidth == bw) {
|
||
|
for (channum = 0;
|
||
|
channum < sizeof(poper_bw_chan[i].channel_list);
|
||
|
channum++) {
|
||
|
if (poper_bw_chan[i].channel_list[channum] &&
|
||
|
poper_bw_chan[i].channel_list[channum] ==
|
||
|
channel) {
|
||
|
*oper_class =
|
||
|
poper_bw_chan[i].oper_class;
|
||
|
return MLAN_STATUS_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PRINTM(MCMND, "Operating class not find!\n");
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Add Supported operating classes IE
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param pptlv_out A pointer to TLV to fill in
|
||
|
* @param curr_oper_class Current operating class
|
||
|
*
|
||
|
* @return Length
|
||
|
*/
|
||
|
int
|
||
|
wlan_add_supported_oper_class_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out,
|
||
|
t_u8 curr_oper_class)
|
||
|
{
|
||
|
|
||
|
t_u8 oper_class_us[] =
|
||
|
{ 1, 2, 3, 4, 5, 12, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||
|
33, 128, 129, 130
|
||
|
};
|
||
|
t_u8 oper_class_eu[] =
|
||
|
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 128, 129, 130
|
||
|
};
|
||
|
t_u8 oper_class_jp[] =
|
||
|
{ 1, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||
|
45, 56, 57, 58, 128, 129, 130
|
||
|
};
|
||
|
t_u8 oper_class_cn[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 129, 130
|
||
|
};
|
||
|
t_u8 country_code[][COUNTRY_CODE_LEN] = { "US", "JP", "CN" };
|
||
|
int country_id = 0, ret = 0;
|
||
|
MrvlIETypes_SuppOperClass_t *poper_class = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
for (country_id = 0; country_id < 3; country_id++)
|
||
|
if (!memcmp
|
||
|
(pmpriv->adapter, pmpriv->adapter->country_code,
|
||
|
country_code[country_id], COUNTRY_CODE_LEN - 1))
|
||
|
break;
|
||
|
if (country_id >= 3)
|
||
|
country_id = COUNTRY_ID_US; /*Set default to US */
|
||
|
if (wlan_is_etsi_country
|
||
|
(pmpriv->adapter, pmpriv->adapter->country_code))
|
||
|
country_id = COUNTRY_ID_EU;
|
||
|
/** Country in EU */
|
||
|
poper_class = (MrvlIETypes_SuppOperClass_t *) * pptlv_out;
|
||
|
memset(pmpriv->adapter, poper_class, 0,
|
||
|
sizeof(MrvlIETypes_SuppOperClass_t));
|
||
|
poper_class->header.type = wlan_cpu_to_le16(REGULATORY_CLASS);
|
||
|
if (country_id == COUNTRY_ID_US) {
|
||
|
poper_class->header.len = sizeof(oper_class_us);
|
||
|
memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_us,
|
||
|
sizeof(oper_class_us));
|
||
|
} else if (country_id == COUNTRY_ID_JP) {
|
||
|
poper_class->header.len = sizeof(oper_class_jp);
|
||
|
memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_jp,
|
||
|
sizeof(oper_class_jp));
|
||
|
} else if (country_id == COUNTRY_ID_CN) {
|
||
|
poper_class->header.len = sizeof(oper_class_cn);
|
||
|
memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_cn,
|
||
|
sizeof(oper_class_cn));
|
||
|
} else if (country_id == COUNTRY_ID_EU) {
|
||
|
poper_class->header.len = sizeof(oper_class_eu);
|
||
|
memcpy(pmpriv->adapter, &poper_class->oper_class, oper_class_eu,
|
||
|
sizeof(oper_class_eu));
|
||
|
}
|
||
|
poper_class->current_oper_class = curr_oper_class;
|
||
|
poper_class->header.len += sizeof(poper_class->current_oper_class);
|
||
|
DBG_HEXDUMP(MCMD_D, "Operating class", (t_u8 *)poper_class,
|
||
|
sizeof(MrvlIEtypesHeader_t) + poper_class->header.len);
|
||
|
ret = sizeof(MrvlIEtypesHeader_t) + poper_class->header.len;
|
||
|
*pptlv_out += ret;
|
||
|
poper_class->header.len = wlan_cpu_to_le16(poper_class->header.len);
|
||
|
|
||
|
LEAVE();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief This function sets region table.
|
||
|
*
|
||
|
* @param pmpriv A pointer to mlan_private structure
|
||
|
* @param region The region code
|
||
|
* @param band The band
|
||
|
*
|
||
|
* @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
|
||
|
*/
|
||
|
mlan_status
|
||
|
wlan_set_regiontable(mlan_private *pmpriv, t_u8 region, t_u8 band)
|
||
|
{
|
||
|
mlan_adapter *pmadapter = pmpriv->adapter;
|
||
|
int i = 0, j;
|
||
|
chan_freq_power_t *cfp;
|
||
|
int cfp_no;
|
||
|
region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];
|
||
|
t_u8 cfp_code_bg = region;
|
||
|
t_u8 cfp_code_a = region;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
memcpy(pmadapter, region_chan_old, pmadapter->region_channel,
|
||
|
sizeof(pmadapter->region_channel));
|
||
|
memset(pmadapter, pmadapter->region_channel, 0,
|
||
|
sizeof(pmadapter->region_channel));
|
||
|
|
||
|
if (band & (BAND_B | BAND_G | BAND_GN)) {
|
||
|
if (pmadapter->cfp_code_bg)
|
||
|
cfp_code_bg = pmadapter->cfp_code_bg;
|
||
|
PRINTM(MCMND, "wlan_set_regiontable 2.4G 0x%x\n", cfp_code_bg);
|
||
|
cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_bg,
|
||
|
BAND_G | BAND_B | BAND_GN,
|
||
|
&cfp_no);
|
||
|
if (cfp) {
|
||
|
pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
|
||
|
pmadapter->region_channel[i].pcfp = cfp;
|
||
|
} else {
|
||
|
PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
|
||
|
region);
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
pmadapter->region_channel[i].valid = MTRUE;
|
||
|
pmadapter->region_channel[i].region = region;
|
||
|
if (band & BAND_GN)
|
||
|
pmadapter->region_channel[i].band = BAND_G;
|
||
|
else
|
||
|
pmadapter->region_channel[i].band =
|
||
|
(band & BAND_G) ? BAND_G : BAND_B;
|
||
|
|
||
|
for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
|
||
|
if (region_chan_old[j].band & (BAND_B | BAND_G))
|
||
|
break;
|
||
|
}
|
||
|
if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid)
|
||
|
wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
|
||
|
region_chan_old[j].pcfp,
|
||
|
region_chan_old[j].num_cfp);
|
||
|
else
|
||
|
wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
|
||
|
i++;
|
||
|
}
|
||
|
if (band & (BAND_A | BAND_AN | BAND_AAC)) {
|
||
|
if (pmadapter->cfp_code_bg)
|
||
|
cfp_code_a = pmadapter->cfp_code_a;
|
||
|
PRINTM(MCMND, "wlan_set_regiontable 5G 0x%x\n", cfp_code_a);
|
||
|
cfp = wlan_get_region_cfp_table(pmadapter, cfp_code_a, BAND_A,
|
||
|
&cfp_no);
|
||
|
if (cfp) {
|
||
|
pmadapter->region_channel[i].num_cfp = (t_u8)cfp_no;
|
||
|
pmadapter->region_channel[i].pcfp = cfp;
|
||
|
} else {
|
||
|
PRINTM(MERROR, "wrong region code %#x in Band A\n",
|
||
|
region);
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_FAILURE;
|
||
|
}
|
||
|
pmadapter->region_channel[i].valid = MTRUE;
|
||
|
pmadapter->region_channel[i].region = region;
|
||
|
pmadapter->region_channel[i].band = BAND_A;
|
||
|
|
||
|
for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
|
||
|
if (region_chan_old[j].band & BAND_A)
|
||
|
break;
|
||
|
}
|
||
|
if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid)
|
||
|
wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
|
||
|
region_chan_old[j].pcfp,
|
||
|
region_chan_old[j].num_cfp);
|
||
|
else
|
||
|
wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
|
||
|
}
|
||
|
LEAVE();
|
||
|
return MLAN_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get if radar detection is enabled or not on a certain channel
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param chnl Channel to determine radar detection requirements
|
||
|
*
|
||
|
* @return
|
||
|
* - MTRUE if radar detection is required
|
||
|
* - MFALSE otherwise
|
||
|
*/
|
||
|
t_bool
|
||
|
wlan_get_cfp_radar_detect(mlan_private *priv, t_u8 chnl)
|
||
|
{
|
||
|
int i, j;
|
||
|
t_bool required = MFALSE;
|
||
|
chan_freq_power_t *pcfp = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/*get the cfp table first */
|
||
|
for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
|
||
|
if (priv->adapter->region_channel[i].band == BAND_A) {
|
||
|
pcfp = priv->adapter->region_channel[i].pcfp;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!pcfp) {
|
||
|
/*This means operation in BAND-A is not support, we can
|
||
|
just return false here, it's harmless */
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
/*get the radar detection requirements according to chan num */
|
||
|
for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
|
||
|
if (pcfp[j].channel == chnl) {
|
||
|
required = pcfp[j].passive_scan_or_radar_detect;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
LEAVE();
|
||
|
return required;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get if scan type is passive or not on a certain channel for b/g band
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param chnl Channel to determine scan type
|
||
|
*
|
||
|
* @return
|
||
|
* - MTRUE if scan type is passive
|
||
|
* - MFALSE otherwise
|
||
|
*/
|
||
|
|
||
|
t_bool
|
||
|
wlan_bg_scan_type_is_passive(mlan_private *priv, t_u8 chnl)
|
||
|
{
|
||
|
int i, j;
|
||
|
t_bool passive = MFALSE;
|
||
|
chan_freq_power_t *pcfp = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/*get the cfp table first */
|
||
|
for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
|
||
|
if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) {
|
||
|
pcfp = priv->adapter->region_channel[i].pcfp;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!pcfp) {
|
||
|
/*This means operation in BAND-B or BAND_G is not support, we can
|
||
|
* just return false here*/
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
/*get the bg scan type according to chan num */
|
||
|
for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
|
||
|
if (pcfp[j].channel == chnl) {
|
||
|
passive = pcfp[j].passive_scan_or_radar_detect;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
LEAVE();
|
||
|
return passive;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get if a channel is disabled or not
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param band Band to check
|
||
|
* @param chan Channel to check
|
||
|
*
|
||
|
* @return
|
||
|
* - MTRUE if channel is disabled
|
||
|
* - MFALSE otherwise
|
||
|
*/
|
||
|
|
||
|
t_bool
|
||
|
wlan_is_chan_disabled(mlan_private *priv, t_u8 band, t_u8 chan)
|
||
|
{
|
||
|
int i, j;
|
||
|
t_bool disabled = MFALSE;
|
||
|
chan_freq_power_t *pcfp = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/* get the cfp table first */
|
||
|
for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
|
||
|
if (priv->adapter->region_channel[i].band & band) {
|
||
|
pcfp = priv->adapter->region_channel[i].pcfp;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pcfp) {
|
||
|
/* check table according to chan num */
|
||
|
for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
|
||
|
if (pcfp[j].channel == chan) {
|
||
|
if (pcfp[j].dynamic.
|
||
|
flags & MARVELL_CHANNEL_DISABLED)
|
||
|
disabled = MTRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return disabled;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get if a channel is blacklisted or not
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param band Band to check
|
||
|
* @param chan Channel to check
|
||
|
*
|
||
|
* @return
|
||
|
* - MTRUE if channel is blacklisted
|
||
|
* - MFALSE otherwise
|
||
|
*/
|
||
|
|
||
|
t_bool
|
||
|
wlan_is_chan_blacklisted(mlan_private *priv, t_u8 band, t_u8 chan)
|
||
|
{
|
||
|
int i, j;
|
||
|
t_bool blacklist = MFALSE;
|
||
|
chan_freq_power_t *pcfp = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/*get the cfp table first */
|
||
|
for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
|
||
|
if (priv->adapter->region_channel[i].band & band) {
|
||
|
pcfp = priv->adapter->region_channel[i].pcfp;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pcfp) {
|
||
|
/*check table according to chan num */
|
||
|
for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
|
||
|
if (pcfp[j].channel == chan) {
|
||
|
blacklist = pcfp[j].dynamic.blacklist;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return blacklist;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set a channel as blacklisted or not
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param band Band to check
|
||
|
* @param chan Channel to check
|
||
|
* @param bl Blacklist if MTRUE
|
||
|
*
|
||
|
* @return
|
||
|
* - MTRUE if channel setting is updated
|
||
|
* - MFALSE otherwise
|
||
|
*/
|
||
|
|
||
|
t_bool
|
||
|
wlan_set_chan_blacklist(mlan_private *priv, t_u8 band, t_u8 chan, t_bool bl)
|
||
|
{
|
||
|
int i, j;
|
||
|
t_bool set_bl = MFALSE;
|
||
|
chan_freq_power_t *pcfp = MNULL;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
/*get the cfp table first */
|
||
|
for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) {
|
||
|
if (priv->adapter->region_channel[i].band & band) {
|
||
|
pcfp = priv->adapter->region_channel[i].pcfp;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pcfp) {
|
||
|
/*check table according to chan num */
|
||
|
for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) {
|
||
|
if (pcfp[j].channel == chan) {
|
||
|
pcfp[j].dynamic.blacklist = bl;
|
||
|
set_bl = MTRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEAVE();
|
||
|
return set_bl;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Convert rateid in IEEE format to MRVL format
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param IeeeMacRate Rate in terms of IEEE format
|
||
|
* @param pmbuf A pointer to packet buffer
|
||
|
*
|
||
|
* @return
|
||
|
* Rate ID in terms of MRVL format
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_ieee_rateid_to_mrvl_rateid(mlan_private *priv, t_u16 IeeeMacRate,
|
||
|
t_u8 *dst_mac)
|
||
|
{
|
||
|
/* Set default rate ID to RATEID_DBPSK1Mbps */
|
||
|
t_u8 mrvlRATEID = 0;
|
||
|
const rate_map *rate_tbl = rate_map_table_1x1;
|
||
|
t_u32 cnt = sizeof(rate_map_table_1x1) / sizeof(rate_map);
|
||
|
t_u8 skip_nss2 = MTRUE;
|
||
|
t_u32 i = 0;
|
||
|
IEEEtypes_HTCap_t *htcap = MNULL;
|
||
|
t_u8 tx_mcs_supp = GET_TXMCSSUPP(priv->usr_dev_mcs_support);
|
||
|
#ifdef UAP_SUPPORT
|
||
|
sta_node *sta_ptr = MNULL;
|
||
|
#endif
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
if (priv->adapter->hw_dev_mcs_support == HT_STREAM_MODE_2X2) {
|
||
|
rate_tbl = rate_map_table_2x2;
|
||
|
cnt = sizeof(rate_map_table_2x2) / sizeof(rate_map);
|
||
|
}
|
||
|
#ifdef UAP_SUPPORT
|
||
|
if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
|
||
|
if (!dst_mac) {
|
||
|
LEAVE();
|
||
|
return mrvlRATEID;
|
||
|
}
|
||
|
sta_ptr =
|
||
|
(sta_node *)util_peek_list(priv->adapter->pmoal_handle,
|
||
|
&priv->sta_list,
|
||
|
priv->adapter->callbacks.
|
||
|
moal_spin_lock,
|
||
|
priv->adapter->callbacks.
|
||
|
moal_spin_unlock);
|
||
|
if (!sta_ptr) {
|
||
|
LEAVE();
|
||
|
return mrvlRATEID;
|
||
|
}
|
||
|
while (sta_ptr != (sta_node *)&priv->sta_list) {
|
||
|
if (memcmp
|
||
|
(priv->adapter, dst_mac, sta_ptr->mac_addr,
|
||
|
MLAN_MAC_ADDR_LENGTH)) {
|
||
|
htcap = &(sta_ptr->HTcap);
|
||
|
break;
|
||
|
}
|
||
|
sta_ptr = sta_ptr->pnext;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef STA_SUPPORT
|
||
|
if (priv->bss_role == MLAN_BSS_ROLE_STA) {
|
||
|
htcap = priv->curr_bss_params.bss_descriptor.pht_cap;
|
||
|
}
|
||
|
#endif
|
||
|
if (htcap) {
|
||
|
/* If user configure tx to 2x2 and peer device rx is 2x2 */
|
||
|
if (tx_mcs_supp >= 2 && htcap->ht_cap.supported_mcs_set[1])
|
||
|
skip_nss2 = MFALSE;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < cnt; i++) {
|
||
|
if (rate_tbl[i].nss && skip_nss2)
|
||
|
continue;
|
||
|
if (rate_tbl[i].rate == IeeeMacRate) {
|
||
|
mrvlRATEID = rate_tbl[i].id;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return mrvlRATEID;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Convert rateid in MRVL format to IEEE format
|
||
|
*
|
||
|
* @param IeeeMacRate Rate in terms of MRVL format
|
||
|
*
|
||
|
* @return
|
||
|
* Rate ID in terms of IEEE format
|
||
|
*/
|
||
|
t_u8
|
||
|
wlan_mrvl_rateid_to_ieee_rateid(t_u8 rate)
|
||
|
{
|
||
|
return rateUnit_500Kbps[rate];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Update CFP tables and power tables from FW
|
||
|
*
|
||
|
* @param priv Private driver information structure
|
||
|
* @param buf Pointer to the buffer holding TLV data
|
||
|
* from 0x242 command response.
|
||
|
* @param buf_left bufsize
|
||
|
*
|
||
|
* @return
|
||
|
* None
|
||
|
*/
|
||
|
void
|
||
|
wlan_add_fw_cfp_tables(pmlan_private pmpriv, t_u8 *buf, t_u16 buf_left)
|
||
|
{
|
||
|
mlan_adapter *pmadapter = pmpriv->adapter;
|
||
|
mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
|
||
|
MrvlIEtypesHeader_t *head;
|
||
|
t_u16 tlv;
|
||
|
t_u16 tlv_buf_len;
|
||
|
t_u16 tlv_buf_left;
|
||
|
t_u16 i;
|
||
|
t_u16 max_tx_pwr_bg = WLAN_TX_PWR_DEFAULT;
|
||
|
t_u16 max_tx_pwr_a = WLAN_TX_PWR_DEFAULT;
|
||
|
t_u8 *tlv_buf;
|
||
|
t_u8 *data;
|
||
|
t_u8 *tmp;
|
||
|
mlan_status ret;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
if (!buf) {
|
||
|
PRINTM(MERROR, "CFP table update failed!\n");
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
pmadapter->tx_power_table_bg_rows = FW_CFP_TABLE_MAX_ROWS_BG;
|
||
|
pmadapter->tx_power_table_bg_cols = FW_CFP_TABLE_MAX_COLS_BG;
|
||
|
pmadapter->tx_power_table_a_rows = FW_CFP_TABLE_MAX_ROWS_A;
|
||
|
pmadapter->tx_power_table_a_cols = FW_CFP_TABLE_MAX_COLS_A;
|
||
|
tlv_buf = (t_u8 *)buf;
|
||
|
tlv_buf_left = buf_left;
|
||
|
|
||
|
while (tlv_buf_left >= sizeof(*head)) {
|
||
|
head = (MrvlIEtypesHeader_t *)tlv_buf;
|
||
|
tlv = wlan_le16_to_cpu(head->type);
|
||
|
tlv_buf_len = wlan_le16_to_cpu(head->len);
|
||
|
|
||
|
if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
|
||
|
break;
|
||
|
data = (t_u8 *)head + sizeof(*head);
|
||
|
|
||
|
switch (tlv) {
|
||
|
case TLV_TYPE_REGION_INFO:
|
||
|
/* Skip adding fw region info if it already exists or
|
||
|
* if this TLV has no set data
|
||
|
*/
|
||
|
if (*data == 0)
|
||
|
break;
|
||
|
if (pmadapter->otp_region)
|
||
|
break;
|
||
|
|
||
|
ret = pcb->moal_malloc(pmadapter->pmoal_handle,
|
||
|
sizeof(otp_region_info_t),
|
||
|
MLAN_MEM_DEF,
|
||
|
(t_u8 **)&pmadapter->otp_region);
|
||
|
if (ret != MLAN_STATUS_SUCCESS ||
|
||
|
!pmadapter->otp_region) {
|
||
|
PRINTM(MERROR,
|
||
|
"Memory allocation for the otp region"
|
||
|
" info struct failed!\n");
|
||
|
break;
|
||
|
}
|
||
|
/* Save region info values from OTP in the otp_region
|
||
|
* structure
|
||
|
*/
|
||
|
memcpy(pmadapter, pmadapter->otp_region, data,
|
||
|
sizeof(otp_region_info_t));
|
||
|
data += sizeof(otp_region_info_t);
|
||
|
/* Get pre-defined cfp tables corresponding to the region code
|
||
|
* in OTP
|
||
|
*/
|
||
|
for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) {
|
||
|
if (cfp_table_BG[i].code ==
|
||
|
pmadapter->otp_region->region_code) {
|
||
|
max_tx_pwr_bg =
|
||
|
(cfp_table_BG[i].cfp)->
|
||
|
max_tx_power;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
for (i = 0; i < MLAN_CFP_TABLE_SIZE_A; i++) {
|
||
|
if (cfp_table_A[i].code ==
|
||
|
pmadapter->otp_region->region_code) {
|
||
|
max_tx_pwr_a =
|
||
|
(cfp_table_A[i].cfp)->
|
||
|
max_tx_power;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
/* Update the region code and the country code in pmadapter */
|
||
|
pmadapter->region_code =
|
||
|
pmadapter->otp_region->region_code;
|
||
|
pmadapter->country_code[0] =
|
||
|
pmadapter->otp_region->country_code[0];
|
||
|
pmadapter->country_code[1] =
|
||
|
pmadapter->otp_region->country_code[1];
|
||
|
pmadapter->country_code[2] = '\0';
|
||
|
pmadapter->domain_reg.country_code[0] =
|
||
|
pmadapter->otp_region->country_code[0];
|
||
|
pmadapter->domain_reg.country_code[1] =
|
||
|
pmadapter->otp_region->country_code[1];
|
||
|
pmadapter->domain_reg.country_code[2] = '\0';
|
||
|
pmadapter->cfp_code_bg =
|
||
|
pmadapter->otp_region->region_code;
|
||
|
pmadapter->cfp_code_a =
|
||
|
pmadapter->otp_region->region_code;
|
||
|
break;
|
||
|
case TLV_TYPE_CHAN_ATTR_CFG:
|
||
|
/* Skip adding fw cfp tables if they already exist or
|
||
|
* if this TLV has no set data
|
||
|
*/
|
||
|
if (*data == 0)
|
||
|
break;
|
||
|
if (pmadapter->cfp_otp_bg || pmadapter->cfp_otp_a) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ret = pcb->moal_malloc(pmadapter->pmoal_handle,
|
||
|
pmadapter->
|
||
|
tx_power_table_bg_rows *
|
||
|
sizeof(chan_freq_power_t),
|
||
|
MLAN_MEM_DEF,
|
||
|
(t_u8 **)&pmadapter->cfp_otp_bg);
|
||
|
if (ret != MLAN_STATUS_SUCCESS ||
|
||
|
!pmadapter->cfp_otp_bg) {
|
||
|
PRINTM(MERROR,
|
||
|
"Memory allocation for storing otp bg"
|
||
|
" table data failed!\n");
|
||
|
break;
|
||
|
}
|
||
|
/* Save channel usability flags from OTP data in the fw cfp bg
|
||
|
* table and set frequency and max_tx_power values
|
||
|
*/
|
||
|
for (i = 0; i < pmadapter->tx_power_table_bg_rows; i++) {
|
||
|
(pmadapter->cfp_otp_bg + i)->channel = *data;
|
||
|
if (*data == 14)
|
||
|
(pmadapter->cfp_otp_bg + i)->freq =
|
||
|
2484;
|
||
|
else
|
||
|
(pmadapter->cfp_otp_bg + i)->freq =
|
||
|
2412 + 5 * (*data - 1);
|
||
|
(pmadapter->cfp_otp_bg + i)->max_tx_power =
|
||
|
max_tx_pwr_bg;
|
||
|
data++;
|
||
|
(pmadapter->cfp_otp_bg + i)->dynamic.flags =
|
||
|
*data;
|
||
|
if (*data & MARVELL_CHANNEL_DFS)
|
||
|
(pmadapter->cfp_otp_bg +
|
||
|
i)->passive_scan_or_radar_detect =
|
||
|
MTRUE;
|
||
|
data++;
|
||
|
}
|
||
|
ret = pcb->moal_malloc(pmadapter->pmoal_handle,
|
||
|
pmadapter->
|
||
|
tx_power_table_a_rows *
|
||
|
sizeof(chan_freq_power_t),
|
||
|
MLAN_MEM_DEF,
|
||
|
(t_u8 **)&pmadapter->cfp_otp_a);
|
||
|
if (ret != MLAN_STATUS_SUCCESS || !pmadapter->cfp_otp_a) {
|
||
|
PRINTM(MERROR,
|
||
|
"Memory allocation for storing otp a"
|
||
|
" table data failed!\n");
|
||
|
break;
|
||
|
}
|
||
|
/* Save channel usability flags from OTP data in the fw cfp a
|
||
|
* table and set frequency and max_tx_power values
|
||
|
*/
|
||
|
for (i = 0; i < pmadapter->tx_power_table_a_rows; i++) {
|
||
|
(pmadapter->cfp_otp_a + i)->channel = *data;
|
||
|
if (*data < 183)
|
||
|
/* 5GHz channels */
|
||
|
(pmadapter->cfp_otp_a + i)->freq =
|
||
|
5035 + 5 * (*data - 7);
|
||
|
else
|
||
|
/* 4GHz channels */
|
||
|
(pmadapter->cfp_otp_a + i)->freq =
|
||
|
4915 + 5 * (*data - 183);
|
||
|
(pmadapter->cfp_otp_a + i)->max_tx_power =
|
||
|
max_tx_pwr_a;
|
||
|
data++;
|
||
|
(pmadapter->cfp_otp_a + i)->dynamic.flags =
|
||
|
*data;
|
||
|
if (*data & MARVELL_CHANNEL_DFS)
|
||
|
(pmadapter->cfp_otp_a +
|
||
|
i)->passive_scan_or_radar_detect =
|
||
|
MTRUE;
|
||
|
data++;
|
||
|
}
|
||
|
break;
|
||
|
case TLV_TYPE_POWER_TABLE:
|
||
|
/* Skip adding fw power tables if this TLV has no data or
|
||
|
* if they already exists but force reg rule is set in the otp
|
||
|
*/
|
||
|
if (*data == 0)
|
||
|
break;
|
||
|
if (pmadapter->otp_region &&
|
||
|
pmadapter->otp_region->force_reg &&
|
||
|
pmadapter->tx_power_table_bg)
|
||
|
break;
|
||
|
|
||
|
/* Save the tlv data in power tables for band BG and A */
|
||
|
tmp = data;
|
||
|
i = 0;
|
||
|
while ((i < pmadapter->tx_power_table_bg_rows *
|
||
|
pmadapter->tx_power_table_bg_cols)
|
||
|
&& (i < tlv_buf_len) && (*tmp != 36)) {
|
||
|
i++;
|
||
|
tmp++;
|
||
|
}
|
||
|
if (!pmadapter->tx_power_table_bg) {
|
||
|
ret = pcb->moal_malloc(pmadapter->pmoal_handle,
|
||
|
i, MLAN_MEM_DEF,
|
||
|
(t_u8 **)&pmadapter->
|
||
|
tx_power_table_bg);
|
||
|
if (ret != MLAN_STATUS_SUCCESS ||
|
||
|
!pmadapter->tx_power_table_bg) {
|
||
|
PRINTM(MERROR,
|
||
|
"Memory allocation for the BG-band"
|
||
|
" power table falied!\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
memcpy(pmadapter, pmadapter->tx_power_table_bg, data,
|
||
|
i);
|
||
|
pmadapter->tx_power_table_bg_size = i;
|
||
|
data += i;
|
||
|
i = 0;
|
||
|
while ((i <
|
||
|
pmadapter->tx_power_table_a_rows *
|
||
|
pmadapter->tx_power_table_a_cols)
|
||
|
&& (i <
|
||
|
(tlv_buf_len -
|
||
|
pmadapter->tx_power_table_bg_size))) {
|
||
|
i++;
|
||
|
}
|
||
|
if (!pmadapter->tx_power_table_a) {
|
||
|
ret = pcb->moal_malloc(pmadapter->pmoal_handle,
|
||
|
i, MLAN_MEM_DEF,
|
||
|
(t_u8 **)&pmadapter->
|
||
|
tx_power_table_a);
|
||
|
if (ret != MLAN_STATUS_SUCCESS ||
|
||
|
!pmadapter->tx_power_table_a) {
|
||
|
PRINTM(MERROR,
|
||
|
"Memory allocation for the A-band"
|
||
|
" power table failed!\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
memcpy(pmadapter, pmadapter->tx_power_table_a, data, i);
|
||
|
pmadapter->tx_power_table_a_size = i;
|
||
|
break;
|
||
|
case TLV_TYPE_POWER_TABLE_ATTR:
|
||
|
pmadapter->tx_power_table_bg_rows =
|
||
|
((power_table_attr_t *) data)->rows_2g;
|
||
|
pmadapter->tx_power_table_bg_cols =
|
||
|
((power_table_attr_t *) data)->cols_2g;
|
||
|
pmadapter->tx_power_table_a_rows =
|
||
|
((power_table_attr_t *) data)->rows_5g;
|
||
|
pmadapter->tx_power_table_a_cols =
|
||
|
((power_table_attr_t *) data)->cols_5g;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
tlv_buf += (sizeof(*head) + tlv_buf_len);
|
||
|
tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
|
||
|
}
|
||
|
out:
|
||
|
LEAVE();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief This function deallocates otp cfp and power tables memory.
|
||
|
*
|
||
|
* @param pmadapter A pointer to mlan_adapter structure
|
||
|
*/
|
||
|
void
|
||
|
wlan_free_fw_cfp_tables(mlan_adapter *pmadapter)
|
||
|
{
|
||
|
pmlan_callbacks pcb;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
pcb = &pmadapter->callbacks;
|
||
|
if (pmadapter->otp_region)
|
||
|
pcb->moal_mfree(pmadapter->pmoal_handle,
|
||
|
(t_u8 *)pmadapter->otp_region);
|
||
|
if (pmadapter->cfp_otp_bg)
|
||
|
pcb->moal_mfree(pmadapter->pmoal_handle,
|
||
|
(t_u8 *)pmadapter->cfp_otp_bg);
|
||
|
if (pmadapter->tx_power_table_bg)
|
||
|
pcb->moal_mfree(pmadapter->pmoal_handle,
|
||
|
(t_u8 *)pmadapter->tx_power_table_bg);
|
||
|
pmadapter->tx_power_table_bg_size = 0;
|
||
|
if (pmadapter->cfp_otp_a)
|
||
|
pcb->moal_mfree(pmadapter->pmoal_handle,
|
||
|
(t_u8 *)pmadapter->cfp_otp_a);
|
||
|
if (pmadapter->tx_power_table_a)
|
||
|
pcb->moal_mfree(pmadapter->pmoal_handle,
|
||
|
(t_u8 *)pmadapter->tx_power_table_a);
|
||
|
pmadapter->tx_power_table_a_size = 0;
|
||
|
LEAVE();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get power tables and cfp tables for set region code
|
||
|
* into the IOCTL request buffer
|
||
|
*
|
||
|
* @param pmadapter Private mlan adapter structure
|
||
|
* @param pioctl_req Pointer to the IOCTL request structure
|
||
|
*
|
||
|
* @return success, otherwise fail
|
||
|
*
|
||
|
*/
|
||
|
mlan_status
|
||
|
wlan_get_cfpinfo(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
|
||
|
{
|
||
|
chan_freq_power_t *cfp_bg = MNULL;
|
||
|
t_u32 cfp_no_bg = 0;
|
||
|
chan_freq_power_t *cfp_a = MNULL;
|
||
|
t_u32 cfp_no_a = 0;
|
||
|
t_u32 len = 0, size = 0;
|
||
|
t_u8 *req_buf, *tmp;
|
||
|
mlan_status ret = MLAN_STATUS_SUCCESS;
|
||
|
|
||
|
ENTER();
|
||
|
|
||
|
if (!pioctl_req || !pioctl_req->pbuf) {
|
||
|
PRINTM(MERROR, "MLAN IOCTL information is not present!\n");
|
||
|
ret = MLAN_STATUS_FAILURE;
|
||
|
goto out;
|
||
|
}
|
||
|
/* Calculate the total response size required to return region,
|
||
|
* country codes, cfp tables and power tables
|
||
|
*/
|
||
|
size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
|
||
|
/* Add size to store region, country and environment codes */
|
||
|
size += sizeof(t_u32);
|
||
|
|
||
|
/* Get cfp table and its size corresponding to the region code */
|
||
|
cfp_bg = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
|
||
|
BAND_G | BAND_B, &cfp_no_bg);
|
||
|
size += cfp_no_bg * sizeof(chan_freq_power_t);
|
||
|
cfp_a = wlan_get_region_cfp_table(pmadapter, pmadapter->region_code,
|
||
|
BAND_A, &cfp_no_a);
|
||
|
size += cfp_no_a * sizeof(chan_freq_power_t);
|
||
|
if (pmadapter->otp_region)
|
||
|
size += sizeof(pmadapter->otp_region->environment);
|
||
|
|
||
|
/* Get power table size */
|
||
|
if (pmadapter->tx_power_table_bg) {
|
||
|
size += pmadapter->tx_power_table_bg_size;
|
||
|
/* Add size to store table size, rows and cols */
|
||
|
size += 3 * sizeof(t_u32);
|
||
|
}
|
||
|
if (pmadapter->tx_power_table_a) {
|
||
|
size += pmadapter->tx_power_table_a_size;
|
||
|
size += 3 * sizeof(t_u32);
|
||
|
}
|
||
|
/* Check information buffer length of MLAN IOCTL */
|
||
|
if (pioctl_req->buf_len < size) {
|
||
|
PRINTM(MWARN,
|
||
|
"MLAN IOCTL information buffer length is too short.\n");
|
||
|
pioctl_req->buf_len_needed = size;
|
||
|
pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
|
||
|
ret = MLAN_STATUS_RESOURCE;
|
||
|
goto out;
|
||
|
}
|
||
|
/* Copy the total size of region code, country code and environment
|
||
|
* in first four bytes of the IOCTL request buffer and then copy
|
||
|
* codes respectively in following bytes
|
||
|
*/
|
||
|
req_buf = (t_u8 *)pioctl_req->pbuf;
|
||
|
size = sizeof(pmadapter->country_code) + sizeof(pmadapter->region_code);
|
||
|
if (pmadapter->otp_region)
|
||
|
size += sizeof(pmadapter->otp_region->environment);
|
||
|
tmp = (t_u8 *)&size;
|
||
|
memcpy(pmadapter, req_buf, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
memcpy(pmadapter, req_buf + len, &pmadapter->region_code,
|
||
|
sizeof(pmadapter->region_code));
|
||
|
len += sizeof(pmadapter->region_code);
|
||
|
memcpy(pmadapter, req_buf + len, &pmadapter->country_code,
|
||
|
sizeof(pmadapter->country_code));
|
||
|
len += sizeof(pmadapter->country_code);
|
||
|
if (pmadapter->otp_region) {
|
||
|
memcpy(pmadapter, req_buf + len,
|
||
|
&pmadapter->otp_region->environment,
|
||
|
sizeof(pmadapter->otp_region->environment));
|
||
|
len += sizeof(pmadapter->otp_region->environment);
|
||
|
}
|
||
|
/* copy the cfp table size followed by the entire table */
|
||
|
if (!cfp_bg)
|
||
|
goto out;
|
||
|
size = cfp_no_bg * sizeof(chan_freq_power_t);
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
memcpy(pmadapter, req_buf + len, cfp_bg, size);
|
||
|
len += size;
|
||
|
if (!cfp_a)
|
||
|
goto out;
|
||
|
size = cfp_no_a * sizeof(chan_freq_power_t);
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
memcpy(pmadapter, req_buf + len, cfp_a, size);
|
||
|
len += size;
|
||
|
/* Copy the size of the power table, number of rows, number of cols
|
||
|
* and the entire power table
|
||
|
*/
|
||
|
if (!pmadapter->tx_power_table_bg)
|
||
|
goto out;
|
||
|
size = pmadapter->tx_power_table_bg_size;
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
|
||
|
/* No. of rows */
|
||
|
size = pmadapter->tx_power_table_bg_rows;
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
|
||
|
/* No. of cols */
|
||
|
size = pmadapter->tx_power_table_bg_size /
|
||
|
pmadapter->tx_power_table_bg_rows;
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_bg,
|
||
|
pmadapter->tx_power_table_bg_size);
|
||
|
len += pmadapter->tx_power_table_bg_size;
|
||
|
if (!pmadapter->tx_power_table_a)
|
||
|
goto out;
|
||
|
size = pmadapter->tx_power_table_a_size;
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
|
||
|
/* No. of rows */
|
||
|
size = pmadapter->tx_power_table_a_rows;
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
|
||
|
/* No. of cols */
|
||
|
size = pmadapter->tx_power_table_a_size /
|
||
|
pmadapter->tx_power_table_a_rows;
|
||
|
memcpy(pmadapter, req_buf + len, tmp, sizeof(size));
|
||
|
len += sizeof(size);
|
||
|
memcpy(pmadapter, req_buf + len, pmadapter->tx_power_table_a,
|
||
|
pmadapter->tx_power_table_a_size);
|
||
|
len += pmadapter->tx_power_table_a_size;
|
||
|
out:
|
||
|
if (pioctl_req)
|
||
|
pioctl_req->data_read_written = len;
|
||
|
|
||
|
LEAVE();
|
||
|
return ret;
|
||
|
}
|