Files
luban-lite-t3e-pro/bsp/peripheral/wireless/atbm603x/hal/atbm_config.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

516 lines
15 KiB
C

/**************************************************************************************************************
* altobeam RTOS wifi hmac source code
*
* Copyright (c) 2018, altobeam.inc All rights reserved.
*
* The source code contains proprietary information of AltoBeam, and shall not be distributed,
* copied, reproduced, or disclosed in whole or in part without prior written permission of AltoBeam.
*****************************************************************************************************************/
#include "atbm_hal.h"
extern struct atbmwifi_common g_hw_prv;
static atbm_int32 Rssi_last = 0;
static atbm_int32 Rssi_aver = 0;
atbm_int32 atbmwifi_get_rssi_avg(atbm_void)
{
return -(Rssi_aver >> 10);
}
atbm_int32 atbmwifi_get_rssi(atbm_void)
{
return Rssi_last;
}
atbm_void atbmwifi_set_rssi(atbm_int8 rssi)
{
Rssi_last = rssi;
Rssi_aver = Rssi_aver ? ((Rssi_aver << 3) - Rssi_aver + ((-rssi) << 10)) >> 3 : (-rssi) << 10;
}
/****************************************************
Function Name: atbmwifi_set_tx_time
Parameters:
time_period: transmit period
time_transmit: transmit time in the period
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 atbmwifi_set_tx_time(atbm_uint32 time_period, atbm_uint32 time_transmit)
{
atbm_int32 ret = 0;
char cmd[32];
atbm_uint8 if_id;
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
if(time_transmit > time_period){
wifi_printk(WIFI_DBG_ERROR, "atbmwifi_set_tx_time(), error, trans = %d, period = %d\n", time_transmit, time_period);
return -ATBM_EINVAL;
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
atbm_memset(cmd, 0, sizeof(cmd));
sprintf(cmd,"set_tx_time %d,%d ", time_period, time_transmit);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD,cmd, strlen(cmd), priv->if_id);
}
return ret;
}
/****************************************************
Function Name: atbmwifi_set_retry
Parameters:
retry_num: max retry transmit number
retry_time_ms: max retry transnit time
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 atbmwifi_set_retry(atbm_uint32 retry_num, atbm_uint32 retry_time_ms)
{
atbm_int32 ret = 0;
char cmd[32];
atbm_uint8 if_id;
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
if(retry_num >= 200){
wifi_printk(WIFI_DBG_ERROR, "atbmwifi_set_retry(), error, retry_num %d\n", retry_num);
}
if(retry_time_ms > 1000){
wifi_printk(WIFI_DBG_ERROR, "atbmwifi_set_retry(), error, retry_time_ms %d\n", retry_time_ms);
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
atbm_memset(cmd, 0, sizeof(cmd));
sprintf(cmd,"set_retry %d,%d ", retry_num, retry_time_ms);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD,cmd, strlen(cmd), priv->if_id);
}
return ret;
}
/****************************************************
Function Name: atbmwifi_set_txpower
Parameters:
txpower_idx: [0:12] -> [-3:0.5:3]dB -> [-30:5:30]/10 dB
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 atbmwifi_set_txpower(atbm_uint32 txpower_idx)
{
atbm_int32 ret = 0;
char cmd[32];
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_uint8 if_id;
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
if(txpower_idx > 12){
wifi_printk(WIFI_DBG_ERROR, "atbmwifi_set_txpower(), error, txpower_idx %d\n", txpower_idx);
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
atbm_memset(cmd, 0, sizeof(cmd));
sprintf(cmd,"set_txpower %d ", txpower_idx);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD,cmd, strlen(cmd), priv->if_id);
}
return ret;
}
/****************************************************
Function Name: atbm_dev_set_adaptive
Parameters:
0: disable
1: enable
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 atbmwifi_dev_set_adaptive(atbm_uint32 adaptive)
{
int ret = 0;
char cmd[32];
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_uint8 if_id;
/*
0: disable
1: enable
*/
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
atbm_memset(cmd, 0, sizeof(cmd));
sprintf(cmd, "set_adaptive %d ", adaptive);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD, cmd, strlen(cmd), priv->if_id);
}
return ret;
}
/****************************************************
Function Name: atbmwifi_tx_rate_set
Parameters:
rate: (11b)->10,20,55,110
(11g)->60,90,120,180,240,360,480,540
(11n)->65,130,195,260,390,520,585,650
Reset->0
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 globle_rate = 0;
atbm_int32 atbmwifi_set_tx_rate(atbm_int32 rate)
{
atbm_int32 ret = 0;
char cmd[32];
atbm_uint8 if_id;
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_memset(cmd, 0, sizeof(cmd));
switch(rate){
//11b
case 10:
case 20:
case 55:
case 110:
globle_rate = RATE_INDEX_B_11M;
break;
//11g
case 60:
case 90:
case 120:
case 180:
case 240:
case 360:
case 480:
case 540:
globle_rate = RATE_INDEX_A_54M;
break;
//11n
case 65:
case 130:
case 195:
case 260:
case 390:
case 520:
case 585:
case 650:
globle_rate = RATE_INDEX_N_65M;
break;
//not force rate
case 0:
globle_rate = 0;
break;
default:
wifi_printk(WIFI_DBG_ERROR, "atbm: invalid rate(%d)\n", rate);
wifi_printk(WIFI_DBG_ERROR, "please enter: 10,20,55,110(11b)\n");
wifi_printk(WIFI_DBG_ERROR, " 60,90,120,180,240,360,480,540(11g)\n");
wifi_printk(WIFI_DBG_ERROR, " 65,130,195,260,390,520,585,650(11n)\n");
return -ATBM_EINVAL;
}
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
sprintf(cmd,"lmac_rate %d ", rate);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD,cmd, strlen(cmd), priv->if_id);
}
return ret;
}
/****************************************************
Function Name: atbmwifi_set_sgi
Parameters:
sgi: short GI
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 atbmwifi_set_sgi(atbm_uint32 sgi)
{
atbm_int32 ret = 0;
char cmd[32];
atbm_uint8 if_id;
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_memset(cmd, 0, sizeof(cmd));
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
sprintf(cmd,"lmac_sgi %d ", sgi);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD,cmd, strlen(cmd), priv->if_id);
}
return ret;
}
/****************************************************
Function Name: atbmwifi_set_rate_txpower_mode
Parameters:
txpower_idx: [-16:16] -> [-8:0.5:8]dB -> [-80:5:80]/10 dB
Return: Success(0), Error(<0)
******************************************************/
atbm_int32 atbmwifi_set_rate_txpower_mode(atbm_int32 txpower_idx)
{
atbm_int32 ret = 0;
char cmd[32];
atbm_uint8 if_id;
struct atbmwifi_vif *priv=ATBM_NULL;
struct atbmwifi_common *hw_priv=ATBM_NULL;
atbm_memset(cmd, 0, sizeof(cmd));
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
sprintf(cmd,"set_rate_txpower_mode %d ", txpower_idx);
ret = wsm_write_mib(hw_priv, WSM_MIB_ID_FW_CMD,cmd, strlen(cmd), priv->if_id);
}
return ret;
}
atbm_int32 atbmwifi_get_lmacLog_to_host(atbm_uint32 value){
atbm_uint8 ucDbgPrintOpenFlag = 0;
atbm_uint8 ret = 0;
atbm_uint8 if_id;
struct atbmwifi_common *hw_priv=ATBM_NULL;
struct atbmwifi_vif *priv=ATBM_NULL;
ucDbgPrintOpenFlag =value;
atbm_for_each_vif(&g_hw_prv,priv,if_id){
if(priv== NULL){
continue;
}
hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
ret=wsm_write_mib(hw_priv, WSM_MIB_ID_DBG_PRINT_TO_HOST,
&ucDbgPrintOpenFlag, sizeof(ucDbgPrintOpenFlag), priv->if_id);
}
return ret;
}
/* TODO:COMBO:UAPSD will be supported only on one interface */
int atbmwifi_set_uapsd_param(struct atbmwifi_vif *priv,
const struct wsm_edca_params *arg)
{
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
struct wsm_uapsd_info uapsd_info={0};
int ret;
atbm_uint16 uapsdFlags = 0;
/* Here's the mapping AC [queue, bit]
VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0]*/
if (arg->params[0].uapsdEnable)
uapsdFlags |= 1 << 3;
if (arg->params[1].uapsdEnable)
uapsdFlags |= 1 << 2;
if (arg->params[2].uapsdEnable)
uapsdFlags |= 1 << 1;
if (arg->params[3].uapsdEnable)
uapsdFlags |= 1;
/* Currently pseudo U-APSD operation is not supported, so setting
* MinAutoTriggerInterval, MaxAutoTriggerInterval and
* AutoTriggerStep to 0 */
uapsd_info.uapsdFlags = atbm_cpu_to_le16(uapsdFlags);
uapsd_info.minAutoTriggerInterval = 0;
uapsd_info.maxAutoTriggerInterval = 0;
uapsd_info.autoTriggerStep = 0;
ret = wsm_set_uapsd_info(hw_priv, &uapsd_info,
priv->if_id);
priv->uapsd_info.uapsdFlags=uapsd_info.uapsdFlags;
return ret;
}
static atbm_void __atbmwifi_bf_configure(struct atbmwifi_vif *priv,struct wsm_beacon_filter_table *bf_table)
{
bf_table->numOfIEs = atbm_cpu_to_le32(3);
bf_table->entry[0].ieId = ATBM_WLAN_EID_VENDOR_SPECIFIC;
bf_table->entry[0].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
WSM_BEACON_FILTER_IE_HAS_APPEARED;
bf_table->entry[0].oui[0] = 0x50;
bf_table->entry[0].oui[1] = 0x6F;
bf_table->entry[0].oui[2] = 0x9A;
bf_table->entry[1].ieId = ATBM_WLAN_EID_ERP_INFO;
bf_table->entry[1].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
WSM_BEACON_FILTER_IE_HAS_APPEARED;
bf_table->entry[2].ieId = ATBM_WLAN_EID_HT_OPERATION;
bf_table->entry[2].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
WSM_BEACON_FILTER_IE_HAS_APPEARED;
}
int atbmwifi_setup_mac(struct atbmwifi_common *hw_priv)
{
int ret = 0;
struct wsm_configuration cfg={0};
cfg.dot11MaxTransmitMsduLifeTime = 512;
cfg.dot11MaxReceiveLifeTime =512;
cfg.dot11RtsThreshold =1000;
cfg.dot11StationId = (atbm_uint8*)&hw_priv->addresses[0];
/* Set low-power mode. */
ret |= (wsm_configuration(hw_priv, &cfg, 0));
return 0;
}
int atbmwifi_vif_setup(struct atbmwifi_vif *priv)
{
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
struct wsm_edca_params edca;
struct config_edca_params *wmm_param;
int ret = 0;
/* default EDCA */
//VO
wmm_param= &priv->wmm_params[ATBM_D11_ACI_AC_VO];
WSM_EDCA_SET(&edca, ATBM_IEEE80211_AC_VO /*0*/, wmm_param->aifns, wmm_param->cwMin, wmm_param->cwMax,
wmm_param->txOpLimit, 0xc8, wmm_param->uapsdEnable);
//VI
wmm_param= &priv->wmm_params[ATBM_D11_ACI_AC_VI];
WSM_EDCA_SET(&edca, ATBM_IEEE80211_AC_VI /*1*/, wmm_param->aifns, wmm_param->cwMin, wmm_param->cwMax,
wmm_param->txOpLimit, 0xc8, wmm_param->uapsdEnable);
//BE
wmm_param= &priv->wmm_params[ATBM_D11_ACI_AC_BE];
WSM_EDCA_SET(&edca, ATBM_IEEE80211_AC_BE /*2*/, wmm_param->aifns, wmm_param->cwMin, wmm_param->cwMax,
wmm_param->txOpLimit, 0xc8, wmm_param->uapsdEnable);
//BK
wmm_param= &priv->wmm_params[ATBM_D11_ACI_AC_BK];
WSM_EDCA_SET(&edca, ATBM_IEEE80211_AC_BK /*3*/, wmm_param->aifns, wmm_param->cwMin, wmm_param->cwMax,
wmm_param->txOpLimit, 0xc8, wmm_param->uapsdEnable);
ret = wsm_set_edca_params(hw_priv, &edca, priv->if_id);
if (ATBM_WARN_ON(ret))
goto out;
ret = atbmwifi_set_uapsd_param(priv, &edca);
if (ATBM_WARN_ON(ret))
goto out;
priv->wep_default_key_id = -1;
priv->bf_control.enabled = WSM_BEACON_FILTER_ENABLE;
out:
return ret;
}
int atbmwifi_setup_mac_pvif(struct atbmwifi_vif *priv)
{
int ret = 0;
/* NOTE: There is a bug in FW: it reports signal
* as RSSI if RSSI subscription is enabled.
* It's not enough to set WSM_RCPI_RSSI_USE_RSSI. */
/* NOTE2: RSSI based reports have been switched to RCPI, since
* FW has a bug and RSSI reported values are not stable,
* what can leads to signal level oscilations in user-end applications */
struct wsm_rcpi_rssi_threshold threshold={0};
threshold.rssiRcpiMode = WSM_RCPI_RSSI_THRESHOLD_ENABLE | WSM_RCPI_RSSI_DONT_USE_UPPER |WSM_RCPI_RSSI_DONT_USE_LOWER;
threshold.rollingAverageCount = 16;
/* Remember the decission here to make sure, we will handle
* the RCPI/RSSI value correctly on WSM_EVENT_RCPI_RSS */
if (threshold.rssiRcpiMode & WSM_RCPI_RSSI_USE_RSSI)
priv->cqm_use_rssi = ATBM_TRUE;
/* Configure RSSI/SCPI reporting as RSSI. */
#ifdef P2P_MULTIVIF
ret = wsm_set_rcpi_rssi_threshold(priv->hw_priv, &threshold,
priv->if_id ? 1 : 0);
#else
ret = wsm_set_rcpi_rssi_threshold(priv->hw_priv, &threshold,
priv->if_id);
#endif
return ret;
}
atbm_void atbmwifi_update_filtering(struct atbmwifi_vif *priv)
{
int ret;
ATBM_BOOL ap_mode = 0;
ATBM_BOOL bssid_filtering = !priv->rx_filter.bssid;
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
struct wsm_beacon_filter_control bf_disabled={0};
struct wsm_beacon_filter_table bf_table_auto={0};
struct wsm_beacon_filter_control bf_auto={0};
bf_disabled.enabled = 0;
bf_disabled.bcn_count = 1;
bf_table_auto.numOfIEs = atbm_cpu_to_le32(2);
bf_table_auto.entry[0].ieId = ATBM_WLAN_EID_VENDOR_SPECIFIC;
bf_table_auto.entry[0].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
WSM_BEACON_FILTER_IE_HAS_APPEARED;
bf_table_auto.entry[0].oui[0] = 0x50;
bf_table_auto.entry[0].oui[1] = 0x6F;
bf_table_auto.entry[0].oui[2] = 0x9A;
bf_table_auto.entry[1].ieId = ATBM_WLAN_EID_HT_OPERATION;
bf_table_auto.entry[1].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED |
WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT |
WSM_BEACON_FILTER_IE_HAS_APPEARED;
bf_auto.enabled = WSM_BEACON_FILTER_ENABLE |
WSM_BEACON_FILTER_AUTO_ERP;
bf_auto.bcn_count = 1;
bf_auto.bcn_count = priv->bf_control.bcn_count;
if (priv->join_status == ATBMWIFI__JOIN_STATUS_PASSIVE)
return;
else if (priv->join_status == ATBMWIFI__JOIN_STATUS_MONITOR)
bssid_filtering = ATBM_FALSE;
if (atbmwifi_is_ap_mode(priv->iftype))
ap_mode = ATBM_TRUE;
/*
* When acting as p2p client being connected to p2p GO, in order to
* receive frames from a different p2p device, turn off bssid filter.
*
* WARNING: FW dependency!
* This can only be used with FW WSM371 and its successors.
* In that FW version even with bssid filter turned off,
* device will block most of the unwanted frames.
*/
//if (priv->vif && priv->vif->p2p)
//bssid_filtering = ATBM_FALSE;
ret = wsm_set_rx_filter(hw_priv, &priv->rx_filter, priv->if_id);
if (!ret && !ap_mode) {
if (ATBM_NL80211_IFTYPE_STATION != priv->iftype){
__atbmwifi_bf_configure(priv,&bf_table_auto);
}
ret = wsm_set_beacon_filter_table(hw_priv, &bf_table_auto,
priv->if_id);
}
if (!ret && !ap_mode) {
if (priv->disable_beacon_filter)
ret = wsm_beacon_filter_control(hw_priv,
&bf_disabled, priv->if_id);
else {
if (ATBM_NL80211_IFTYPE_STATION != priv->iftype)
ret = wsm_beacon_filter_control(hw_priv,
&priv->bf_control, priv->if_id);
else
ret = wsm_beacon_filter_control(hw_priv,
&bf_auto, priv->if_id);
}
}
if (!ret)
ret = wsm_set_bssid_filtering(hw_priv, bssid_filtering,
priv->if_id);
if (ret)
wifi_printk(WIFI_DBG_ERROR,"%s:fail=%d.\n",
__FUNCTION__, ret);
return;
}