rtl8188eu/hal/rtl8188e_rxdesc.c

343 lines
11 KiB
C
Raw Normal View History

/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTL8188E_REDESC_C_
#include <drv_conf.h>
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8188e_hal.h>
static s32 translate2dbm(u8 signal_strength_idx)
{
s32 signal_power; // in dBm.
// Translate to dBm (x=0.5y-95).
signal_power = (s32)((signal_strength_idx + 1) >> 1);
signal_power -= 95;
return signal_power;
}
static void process_rssi(struct adapter *padapter,union recv_frame *prframe)
{
u32 last_rssi, tmp_val;
struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
struct signal_stat * signal_stat = &padapter->recvpriv.signal_strength_data;
#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
//DBG_8192C("process_rssi=> pattrib->rssil(%d) signal_strength(%d)\n ",pattrib->RecvSignalPower,pattrib->signal_strength);
//if(pRfd->Status.bPacketToSelf || pRfd->Status.bPacketBeacon)
{
#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
if(signal_stat->update_req) {
signal_stat->total_num = 0;
signal_stat->total_val = 0;
signal_stat->update_req = 0;
}
signal_stat->total_num++;
signal_stat->total_val += pattrib->phy_info.SignalStrength;
signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
#else //CONFIG_NEW_SIGNAL_STAT_PROCESS
//Adapter->RxStats.RssiCalculateCnt++; //For antenna Test
if(padapter->recvpriv.signal_strength_data.total_num++ >= PHY_RSSI_SLID_WIN_MAX)
{
padapter->recvpriv.signal_strength_data.total_num = PHY_RSSI_SLID_WIN_MAX;
last_rssi = padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index];
padapter->recvpriv.signal_strength_data.total_val -= last_rssi;
}
padapter->recvpriv.signal_strength_data.total_val +=pattrib->phy_info.SignalStrength;
padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index++] = pattrib->phy_info.SignalStrength;
if(padapter->recvpriv.signal_strength_data.index >= PHY_RSSI_SLID_WIN_MAX)
padapter->recvpriv.signal_strength_data.index = 0;
tmp_val = padapter->recvpriv.signal_strength_data.total_val/padapter->recvpriv.signal_strength_data.total_num;
if(padapter->recvpriv.is_signal_dbg) {
padapter->recvpriv.signal_strength= padapter->recvpriv.signal_strength_dbg;
padapter->recvpriv.rssi=(s8)translate2dbm((u8)padapter->recvpriv.signal_strength_dbg);
} else {
padapter->recvpriv.signal_strength= tmp_val;
padapter->recvpriv.rssi=(s8)translate2dbm((u8)tmp_val);
}
RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("UI RSSI = %d, ui_rssi.TotalVal = %d, ui_rssi.TotalNum = %d\n", tmp_val, padapter->recvpriv.signal_strength_data.total_val,padapter->recvpriv.signal_strength_data.total_num));
#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
}
}// Process_UI_RSSI_8192C
static void process_link_qual(struct adapter *padapter,union recv_frame *prframe)
{
u32 last_evm=0, tmpVal;
struct rx_pkt_attrib *pattrib;
#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
struct signal_stat * signal_stat;
#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
if(prframe == NULL || padapter==NULL){
return;
}
pattrib = &prframe->u.hdr.attrib;
#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
signal_stat = &padapter->recvpriv.signal_qual_data;
#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
//DBG_8192C("process_link_qual=> pattrib->signal_qual(%d)\n ",pattrib->signal_qual);
#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
if(signal_stat->update_req) {
signal_stat->total_num = 0;
signal_stat->total_val = 0;
signal_stat->update_req = 0;
}
signal_stat->total_num++;
signal_stat->total_val += pattrib->phy_info.SignalQuality;
signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
#else //CONFIG_NEW_SIGNAL_STAT_PROCESS
if(pattrib->phy_info.SignalQuality != 0)
{
//
// 1. Record the general EVM to the sliding window.
//
if(padapter->recvpriv.signal_qual_data.total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX)
{
padapter->recvpriv.signal_qual_data.total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
last_evm = padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index];
padapter->recvpriv.signal_qual_data.total_val -= last_evm;
}
padapter->recvpriv.signal_qual_data.total_val += pattrib->phy_info.SignalQuality;
padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index++] = pattrib->phy_info.SignalQuality;
if(padapter->recvpriv.signal_qual_data.index >= PHY_LINKQUALITY_SLID_WIN_MAX)
padapter->recvpriv.signal_qual_data.index = 0;
RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Total SQ=%d pattrib->signal_qual= %d\n", padapter->recvpriv.signal_qual_data.total_val, pattrib->phy_info.SignalQuality));
// <1> Showed on UI for user, in percentage.
tmpVal = padapter->recvpriv.signal_qual_data.total_val/padapter->recvpriv.signal_qual_data.total_num;
padapter->recvpriv.signal_qual=(u8)tmpVal;
}
else
{
RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" pattrib->signal_qual =%d\n", pattrib->phy_info.SignalQuality));
}
#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
}
//void rtl8188e_process_phy_info(struct adapter *padapter, union recv_frame *prframe)
void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe)
{
union recv_frame *precvframe = (union recv_frame *)prframe;
//
// Check RSSI
//
process_rssi(padapter, precvframe);
//
// Check PWDB.
//
//process_PWDB(padapter, precvframe);
//UpdateRxSignalStatistics8192C(Adapter, pRfd);
//
// Check EVM
//
process_link_qual(padapter, precvframe);
}
void update_recvframe_attrib_88e(
union recv_frame *precvframe,
struct recv_stat *prxstat)
{
struct rx_pkt_attrib *pattrib;
struct recv_stat report;
PRXREPORT prxreport;
//struct recv_frame_hdr *phdr;
//phdr = &precvframe->u.hdr;
report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
prxreport = (PRXREPORT)&report;
pattrib = &precvframe->u.hdr.attrib;
_rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
pattrib->crc_err = (u8)((report.rxdw0 >> 14) & 0x1);;//(u8)prxreport->crc32;
// update rx report to recv_frame attribute
pattrib->pkt_rpt_type = (u8)((report.rxdw3 >> 14) & 0x3);//prxreport->rpt_sel;
if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
{
pattrib->pkt_len = (u16)(report.rxdw0 &0x00003fff);//(u16)prxreport->pktlen;
pattrib->drvinfo_sz = (u8)((report.rxdw0 >> 16) & 0xf) * 8;//(u8)(prxreport->drvinfosize << 3);
pattrib->physt = (u8)((report.rxdw0 >> 26) & 0x1);//(u8)prxreport->physt;
pattrib->bdecrypted = (report.rxdw0 & BIT(27))? 0:1;//(u8)(prxreport->swdec ? 0 : 1);
pattrib->encrypt = (u8)((report.rxdw0 >> 20) & 0x7);//(u8)prxreport->security;
pattrib->qos = (u8)((report.rxdw0 >> 23) & 0x1);//(u8)prxreport->qos;
pattrib->priority = (u8)((report.rxdw1 >> 8) & 0xf);//(u8)prxreport->tid;
pattrib->amsdu = (u8)((report.rxdw1 >> 13) & 0x1);//(u8)prxreport->amsdu;
pattrib->seq_num = (u16)(report.rxdw2 & 0x00000fff);//(u16)prxreport->seq;
pattrib->frag_num = (u8)((report.rxdw2 >> 12) & 0xf);//(u8)prxreport->frag;
pattrib->mfrag = (u8)((report.rxdw1 >> 27) & 0x1);//(u8)prxreport->mf;
pattrib->mdata = (u8)((report.rxdw1 >> 26) & 0x1);//(u8)prxreport->md;
pattrib->mcs_rate = (u8)(report.rxdw3 & 0x3f);//(u8)prxreport->rxmcs;
pattrib->rxht = (u8)((report.rxdw3 >> 6) & 0x1);//(u8)prxreport->rxht;
pattrib->icv_err = (u8)((report.rxdw0 >> 15) & 0x1);//(u8)prxreport->icverr;
pattrib->shift_sz = (u8)((report.rxdw0 >> 24) & 0x3);
}
else if(pattrib->pkt_rpt_type == TX_REPORT1)//CCX
{
pattrib->pkt_len = TX_RPT1_PKT_LEN;
pattrib->drvinfo_sz = 0;
}
else if(pattrib->pkt_rpt_type == TX_REPORT2)// TX RPT
{
pattrib->pkt_len =(u16)(report.rxdw0 & 0x3FF);//Rx length[9:0]
pattrib->drvinfo_sz = 0;
//
// Get TX report MAC ID valid.
//
pattrib->MacIDValidEntry[0] = report.rxdw4;
pattrib->MacIDValidEntry[1] = report.rxdw5;
}
else if(pattrib->pkt_rpt_type == HIS_REPORT)// USB HISR RPT
{
pattrib->pkt_len = (u16)(report.rxdw0 &0x00003fff);//(u16)prxreport->pktlen;
}
}
/*
* Notice:
* Before calling this function,
* precvframe->u.hdr.rx_data should be ready!
*/
void update_recvframe_phyinfo_88e(
union recv_frame *precvframe,
struct phy_stat *pphy_status)
{
struct adapter * padapter = precvframe->u.hdr.adapter;
struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
PODM_PHY_INFO_T pPHYInfo = (PODM_PHY_INFO_T)(&pattrib->phy_info);
u8 *wlanhdr;
ODM_PACKET_INFO_T pkt_info;
u8 *sa;
struct sta_priv *pstapriv;
struct sta_info *psta;
//_irqL irqL;
pkt_info.bPacketMatchBSSID =false;
pkt_info.bPacketToSelf = false;
pkt_info.bPacketBeacon = false;
wlanhdr = get_recvframe_data(precvframe);
pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) &&
!pattrib->icv_err && !pattrib->crc_err &&
_rtw_memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN));
pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && (_rtw_memcmp(get_da(wlanhdr), myid(&padapter->eeprompriv), ETH_ALEN));
pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && (GetFrameSubType(wlanhdr) == WIFI_BEACON);
if(pkt_info.bPacketBeacon){
if(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true){
sa = padapter->mlmepriv.cur_network.network.MacAddress;
}
else
sa = get_sa(wlanhdr);
} else{
sa = get_sa(wlanhdr);
}
pstapriv = &padapter->stapriv;
pkt_info.StationID = 0xFF;
psta = rtw_get_stainfo(pstapriv, sa);
if (psta)
{
pkt_info.StationID = psta->mac_id;
//DBG_8192C("%s ==> StationID(%d)\n",__FUNCTION__,pkt_info.StationID);
}
pkt_info.Rate = pattrib->mcs_rate;
//rtl8188e_query_rx_phy_status(precvframe, pphy_status);
//_enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
ODM_PhyStatusQuery(&pHalData->odmpriv,pPHYInfo,(u8 *)pphy_status,&(pkt_info));
//_exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
precvframe->u.hdr.psta = NULL;
if (pkt_info.bPacketMatchBSSID &&
(check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true))
{
if (psta)
{
precvframe->u.hdr.psta = psta;
rtl8188e_process_phy_info(padapter, precvframe);
}
}
else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon)
{
if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true)
{
if (psta)
{
precvframe->u.hdr.psta = psta;
}
}
rtl8188e_process_phy_info(padapter, precvframe);
}
}