staging: r8188eu: introduce new hal dir for RTL8188eu driver

This patchset is split in order to keep the file sizes down. This hal
directory is part of the newer/better driver from GitHub modified by
Larry Finger. Import this as the basis for all future work going
forward.

Suggested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
Link: https://lore.kernel.org/r/20210727232219.2948-3-phil@philpotter.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Phillip Potter 2021-07-28 00:22:15 +01:00 committed by Greg Kroah-Hartman
parent 15865124fe
commit 8cd574e6af
30 changed files with 18489 additions and 0 deletions

View File

@ -0,0 +1,86 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "Hal8188EPwrSeq.h"
#include <rtl8188e_hal.h>
/*
drivers should parse below arrays and do the corresponding actions
*/
/* 3 Power on Array */
struct wl_pwr_cfg rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_CARDEMU_TO_ACT
RTL8188E_TRANS_END
};
/* 3Radio off Array */
struct wl_pwr_cfg rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_END
};
/* 3Card Disable Array */
struct wl_pwr_cfg rtl8188E_card_disable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_CARDDIS
RTL8188E_TRANS_END
};
/* 3 Card Enable Array */
struct wl_pwr_cfg rtl8188E_card_enable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_CARDDIS_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_ACT
RTL8188E_TRANS_END
};
/* 3Suspend Array */
struct wl_pwr_cfg rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_SUS
RTL8188E_TRANS_END
};
/* 3 Resume Array */
struct wl_pwr_cfg rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_SUS_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_ACT
RTL8188E_TRANS_END
};
/* 3HWPDN Array */
struct wl_pwr_cfg rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_PDN
RTL8188E_TRANS_END
};
/* 3 Enter LPS */
struct wl_pwr_cfg rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS + RTL8188E_TRANS_END_STEPS] = {
/* FW behavior */
RTL8188E_TRANS_ACT_TO_LPS
RTL8188E_TRANS_END
};
/* 3 Leave LPS */
struct wl_pwr_cfg rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS] = {
/* FW behavior */
RTL8188E_TRANS_LPS_TO_ACT
RTL8188E_TRANS_END
};

View File

@ -0,0 +1,760 @@
/*++
Copyright (c) Realtek Semiconductor Corp. All rights reserved.
Module Name:
RateAdaptive.c
Abstract:
Implement Rate Adaptive functions for common operations.
Major Change History:
When Who What
---------- --------------- -------------------------------
2011-08-12 Page Create.
--*/
#include "odm_precomp.h"
/* Rate adaptive parameters */
static u8 RETRY_PENALTY[PERENTRY][RETRYSIZE+1] = {
{5, 4, 3, 2, 0, 3}, /* 92 , idx = 0 */
{6, 5, 4, 3, 0, 4}, /* 86 , idx = 1 */
{6, 5, 4, 2, 0, 4}, /* 81 , idx = 2 */
{8, 7, 6, 4, 0, 6}, /* 75 , idx = 3 */
{10, 9, 8, 6, 0, 8}, /* 71 , idx = 4 */
{10, 9, 8, 4, 0, 8}, /* 66 , idx = 5 */
{10, 9, 8, 2, 0, 8}, /* 62 , idx = 6 */
{10, 9, 8, 0, 0, 8}, /* 59 , idx = 7 */
{18, 17, 16, 8, 0, 16}, /* 53 , idx = 8 */
{26, 25, 24, 16, 0, 24}, /* 50 , idx = 9 */
{34, 33, 32, 24, 0, 32}, /* 47 , idx = 0x0a */
{34, 31, 28, 20, 0, 32}, /* 43 , idx = 0x0b */
{34, 31, 27, 18, 0, 32}, /* 40 , idx = 0x0c */
{34, 31, 26, 16, 0, 32}, /* 37 , idx = 0x0d */
{34, 30, 22, 16, 0, 32}, /* 32 , idx = 0x0e */
{34, 30, 24, 16, 0, 32}, /* 26 , idx = 0x0f */
{49, 46, 40, 16, 0, 48}, /* 20 , idx = 0x10 */
{49, 45, 32, 0, 0, 48}, /* 17 , idx = 0x11 */
{49, 45, 22, 18, 0, 48}, /* 15 , idx = 0x12 */
{49, 40, 24, 16, 0, 48}, /* 12 , idx = 0x13 */
{49, 32, 18, 12, 0, 48}, /* 9 , idx = 0x14 */
{49, 22, 18, 14, 0, 48}, /* 6 , idx = 0x15 */
{49, 16, 16, 0, 0, 48}
}; /* 3, idx = 0x16 */
static u8 PT_PENALTY[RETRYSIZE+1] = {34, 31, 30, 24, 0, 32};
/* wilson modify */
static u8 RETRY_PENALTY_IDX[2][RATESIZE] = {
{4, 4, 4, 5, 4, 4, 5, 7, 7, 7, 8, 0x0a, /* SS>TH */
4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f}, /* 0329 R01 */
{0x0a, 0x0a, 0x0b, 0x0c, 0x0a,
0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x14, /* SS<TH */
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x15,
9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13}
};
static u8 RETRY_PENALTY_UP_IDX[RATESIZE] = {
0x0c, 0x0d, 0x0d, 0x0f, 0x0d, 0x0e,
0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14, /* SS>TH */
0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15,
0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15};
static u8 RSSI_THRESHOLD[RATESIZE] = {
0, 0, 0, 0,
0, 0, 0, 0, 0, 0x24, 0x26, 0x2a,
0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a,
0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c};
static u16 N_THRESHOLD_HIGH[RATESIZE] = {
4, 4, 8, 16,
24, 36, 48, 72, 96, 144, 192, 216,
60, 80, 100, 160, 240, 400, 560, 640,
300, 320, 480, 720, 1000, 1200, 1600, 2000};
static u16 N_THRESHOLD_LOW[RATESIZE] = {
2, 2, 4, 8,
12, 18, 24, 36, 48, 72, 96, 108,
30, 40, 50, 80, 120, 200, 280, 320,
150, 160, 240, 360, 500, 600, 800, 1000};
static u8 DROPING_NECESSARY[RATESIZE] = {
1, 1, 1, 1,
1, 2, 3, 4, 5, 6, 7, 8,
1, 2, 3, 4, 5, 6, 7, 8,
5, 6, 7, 8, 9, 10, 11, 12};
static u8 PendingForRateUpFail[5] = {2, 10, 24, 40, 60};
static u16 DynamicTxRPTTiming[6] = {
0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12 , 0x927c}; /* 200ms-1200ms */
/* End Rate adaptive parameters */
static void odm_SetTxRPTTiming_8188E(
struct odm_dm_struct *dm_odm,
struct odm_ra_info *pRaInfo,
u8 extend
)
{
u8 idx = 0;
for (idx = 0; idx < 5; idx++)
if (DynamicTxRPTTiming[idx] == pRaInfo->RptTime)
break;
if (extend == 0) { /* back to default timing */
idx = 0; /* 200ms */
} else if (extend == 1) {/* increase the timing */
idx += 1;
if (idx > 5)
idx = 5;
} else if (extend == 2) {/* decrease the timing */
if (idx != 0)
idx -= 1;
}
pRaInfo->RptTime = DynamicTxRPTTiming[idx];
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("pRaInfo->RptTime = 0x%x\n", pRaInfo->RptTime));
}
static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
{
u8 RateID, LowestRate, HighestRate;
u8 i;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_RateDown_8188E()\n"));
if (NULL == pRaInfo) {
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_RateDown_8188E(): pRaInfo is NULL\n"));
return -1;
}
RateID = pRaInfo->PreRate;
LowestRate = pRaInfo->LowestRate;
HighestRate = pRaInfo->HighestRate;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" RateID =%d LowestRate =%d HighestRate =%d RateSGI =%d\n",
RateID, LowestRate, HighestRate, pRaInfo->RateSGI));
if (RateID > HighestRate) {
RateID = HighestRate;
} else if (pRaInfo->RateSGI) {
pRaInfo->RateSGI = 0;
} else if (RateID > LowestRate) {
if (RateID > 0) {
for (i = RateID-1; i > LowestRate; i--) {
if (pRaInfo->RAUseRate & BIT(i)) {
RateID = i;
goto RateDownFinish;
}
}
}
} else if (RateID <= LowestRate) {
RateID = LowestRate;
}
RateDownFinish:
if (pRaInfo->RAWaitingCounter == 1) {
pRaInfo->RAWaitingCounter += 1;
pRaInfo->RAPendingCounter += 1;
} else if (pRaInfo->RAWaitingCounter == 0) {
;
} else {
pRaInfo->RAWaitingCounter = 0;
pRaInfo->RAPendingCounter = 0;
}
if (pRaInfo->RAPendingCounter >= 4)
pRaInfo->RAPendingCounter = 4;
pRaInfo->DecisionRate = RateID;
odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 2);
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Rate down, RPT Timing default\n"));
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("RAWaitingCounter %d, RAPendingCounter %d", pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Rate down to RateID %d RateSGI %d\n", RateID, pRaInfo->RateSGI));
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<===== odm_RateDown_8188E()\n"));
return 0;
}
static int odm_RateUp_8188E(
struct odm_dm_struct *dm_odm,
struct odm_ra_info *pRaInfo
)
{
u8 RateID, HighestRate;
u8 i;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_RateUp_8188E()\n"));
if (NULL == pRaInfo) {
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_RateUp_8188E(): pRaInfo is NULL\n"));
return -1;
}
RateID = pRaInfo->PreRate;
HighestRate = pRaInfo->HighestRate;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" RateID =%d HighestRate =%d\n",
RateID, HighestRate));
if (pRaInfo->RAWaitingCounter == 1) {
pRaInfo->RAWaitingCounter = 0;
pRaInfo->RAPendingCounter = 0;
} else if (pRaInfo->RAWaitingCounter > 1) {
pRaInfo->PreRssiStaRA = pRaInfo->RssiStaRA;
goto RateUpfinish;
}
odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 0);
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("odm_RateUp_8188E():Decrease RPT Timing\n"));
if (RateID < HighestRate) {
for (i = RateID+1; i <= HighestRate; i++) {
if (pRaInfo->RAUseRate & BIT(i)) {
RateID = i;
goto RateUpfinish;
}
}
} else if (RateID == HighestRate) {
if (pRaInfo->SGIEnable && (pRaInfo->RateSGI != 1))
pRaInfo->RateSGI = 1;
else if ((pRaInfo->SGIEnable) != 1)
pRaInfo->RateSGI = 0;
} else {
RateID = HighestRate;
}
RateUpfinish:
if (pRaInfo->RAWaitingCounter == (4+PendingForRateUpFail[pRaInfo->RAPendingCounter]))
pRaInfo->RAWaitingCounter = 0;
else
pRaInfo->RAWaitingCounter++;
pRaInfo->DecisionRate = RateID;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("Rate up to RateID %d\n", RateID));
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("RAWaitingCounter %d, RAPendingCounter %d", pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<===== odm_RateUp_8188E()\n"));
return 0;
}
static void odm_ResetRaCounter_8188E(struct odm_ra_info *pRaInfo)
{
u8 RateID;
RateID = pRaInfo->DecisionRate;
pRaInfo->NscUp = (N_THRESHOLD_HIGH[RateID]+N_THRESHOLD_LOW[RateID])>>1;
pRaInfo->NscDown = (N_THRESHOLD_HIGH[RateID]+N_THRESHOLD_LOW[RateID])>>1;
}
static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
struct odm_ra_info *pRaInfo
)
{
u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0;
/* u32 pool_retry; */
static u8 DynamicTxRPTTimingCounter;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("=====>odm_RateDecision_8188E()\n"));
if (pRaInfo->Active && (pRaInfo->TOTAL > 0)) { /* STA used and data packet exits */
if ((pRaInfo->RssiStaRA < (pRaInfo->PreRssiStaRA - 3)) ||
(pRaInfo->RssiStaRA > (pRaInfo->PreRssiStaRA + 3))) {
pRaInfo->RAWaitingCounter = 0;
pRaInfo->RAPendingCounter = 0;
}
/* Start RA decision */
if (pRaInfo->PreRate > pRaInfo->HighestRate)
RateID = pRaInfo->HighestRate;
else
RateID = pRaInfo->PreRate;
if (pRaInfo->RssiStaRA > RSSI_THRESHOLD[RateID])
RtyPtID = 0;
else
RtyPtID = 1;
PenaltyID1 = RETRY_PENALTY_IDX[RtyPtID][RateID]; /* TODO by page */
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" NscDown init is %d\n", pRaInfo->NscDown));
pRaInfo->NscDown += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID1][0];
pRaInfo->NscDown += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID1][1];
pRaInfo->NscDown += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID1][2];
pRaInfo->NscDown += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID1][3];
pRaInfo->NscDown += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID1][4];
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" NscDown is %d, total*penalty[5] is %d\n",
pRaInfo->NscDown, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])));
if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]))
pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5];
else
pRaInfo->NscDown = 0;
/* rate up */
PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID];
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" NscUp init is %d\n", pRaInfo->NscUp));
pRaInfo->NscUp += pRaInfo->RTY[0] * RETRY_PENALTY[PenaltyID2][0];
pRaInfo->NscUp += pRaInfo->RTY[1] * RETRY_PENALTY[PenaltyID2][1];
pRaInfo->NscUp += pRaInfo->RTY[2] * RETRY_PENALTY[PenaltyID2][2];
pRaInfo->NscUp += pRaInfo->RTY[3] * RETRY_PENALTY[PenaltyID2][3];
pRaInfo->NscUp += pRaInfo->RTY[4] * RETRY_PENALTY[PenaltyID2][4];
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
("NscUp is %d, total*up[5] is %d\n",
pRaInfo->NscUp, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5])));
if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]))
pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5];
else
pRaInfo->NscUp = 0;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE|ODM_COMP_INIT, ODM_DBG_LOUD,
(" RssiStaRa = %d RtyPtID =%d PenaltyID1 = 0x%x PenaltyID2 = 0x%x RateID =%d NscDown =%d NscUp =%d SGI =%d\n",
pRaInfo->RssiStaRA, RtyPtID, PenaltyID1, PenaltyID2, RateID, pRaInfo->NscDown, pRaInfo->NscUp, pRaInfo->RateSGI));
if ((pRaInfo->NscDown < N_THRESHOLD_LOW[RateID]) ||
(pRaInfo->DROP > DROPING_NECESSARY[RateID]))
odm_RateDown_8188E(dm_odm, pRaInfo);
else if (pRaInfo->NscUp > N_THRESHOLD_HIGH[RateID])
odm_RateUp_8188E(dm_odm, pRaInfo);
if (pRaInfo->DecisionRate > pRaInfo->HighestRate)
pRaInfo->DecisionRate = pRaInfo->HighestRate;
if ((pRaInfo->DecisionRate) == (pRaInfo->PreRate))
DynamicTxRPTTimingCounter += 1;
else
DynamicTxRPTTimingCounter = 0;
if (DynamicTxRPTTimingCounter >= 4) {
odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 1);
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
ODM_DBG_LOUD, ("<===== Rate don't change 4 times, Extend RPT Timing\n"));
DynamicTxRPTTimingCounter = 0;
}
pRaInfo->PreRate = pRaInfo->DecisionRate; /* YJ, add, 120120 */
odm_ResetRaCounter_8188E(pRaInfo);
}
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, ("<===== odm_RateDecision_8188E()\n"));
}
static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
{ /* Wilson 2011/10/26 */
u32 MaskFromReg;
s8 i;
switch (pRaInfo->RateID) {
case RATR_INX_WIRELESS_NGB:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff015;
break;
case RATR_INX_WIRELESS_NG:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff010;
break;
case RATR_INX_WIRELESS_NB:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff005;
break;
case RATR_INX_WIRELESS_N:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0f8ff000;
break;
case RATR_INX_WIRELESS_GB:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x00000ff5;
break;
case RATR_INX_WIRELESS_G:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x00000ff0;
break;
case RATR_INX_WIRELESS_B:
pRaInfo->RAUseRate = (pRaInfo->RateMask)&0x0000000d;
break;
case 12:
MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR0);
pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
break;
case 13:
MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR1);
pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
break;
case 14:
MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR2);
pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
break;
case 15:
MaskFromReg = ODM_Read4Byte(dm_odm, REG_ARFR3);
pRaInfo->RAUseRate = (pRaInfo->RateMask)&MaskFromReg;
break;
default:
pRaInfo->RAUseRate = (pRaInfo->RateMask);
break;
}
/* Highest rate */
if (pRaInfo->RAUseRate) {
for (i = RATESIZE; i >= 0; i--) {
if ((pRaInfo->RAUseRate)&BIT(i)) {
pRaInfo->HighestRate = i;
break;
}
}
} else {
pRaInfo->HighestRate = 0;
}
/* Lowest rate */
if (pRaInfo->RAUseRate) {
for (i = 0; i < RATESIZE; i++) {
if ((pRaInfo->RAUseRate) & BIT(i)) {
pRaInfo->LowestRate = i;
break;
}
}
} else {
pRaInfo->LowestRate = 0;
}
if (pRaInfo->HighestRate > 0x13)
pRaInfo->PTModeSS = 3;
else if (pRaInfo->HighestRate > 0x0b)
pRaInfo->PTModeSS = 2;
else if (pRaInfo->HighestRate > 0x03)
pRaInfo->PTModeSS = 1;
else
pRaInfo->PTModeSS = 0;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("ODM_ARFBRefresh_8188E(): PTModeSS =%d\n", pRaInfo->PTModeSS));
if (pRaInfo->DecisionRate > pRaInfo->HighestRate)
pRaInfo->DecisionRate = pRaInfo->HighestRate;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("ODM_ARFBRefresh_8188E(): RateID =%d RateMask =%8.8x RAUseRate =%8.8x HighestRate =%d, DecisionRate =%d\n",
pRaInfo->RateID, pRaInfo->RateMask, pRaInfo->RAUseRate, pRaInfo->HighestRate, pRaInfo->DecisionRate));
return 0;
}
static void odm_PTTryState_8188E(struct odm_ra_info *pRaInfo)
{
pRaInfo->PTTryState = 0;
switch (pRaInfo->PTModeSS) {
case 3:
if (pRaInfo->DecisionRate >= 0x19)
pRaInfo->PTTryState = 1;
break;
case 2:
if (pRaInfo->DecisionRate >= 0x11)
pRaInfo->PTTryState = 1;
break;
case 1:
if (pRaInfo->DecisionRate >= 0x0a)
pRaInfo->PTTryState = 1;
break;
case 0:
if (pRaInfo->DecisionRate >= 0x03)
pRaInfo->PTTryState = 1;
break;
default:
pRaInfo->PTTryState = 0;
break;
}
if (pRaInfo->RssiStaRA < 48) {
pRaInfo->PTStage = 0;
} else if (pRaInfo->PTTryState == 1) {
if ((pRaInfo->PTStopCount >= 10) ||
(pRaInfo->PTPreRssi > pRaInfo->RssiStaRA + 5) ||
(pRaInfo->PTPreRssi < pRaInfo->RssiStaRA - 5) ||
(pRaInfo->DecisionRate != pRaInfo->PTPreRate)) {
if (pRaInfo->PTStage == 0)
pRaInfo->PTStage = 1;
else if (pRaInfo->PTStage == 1)
pRaInfo->PTStage = 3;
else
pRaInfo->PTStage = 5;
pRaInfo->PTPreRssi = pRaInfo->RssiStaRA;
pRaInfo->PTStopCount = 0;
} else {
pRaInfo->RAstage = 0;
pRaInfo->PTStopCount++;
}
} else {
pRaInfo->PTStage = 0;
pRaInfo->RAstage = 0;
}
pRaInfo->PTPreRate = pRaInfo->DecisionRate;
}
static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo)
{
u8 j;
u8 temp_stage;
u32 numsc;
u32 num_total;
u8 stage_id;
numsc = 0;
num_total = pRaInfo->TOTAL * PT_PENALTY[5];
for (j = 0; j <= 4; j++) {
numsc += pRaInfo->RTY[j] * PT_PENALTY[j];
if (numsc > num_total)
break;
}
j = j >> 1;
temp_stage = (pRaInfo->PTStage + 1) >> 1;
if (temp_stage > j)
stage_id = temp_stage-j;
else
stage_id = 0;
pRaInfo->PTSmoothFactor = (pRaInfo->PTSmoothFactor>>1) + (pRaInfo->PTSmoothFactor>>2) + stage_id*16+2;
if (pRaInfo->PTSmoothFactor > 192)
pRaInfo->PTSmoothFactor = 192;
stage_id = pRaInfo->PTSmoothFactor >> 6;
temp_stage = stage_id*2;
if (temp_stage != 0)
temp_stage -= 1;
if (pRaInfo->DROP > 3)
temp_stage = 0;
pRaInfo->PTStage = temp_stage;
}
static void
odm_RATxRPTTimerSetting(
struct odm_dm_struct *dm_odm,
u16 minRptTime
)
{
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, (" =====>odm_RATxRPTTimerSetting()\n"));
if (dm_odm->CurrminRptTime != minRptTime) {
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
(" CurrminRptTime = 0x%04x minRptTime = 0x%04x\n", dm_odm->CurrminRptTime, minRptTime));
rtw_rpt_timer_cfg_cmd(dm_odm->Adapter, minRptTime);
dm_odm->CurrminRptTime = minRptTime;
}
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE, (" <===== odm_RATxRPTTimerSetting()\n"));
}
void
ODM_RASupport_Init(
struct odm_dm_struct *dm_odm
)
{
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>ODM_RASupport_Init()\n"));
/* 2012/02/14 MH Be noticed, the init must be after IC type is recognized!!!!! */
if (dm_odm->SupportICType == ODM_RTL8188E)
dm_odm->RaSupport88E = true;
}
int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid)
{
struct odm_ra_info *pRaInfo = &dm_odm->RAInfo[macid];
u8 WirelessMode = 0xFF; /* invalid value */
u8 max_rate_idx = 0x13; /* MCS7 */
if (dm_odm->pWirelessMode != NULL)
WirelessMode = *(dm_odm->pWirelessMode);
if (WirelessMode != 0xFF) {
if (WirelessMode & ODM_WM_N24G)
max_rate_idx = 0x13;
else if (WirelessMode & ODM_WM_G)
max_rate_idx = 0x0b;
else if (WirelessMode & ODM_WM_B)
max_rate_idx = 0x03;
}
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("ODM_RAInfo_Init(): WirelessMode:0x%08x , max_raid_idx:0x%02x\n",
WirelessMode, max_rate_idx));
pRaInfo->DecisionRate = max_rate_idx;
pRaInfo->PreRate = max_rate_idx;
pRaInfo->HighestRate = max_rate_idx;
pRaInfo->LowestRate = 0;
pRaInfo->RateID = 0;
pRaInfo->RateMask = 0xffffffff;
pRaInfo->RssiStaRA = 0;
pRaInfo->PreRssiStaRA = 0;
pRaInfo->SGIEnable = 0;
pRaInfo->RAUseRate = 0xffffffff;
pRaInfo->NscDown = (N_THRESHOLD_HIGH[0x13]+N_THRESHOLD_LOW[0x13])/2;
pRaInfo->NscUp = (N_THRESHOLD_HIGH[0x13]+N_THRESHOLD_LOW[0x13])/2;
pRaInfo->RateSGI = 0;
pRaInfo->Active = 1; /* Active is not used at present. by page, 110819 */
pRaInfo->RptTime = 0x927c;
pRaInfo->DROP = 0;
pRaInfo->RTY[0] = 0;
pRaInfo->RTY[1] = 0;
pRaInfo->RTY[2] = 0;
pRaInfo->RTY[3] = 0;
pRaInfo->RTY[4] = 0;
pRaInfo->TOTAL = 0;
pRaInfo->RAWaitingCounter = 0;
pRaInfo->RAPendingCounter = 0;
pRaInfo->PTActive = 1; /* Active when this STA is use */
pRaInfo->PTTryState = 0;
pRaInfo->PTStage = 5; /* Need to fill into HW_PWR_STATUS */
pRaInfo->PTSmoothFactor = 192;
pRaInfo->PTStopCount = 0;
pRaInfo->PTPreRate = 0;
pRaInfo->PTPreRssi = 0;
pRaInfo->PTModeSS = 0;
pRaInfo->RAstage = 0;
return 0;
}
int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm)
{
u8 macid = 0;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>\n"));
dm_odm->CurrminRptTime = 0;
for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++)
ODM_RAInfo_Init(dm_odm, macid);
return 0;
}
u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 macid)
{
if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return 0;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
("macid =%d SGI =%d\n", macid, dm_odm->RAInfo[macid].RateSGI));
return dm_odm->RAInfo[macid].RateSGI;
}
u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid)
{
u8 DecisionRate = 0;
if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return 0;
DecisionRate = (dm_odm->RAInfo[macid].DecisionRate);
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" macid =%d DecisionRate = 0x%x\n", macid, DecisionRate));
return DecisionRate;
}
u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid)
{
u8 PTStage = 5;
if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return 0;
PTStage = (dm_odm->RAInfo[macid].PTStage);
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
("macid =%d PTStage = 0x%x\n", macid, PTStage));
return PTStage;
}
void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 RateID, u32 RateMask, u8 SGIEnable)
{
struct odm_ra_info *pRaInfo = NULL;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("macid =%d RateID = 0x%x RateMask = 0x%x SGIEnable =%d\n",
macid, RateID, RateMask, SGIEnable));
if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return;
pRaInfo = &(dm_odm->RAInfo[macid]);
pRaInfo->RateID = RateID;
pRaInfo->RateMask = RateMask;
pRaInfo->SGIEnable = SGIEnable;
odm_ARFBRefresh_8188E(dm_odm, pRaInfo);
}
void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
{
struct odm_ra_info *pRaInfo = NULL;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
(" macid =%d Rssi =%d\n", macid, Rssi));
if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return;
pRaInfo = &(dm_odm->RAInfo[macid]);
pRaInfo->RssiStaRA = Rssi;
}
void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime)
{
ODM_Write2Byte(dm_odm, REG_TX_RPT_TIME, minRptTime);
}
void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1)
{
struct odm_ra_info *pRAInfo = NULL;
u8 MacId = 0;
u8 *pBuffer = NULL;
u32 valid = 0, ItemNum = 0;
u16 minRptTime = 0x927c;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("=====>ODM_RA_TxRPT2Handle_8188E(): valid0 =%d valid1 =%d BufferLength =%d\n",
macid_entry0, macid_entry1, TxRPT_Len));
ItemNum = TxRPT_Len >> 3;
pBuffer = TxRPT_Buf;
do {
if (MacId >= ASSOCIATE_ENTRY_NUM)
valid = 0;
else if (MacId >= 32)
valid = (1 << (MacId - 32)) & macid_entry1;
else
valid = (1 << MacId) & macid_entry0;
pRAInfo = &(dm_odm->RAInfo[MacId]);
if (valid) {
pRAInfo->RTY[0] = (u16)GET_TX_REPORT_TYPE1_RERTY_0(pBuffer);
pRAInfo->RTY[1] = (u16)GET_TX_REPORT_TYPE1_RERTY_1(pBuffer);
pRAInfo->RTY[2] = (u16)GET_TX_REPORT_TYPE1_RERTY_2(pBuffer);
pRAInfo->RTY[3] = (u16)GET_TX_REPORT_TYPE1_RERTY_3(pBuffer);
pRAInfo->RTY[4] = (u16)GET_TX_REPORT_TYPE1_RERTY_4(pBuffer);
pRAInfo->DROP = (u16)GET_TX_REPORT_TYPE1_DROP_0(pBuffer);
pRAInfo->TOTAL = pRAInfo->RTY[0] + pRAInfo->RTY[1] +
pRAInfo->RTY[2] + pRAInfo->RTY[3] +
pRAInfo->RTY[4] + pRAInfo->DROP;
if (pRAInfo->TOTAL != 0) {
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("macid =%d Total =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d D0 =%d valid0 =%x valid1 =%x\n",
MacId, pRAInfo->TOTAL,
pRAInfo->RTY[0], pRAInfo->RTY[1],
pRAInfo->RTY[2], pRAInfo->RTY[3],
pRAInfo->RTY[4], pRAInfo->DROP,
macid_entry0 , macid_entry1));
if (pRAInfo->PTActive) {
if (pRAInfo->RAstage < 5)
odm_RateDecision_8188E(dm_odm, pRAInfo);
else if (pRAInfo->RAstage == 5) /* Power training try state */
odm_PTTryState_8188E(pRAInfo);
else /* RAstage == 6 */
odm_PTDecision_8188E(pRAInfo);
/* Stage_RA counter */
if (pRAInfo->RAstage <= 5)
pRAInfo->RAstage++;
else
pRAInfo->RAstage = 0;
} else {
odm_RateDecision_8188E(dm_odm, pRAInfo);
}
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("macid =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d drop =%d valid0 =%x RateID =%d SGI =%d\n",
MacId,
pRAInfo->RTY[0],
pRAInfo->RTY[1],
pRAInfo->RTY[2],
pRAInfo->RTY[3],
pRAInfo->RTY[4],
pRAInfo->DROP,
macid_entry0,
pRAInfo->DecisionRate,
pRAInfo->RateSGI));
} else {
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, (" TOTAL = 0!!!!\n"));
}
}
if (minRptTime > pRAInfo->RptTime)
minRptTime = pRAInfo->RptTime;
pBuffer += TX_RPT2_ITEM_SIZE;
MacId++;
} while (MacId < ItemNum);
odm_RATxRPTTimerSetting(dm_odm, minRptTime);
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("<===== ODM_RA_TxRPT2Handle_8188E()\n"));
}

View File

@ -0,0 +1,720 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
#include <rtw_iol.h>
#define read_next_pair(array, v1, v2, i) \
do { \
i += 2; \
v1 = array[i]; \
v2 = array[i+1]; \
} while (0)
static bool CheckCondition(const u32 condition, const u32 hex)
{
u32 _board = (hex & 0x000000FF);
u32 _interface = (hex & 0x0000FF00) >> 8;
u32 _platform = (hex & 0x00FF0000) >> 16;
u32 cond = condition;
if (condition == 0xCDCDCDCD)
return true;
cond = condition & 0x000000FF;
if ((_board == cond) && cond != 0x00)
return false;
cond = condition & 0x0000FF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = condition & 0x00FF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
/******************************************************************************
* AGC_TAB_1T.TXT
******************************************************************************/
static u32 array_agc_tab_1t_8188e[] = {
0xC78, 0xFB000001,
0xC78, 0xFB010001,
0xC78, 0xFB020001,
0xC78, 0xFB030001,
0xC78, 0xFB040001,
0xC78, 0xFB050001,
0xC78, 0xFA060001,
0xC78, 0xF9070001,
0xC78, 0xF8080001,
0xC78, 0xF7090001,
0xC78, 0xF60A0001,
0xC78, 0xF50B0001,
0xC78, 0xF40C0001,
0xC78, 0xF30D0001,
0xC78, 0xF20E0001,
0xC78, 0xF10F0001,
0xC78, 0xF0100001,
0xC78, 0xEF110001,
0xC78, 0xEE120001,
0xC78, 0xED130001,
0xC78, 0xEC140001,
0xC78, 0xEB150001,
0xC78, 0xEA160001,
0xC78, 0xE9170001,
0xC78, 0xE8180001,
0xC78, 0xE7190001,
0xC78, 0xE61A0001,
0xC78, 0xE51B0001,
0xC78, 0xE41C0001,
0xC78, 0xE31D0001,
0xC78, 0xE21E0001,
0xC78, 0xE11F0001,
0xC78, 0x8A200001,
0xC78, 0x89210001,
0xC78, 0x88220001,
0xC78, 0x87230001,
0xC78, 0x86240001,
0xC78, 0x85250001,
0xC78, 0x84260001,
0xC78, 0x83270001,
0xC78, 0x82280001,
0xC78, 0x6B290001,
0xC78, 0x6A2A0001,
0xC78, 0x692B0001,
0xC78, 0x682C0001,
0xC78, 0x672D0001,
0xC78, 0x662E0001,
0xC78, 0x652F0001,
0xC78, 0x64300001,
0xC78, 0x63310001,
0xC78, 0x62320001,
0xC78, 0x61330001,
0xC78, 0x46340001,
0xC78, 0x45350001,
0xC78, 0x44360001,
0xC78, 0x43370001,
0xC78, 0x42380001,
0xC78, 0x41390001,
0xC78, 0x403A0001,
0xC78, 0x403B0001,
0xC78, 0x403C0001,
0xC78, 0x403D0001,
0xC78, 0x403E0001,
0xC78, 0x403F0001,
0xC78, 0xFB400001,
0xC78, 0xFB410001,
0xC78, 0xFB420001,
0xC78, 0xFB430001,
0xC78, 0xFB440001,
0xC78, 0xFB450001,
0xC78, 0xFB460001,
0xC78, 0xFB470001,
0xC78, 0xFB480001,
0xC78, 0xFA490001,
0xC78, 0xF94A0001,
0xC78, 0xF84B0001,
0xC78, 0xF74C0001,
0xC78, 0xF64D0001,
0xC78, 0xF54E0001,
0xC78, 0xF44F0001,
0xC78, 0xF3500001,
0xC78, 0xF2510001,
0xC78, 0xF1520001,
0xC78, 0xF0530001,
0xC78, 0xEF540001,
0xC78, 0xEE550001,
0xC78, 0xED560001,
0xC78, 0xEC570001,
0xC78, 0xEB580001,
0xC78, 0xEA590001,
0xC78, 0xE95A0001,
0xC78, 0xE85B0001,
0xC78, 0xE75C0001,
0xC78, 0xE65D0001,
0xC78, 0xE55E0001,
0xC78, 0xE45F0001,
0xC78, 0xE3600001,
0xC78, 0xE2610001,
0xC78, 0xC3620001,
0xC78, 0xC2630001,
0xC78, 0xC1640001,
0xC78, 0x8B650001,
0xC78, 0x8A660001,
0xC78, 0x89670001,
0xC78, 0x88680001,
0xC78, 0x87690001,
0xC78, 0x866A0001,
0xC78, 0x856B0001,
0xC78, 0x846C0001,
0xC78, 0x676D0001,
0xC78, 0x666E0001,
0xC78, 0x656F0001,
0xC78, 0x64700001,
0xC78, 0x63710001,
0xC78, 0x62720001,
0xC78, 0x61730001,
0xC78, 0x60740001,
0xC78, 0x46750001,
0xC78, 0x45760001,
0xC78, 0x44770001,
0xC78, 0x43780001,
0xC78, 0x42790001,
0xC78, 0x417A0001,
0xC78, 0x407B0001,
0xC78, 0x407C0001,
0xC78, 0x407D0001,
0xC78, 0x407E0001,
0xC78, 0x407F0001,
};
enum HAL_STATUS ODM_ReadAndConfig_AGC_TAB_1T_8188E(struct odm_dm_struct *dm_odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = dm_odm->SupportPlatform;
u8 interfaceValue = dm_odm->SupportInterface;
u8 board = dm_odm->BoardType;
u32 arraylen = sizeof(array_agc_tab_1t_8188e)/sizeof(u32);
u32 *array = array_agc_tab_1t_8188e;
bool biol = false;
struct adapter *adapter = dm_odm->Adapter;
struct xmit_frame *pxmit_frame = NULL;
u8 bndy_cnt = 1;
enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
biol = rtw_IOL_applied(adapter);
if (biol) {
pxmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
if (pxmit_frame == NULL) {
pr_info("rtw_IOL_accquire_xmit_frame failed\n");
return HAL_STATUS_FAILURE;
}
}
for (i = 0; i < arraylen; i += 2) {
u32 v1 = array[i];
u32 v2 = array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
} else {
odm_ConfigBB_AGC_8188E(dm_odm, v1, bMaskDWord, v2);
}
continue;
} else {
/* This line is the start line of branch. */
if (!CheckCondition(array[i], hex)) {
/* Discard the following (offset, data) pairs. */
read_next_pair(array, v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2)
read_next_pair(array, v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else { /* Configure matched pairs and skip to end of if-else. */
read_next_pair(array, v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
} else {
odm_ConfigBB_AGC_8188E(dm_odm, v1, bMaskDWord, v2);
}
read_next_pair(array, v1, v2, i);
}
while (v2 != 0xDEAD && i < arraylen - 2)
read_next_pair(array, v1, v2, i);
}
}
}
if (biol) {
if (!rtw_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
printk("~~~ %s IOL_exec_cmds Failed !!!\n", __func__);
rst = HAL_STATUS_FAILURE;
}
}
return rst;
}
/******************************************************************************
* PHY_REG_1T.TXT
******************************************************************************/
static u32 array_phy_reg_1t_8188e[] = {
0x800, 0x80040000,
0x804, 0x00000003,
0x808, 0x0000FC00,
0x80C, 0x0000000A,
0x810, 0x10001331,
0x814, 0x020C3D10,
0x818, 0x02200385,
0x81C, 0x00000000,
0x820, 0x01000100,
0x824, 0x00390204,
0x828, 0x00000000,
0x82C, 0x00000000,
0x830, 0x00000000,
0x834, 0x00000000,
0x838, 0x00000000,
0x83C, 0x00000000,
0x840, 0x00010000,
0x844, 0x00000000,
0x848, 0x00000000,
0x84C, 0x00000000,
0x850, 0x00000000,
0x854, 0x00000000,
0x858, 0x569A11A9,
0x85C, 0x01000014,
0x860, 0x66F60110,
0x864, 0x061F0649,
0x868, 0x00000000,
0x86C, 0x27272700,
0x870, 0x07000760,
0x874, 0x25004000,
0x878, 0x00000808,
0x87C, 0x00000000,
0x880, 0xB0000C1C,
0x884, 0x00000001,
0x888, 0x00000000,
0x88C, 0xCCC000C0,
0x890, 0x00000800,
0x894, 0xFFFFFFFE,
0x898, 0x40302010,
0x89C, 0x00706050,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90C, 0x81121111,
0x910, 0x00000002,
0x914, 0x00000201,
0xA00, 0x00D047C8,
0xA04, 0x80FF000C,
0xA08, 0x8C838300,
0xA0C, 0x2E7F120F,
0xA10, 0x9500BB78,
0xA14, 0x1114D028,
0xA18, 0x00881117,
0xA1C, 0x89140F00,
0xA20, 0x1A1B0000,
0xA24, 0x090E1317,
0xA28, 0x00000204,
0xA2C, 0x00D30000,
0xA70, 0x101FBF00,
0xA74, 0x00000007,
0xA78, 0x00000900,
0xA7C, 0x225B0606,
0xA80, 0x218075B1,
0xB2C, 0x80000000,
0xC00, 0x48071D40,
0xC04, 0x03A05611,
0xC08, 0x000000E4,
0xC0C, 0x6C6C6C6C,
0xC10, 0x08800000,
0xC14, 0x40000100,
0xC18, 0x08800000,
0xC1C, 0x40000100,
0xC20, 0x00000000,
0xC24, 0x00000000,
0xC28, 0x00000000,
0xC2C, 0x00000000,
0xC30, 0x69E9AC47,
0xC34, 0x469652AF,
0xC38, 0x49795994,
0xC3C, 0x0A97971C,
0xC40, 0x1F7C403F,
0xC44, 0x000100B7,
0xC48, 0xEC020107,
0xC4C, 0x007F037F,
0xC50, 0x69553420,
0xC54, 0x43BC0094,
0xC58, 0x00013169,
0xC5C, 0x00250492,
0xC60, 0x00000000,
0xC64, 0x7112848B,
0xC68, 0x47C00BFF,
0xC6C, 0x00000036,
0xC70, 0x2C7F000D,
0xC74, 0x020610DB,
0xC78, 0x0000001F,
0xC7C, 0x00B91612,
0xC80, 0x390000E4,
0xC84, 0x20F60000,
0xC88, 0x40000100,
0xC8C, 0x20200000,
0xC90, 0x00091521,
0xC94, 0x00000000,
0xC98, 0x00121820,
0xC9C, 0x00007F7F,
0xCA0, 0x00000000,
0xCA4, 0x000300A0,
0xCA8, 0x00000000,
0xCAC, 0x00000000,
0xCB0, 0x00000000,
0xCB4, 0x00000000,
0xCB8, 0x00000000,
0xCBC, 0x28000000,
0xCC0, 0x00000000,
0xCC4, 0x00000000,
0xCC8, 0x00000000,
0xCCC, 0x00000000,
0xCD0, 0x00000000,
0xCD4, 0x00000000,
0xCD8, 0x64B22427,
0xCDC, 0x00766932,
0xCE0, 0x00222222,
0xCE4, 0x00000000,
0xCE8, 0x37644302,
0xCEC, 0x2F97D40C,
0xD00, 0x00000740,
0xD04, 0x00020401,
0xD08, 0x0000907F,
0xD0C, 0x20010201,
0xD10, 0xA0633333,
0xD14, 0x3333BC43,
0xD18, 0x7A8F5B6F,
0xD2C, 0xCC979975,
0xD30, 0x00000000,
0xD34, 0x80608000,
0xD38, 0x00000000,
0xD3C, 0x00127353,
0xD40, 0x00000000,
0xD44, 0x00000000,
0xD48, 0x00000000,
0xD4C, 0x00000000,
0xD50, 0x6437140A,
0xD54, 0x00000000,
0xD58, 0x00000282,
0xD5C, 0x30032064,
0xD60, 0x4653DE68,
0xD64, 0x04518A3C,
0xD68, 0x00002101,
0xD6C, 0x2A201C16,
0xD70, 0x1812362E,
0xD74, 0x322C2220,
0xD78, 0x000E3C24,
0xE00, 0x2D2D2D2D,
0xE04, 0x2D2D2D2D,
0xE08, 0x0390272D,
0xE10, 0x2D2D2D2D,
0xE14, 0x2D2D2D2D,
0xE18, 0x2D2D2D2D,
0xE1C, 0x2D2D2D2D,
0xE28, 0x00000000,
0xE30, 0x1000DC1F,
0xE34, 0x10008C1F,
0xE38, 0x02140102,
0xE3C, 0x681604C2,
0xE40, 0x01007C00,
0xE44, 0x01004800,
0xE48, 0xFB000000,
0xE4C, 0x000028D1,
0xE50, 0x1000DC1F,
0xE54, 0x10008C1F,
0xE58, 0x02140102,
0xE5C, 0x28160D05,
0xE60, 0x00000008,
0xE68, 0x001B25A4,
0xE6C, 0x00C00014,
0xE70, 0x00C00014,
0xE74, 0x01000014,
0xE78, 0x01000014,
0xE7C, 0x01000014,
0xE80, 0x01000014,
0xE84, 0x00C00014,
0xE88, 0x01000014,
0xE8C, 0x00C00014,
0xED0, 0x00C00014,
0xED4, 0x00C00014,
0xED8, 0x00C00014,
0xEDC, 0x00000014,
0xEE0, 0x00000014,
0xEEC, 0x01C00014,
0xF14, 0x00000003,
0xF4C, 0x00000000,
0xF00, 0x00000300,
};
enum HAL_STATUS ODM_ReadAndConfig_PHY_REG_1T_8188E(struct odm_dm_struct *dm_odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = dm_odm->SupportPlatform;
u8 interfaceValue = dm_odm->SupportInterface;
u8 board = dm_odm->BoardType;
u32 arraylen = sizeof(array_phy_reg_1t_8188e)/sizeof(u32);
u32 *array = array_phy_reg_1t_8188e;
bool biol = false;
struct adapter *adapter = dm_odm->Adapter;
struct xmit_frame *pxmit_frame = NULL;
u8 bndy_cnt = 1;
enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
biol = rtw_IOL_applied(adapter);
if (biol) {
pxmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
if (pxmit_frame == NULL) {
pr_info("rtw_IOL_accquire_xmit_frame failed\n");
return HAL_STATUS_FAILURE;
}
}
for (i = 0; i < arraylen; i += 2) {
u32 v1 = array[i];
u32 v2 = array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
if (v1 == 0xfe) {
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
} else if (v1 == 0xfd) {
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
} else if (v1 == 0xfc) {
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
} else if (v1 == 0xfb) {
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
} else if (v1 == 0xfa) {
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
} else if (v1 == 0xf9) {
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
} else {
if (v1 == 0xa24)
dm_odm->RFCalibrateInfo.RegA24 = v2;
rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
}
} else {
odm_ConfigBB_PHY_8188E(dm_odm, v1, bMaskDWord, v2);
}
continue;
} else { /* This line is the start line of branch. */
if (!CheckCondition(array[i], hex)) {
/* Discard the following (offset, data) pairs. */
read_next_pair(array, v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2)
read_next_pair(array, v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else { /* Configure matched pairs and skip to end of if-else. */
read_next_pair(array, v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
if (v1 == 0xfe) {
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
} else if (v1 == 0xfd) {
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
} else if (v1 == 0xfc) {
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
} else if (v1 == 0xfb) {
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
} else if (v1 == 0xfa) {
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
} else if (v1 == 0xf9) {
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
} else{
if (v1 == 0xa24)
dm_odm->RFCalibrateInfo.RegA24 = v2;
rtw_IOL_append_WD_cmd(pxmit_frame, (u16)v1, v2, bMaskDWord);
}
} else {
odm_ConfigBB_PHY_8188E(dm_odm, v1, bMaskDWord, v2);
}
read_next_pair(array, v1, v2, i);
}
while (v2 != 0xDEAD && i < arraylen - 2)
read_next_pair(array, v1, v2, i);
}
}
}
if (biol) {
if (!rtw_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
rst = HAL_STATUS_FAILURE;
pr_info("~~~ IOL Config %s Failed !!!\n", __func__);
}
}
return rst;
}
/******************************************************************************
* PHY_REG_PG.TXT
******************************************************************************/
static u32 array_phy_reg_pg_8188e[] = {
0xE00, 0xFFFFFFFF, 0x06070809,
0xE04, 0xFFFFFFFF, 0x02020405,
0xE08, 0x0000FF00, 0x00000006,
0x86C, 0xFFFFFF00, 0x00020400,
0xE10, 0xFFFFFFFF, 0x08090A0B,
0xE14, 0xFFFFFFFF, 0x01030607,
0xE18, 0xFFFFFFFF, 0x08090A0B,
0xE1C, 0xFFFFFFFF, 0x01030607,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x02020202,
0xE04, 0xFFFFFFFF, 0x00020202,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x04040404,
0xE14, 0xFFFFFFFF, 0x00020404,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x02020202,
0xE04, 0xFFFFFFFF, 0x00020202,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x04040404,
0xE14, 0xFFFFFFFF, 0x00020404,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x02020202,
0xE04, 0xFFFFFFFF, 0x00020202,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x04040404,
0xE14, 0xFFFFFFFF, 0x00020404,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
};
void ODM_ReadAndConfig_PHY_REG_PG_8188E(struct odm_dm_struct *dm_odm)
{
u32 hex;
u32 i = 0;
u8 platform = dm_odm->SupportPlatform;
u8 interfaceValue = dm_odm->SupportInterface;
u8 board = dm_odm->BoardType;
u32 arraylen = sizeof(array_phy_reg_pg_8188e) / sizeof(u32);
u32 *array = array_phy_reg_pg_8188e;
hex = board + (interfaceValue << 8);
hex += (platform << 16) + 0xFF000000;
for (i = 0; i < arraylen; i += 3) {
u32 v1 = array[i];
u32 v2 = array[i+1];
u32 v3 = array[i+2];
/* this line is a line of pure_body */
if (v1 < 0xCDCDCDCD) {
odm_ConfigBB_PHY_REG_PG_8188E(dm_odm, v1, v2, v3);
continue;
} else { /* this line is the start of branch */
if (!CheckCondition(array[i], hex)) {
/* don't need the hw_body */
i += 2; /* skip the pair of expression */
v1 = array[i];
v2 = array[i+1];
v3 = array[i+2];
while (v2 != 0xDEAD) {
i += 3;
v1 = array[i];
v2 = array[i+1];
v3 = array[i+1];
}
}
}
}
}

View File

@ -0,0 +1,230 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
#include <rtw_iol.h>
static bool Checkcondition(const u32 condition, const u32 hex)
{
u32 _board = (hex & 0x000000FF);
u32 _interface = (hex & 0x0000FF00) >> 8;
u32 _platform = (hex & 0x00FF0000) >> 16;
u32 cond = condition;
if (condition == 0xCDCDCDCD)
return true;
cond = condition & 0x000000FF;
if ((_board == cond) && cond != 0x00)
return false;
cond = condition & 0x0000FF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = condition & 0x00FF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
/******************************************************************************
* MAC_REG.TXT
******************************************************************************/
static u32 array_MAC_REG_8188E[] = {
0x026, 0x00000041,
0x027, 0x00000035,
0x428, 0x0000000A,
0x429, 0x00000010,
0x430, 0x00000000,
0x431, 0x00000001,
0x432, 0x00000002,
0x433, 0x00000004,
0x434, 0x00000005,
0x435, 0x00000006,
0x436, 0x00000007,
0x437, 0x00000008,
0x438, 0x00000000,
0x439, 0x00000000,
0x43A, 0x00000001,
0x43B, 0x00000002,
0x43C, 0x00000004,
0x43D, 0x00000005,
0x43E, 0x00000006,
0x43F, 0x00000007,
0x440, 0x0000005D,
0x441, 0x00000001,
0x442, 0x00000000,
0x444, 0x00000015,
0x445, 0x000000F0,
0x446, 0x0000000F,
0x447, 0x00000000,
0x458, 0x00000041,
0x459, 0x000000A8,
0x45A, 0x00000072,
0x45B, 0x000000B9,
0x460, 0x00000066,
0x461, 0x00000066,
0x480, 0x00000008,
0x4C8, 0x000000FF,
0x4C9, 0x00000008,
0x4CC, 0x000000FF,
0x4CD, 0x000000FF,
0x4CE, 0x00000001,
0x4D3, 0x00000001,
0x500, 0x00000026,
0x501, 0x000000A2,
0x502, 0x0000002F,
0x503, 0x00000000,
0x504, 0x00000028,
0x505, 0x000000A3,
0x506, 0x0000005E,
0x507, 0x00000000,
0x508, 0x0000002B,
0x509, 0x000000A4,
0x50A, 0x0000005E,
0x50B, 0x00000000,
0x50C, 0x0000004F,
0x50D, 0x000000A4,
0x50E, 0x00000000,
0x50F, 0x00000000,
0x512, 0x0000001C,
0x514, 0x0000000A,
0x516, 0x0000000A,
0x525, 0x0000004F,
0x550, 0x00000010,
0x551, 0x00000010,
0x559, 0x00000002,
0x55D, 0x000000FF,
0x605, 0x00000030,
0x608, 0x0000000E,
0x609, 0x0000002A,
0x620, 0x000000FF,
0x621, 0x000000FF,
0x622, 0x000000FF,
0x623, 0x000000FF,
0x624, 0x000000FF,
0x625, 0x000000FF,
0x626, 0x000000FF,
0x627, 0x000000FF,
0x652, 0x00000020,
0x63C, 0x0000000A,
0x63D, 0x0000000A,
0x63E, 0x0000000E,
0x63F, 0x0000000E,
0x640, 0x00000040,
0x66E, 0x00000005,
0x700, 0x00000021,
0x701, 0x00000043,
0x702, 0x00000065,
0x703, 0x00000087,
0x708, 0x00000021,
0x709, 0x00000043,
0x70A, 0x00000065,
0x70B, 0x00000087,
};
enum HAL_STATUS ODM_ReadAndConfig_MAC_REG_8188E(struct odm_dm_struct *dm_odm)
{
#define READ_NEXT_PAIR(v1, v2, i) do { i += 2; v1 = array[i]; v2 = array[i+1]; } while (0)
u32 hex = 0;
u32 i;
u8 platform = dm_odm->SupportPlatform;
u8 interface_val = dm_odm->SupportInterface;
u8 board = dm_odm->BoardType;
u32 array_len = sizeof(array_MAC_REG_8188E)/sizeof(u32);
u32 *array = array_MAC_REG_8188E;
bool biol = false;
struct adapter *adapt = dm_odm->Adapter;
struct xmit_frame *pxmit_frame = NULL;
u8 bndy_cnt = 1;
enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
hex += board;
hex += interface_val << 8;
hex += platform << 16;
hex += 0xFF000000;
biol = rtw_IOL_applied(adapt);
if (biol) {
pxmit_frame = rtw_IOL_accquire_xmit_frame(adapt);
if (pxmit_frame == NULL) {
pr_info("rtw_IOL_accquire_xmit_frame failed\n");
return HAL_STATUS_FAILURE;
}
}
for (i = 0; i < array_len; i += 2) {
u32 v1 = array[i];
u32 v2 = array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
rtw_IOL_append_WB_cmd(pxmit_frame, (u16)v1, (u8)v2, 0xFF);
} else {
odm_ConfigMAC_8188E(dm_odm, v1, (u8)v2);
}
continue;
} else { /* This line is the start line of branch. */
if (!Checkcondition(array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < array_len - 2) {
READ_NEXT_PAIR(v1, v2, i);
}
i -= 2; /* prevent from for-loop += 2 */
} else { /* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < array_len - 2) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
rtw_IOL_append_WB_cmd(pxmit_frame, (u16)v1, (u8)v2, 0xFF);
} else {
odm_ConfigMAC_8188E(dm_odm, v1, (u8)v2);
}
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < array_len - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
if (biol) {
if (!rtw_IOL_exec_cmds_sync(dm_odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
pr_info("~~~ MAC IOL_exec_cmds Failed !!!\n");
rst = HAL_STATUS_FAILURE;
}
}
return rst;
}

View File

@ -0,0 +1,268 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
#include <rtw_iol.h>
static bool CheckCondition(const u32 Condition, const u32 Hex)
{
u32 _board = (Hex & 0x000000FF);
u32 _interface = (Hex & 0x0000FF00) >> 8;
u32 _platform = (Hex & 0x00FF0000) >> 16;
u32 cond = Condition;
if (Condition == 0xCDCDCDCD)
return true;
cond = Condition & 0x000000FF;
if ((_board == cond) && cond != 0x00)
return false;
cond = Condition & 0x0000FF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = Condition & 0x00FF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
/******************************************************************************
* RadioA_1T.TXT
******************************************************************************/
static u32 Array_RadioA_1T_8188E[] = {
0x000, 0x00030000,
0x008, 0x00084000,
0x018, 0x00000407,
0x019, 0x00000012,
0x01E, 0x00080009,
0x01F, 0x00000880,
0x02F, 0x0001A060,
0x03F, 0x00000000,
0x042, 0x000060C0,
0x057, 0x000D0000,
0x058, 0x000BE180,
0x067, 0x00001552,
0x083, 0x00000000,
0x0B0, 0x000FF8FC,
0x0B1, 0x00054400,
0x0B2, 0x000CCC19,
0x0B4, 0x00043003,
0x0B6, 0x0004953E,
0x0B7, 0x0001C718,
0x0B8, 0x000060FF,
0x0B9, 0x00080001,
0x0BA, 0x00040000,
0x0BB, 0x00000400,
0x0BF, 0x000C0000,
0x0C2, 0x00002400,
0x0C3, 0x00000009,
0x0C4, 0x00040C91,
0x0C5, 0x00099999,
0x0C6, 0x000000A3,
0x0C7, 0x00088820,
0x0C8, 0x00076C06,
0x0C9, 0x00000000,
0x0CA, 0x00080000,
0x0DF, 0x00000180,
0x0EF, 0x000001A0,
0x051, 0x0006B27D,
0xFF0F041F, 0xABCD,
0x052, 0x0007E4DD,
0xCDCDCDCD, 0xCDCD,
0x052, 0x0007E49D,
0xFF0F041F, 0xDEAD,
0x053, 0x00000073,
0x056, 0x00051FF3,
0x035, 0x00000086,
0x035, 0x00000186,
0x035, 0x00000286,
0x036, 0x00001C25,
0x036, 0x00009C25,
0x036, 0x00011C25,
0x036, 0x00019C25,
0x0B6, 0x00048538,
0x018, 0x00000C07,
0x05A, 0x0004BD00,
0x019, 0x000739D0,
0x034, 0x0000ADF3,
0x034, 0x00009DF0,
0x034, 0x00008DED,
0x034, 0x00007DEA,
0x034, 0x00006DE7,
0x034, 0x000054EE,
0x034, 0x000044EB,
0x034, 0x000034E8,
0x034, 0x0000246B,
0x034, 0x00001468,
0x034, 0x0000006D,
0x000, 0x00030159,
0x084, 0x00068200,
0x086, 0x000000CE,
0x087, 0x00048A00,
0x08E, 0x00065540,
0x08F, 0x00088000,
0x0EF, 0x000020A0,
0x03B, 0x000F02B0,
0x03B, 0x000EF7B0,
0x03B, 0x000D4FB0,
0x03B, 0x000CF060,
0x03B, 0x000B0090,
0x03B, 0x000A0080,
0x03B, 0x00090080,
0x03B, 0x0008F780,
0x03B, 0x000722B0,
0x03B, 0x0006F7B0,
0x03B, 0x00054FB0,
0x03B, 0x0004F060,
0x03B, 0x00030090,
0x03B, 0x00020080,
0x03B, 0x00010080,
0x03B, 0x0000F780,
0x0EF, 0x000000A0,
0x000, 0x00010159,
0x018, 0x0000F407,
0xFFE, 0x00000000,
0xFFE, 0x00000000,
0x01F, 0x00080003,
0xFFE, 0x00000000,
0xFFE, 0x00000000,
0x01E, 0x00000001,
0x01F, 0x00080000,
0x000, 0x00033E60,
};
enum HAL_STATUS ODM_ReadAndConfig_RadioA_1T_8188E(struct odm_dm_struct *pDM_Odm)
{
#define READ_NEXT_PAIR(v1, v2, i) do \
{ i += 2; v1 = Array[i]; \
v2 = Array[i+1]; } while (0)
u32 hex = 0;
u32 i = 0;
u8 platform = pDM_Odm->SupportPlatform;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_RadioA_1T_8188E)/sizeof(u32);
u32 *Array = Array_RadioA_1T_8188E;
bool biol = false;
struct adapter *Adapter = pDM_Odm->Adapter;
struct xmit_frame *pxmit_frame = NULL;
u8 bndy_cnt = 1;
enum HAL_STATUS rst = HAL_STATUS_SUCCESS;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
biol = rtw_IOL_applied(Adapter);
if (biol) {
pxmit_frame = rtw_IOL_accquire_xmit_frame(Adapter);
if (pxmit_frame == NULL) {
pr_info("rtw_IOL_accquire_xmit_frame failed\n");
return HAL_STATUS_FAILURE;
}
}
for (i = 0; i < ArrayLen; i += 2) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
if (v1 == 0xffe)
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
else if (v1 == 0xfd)
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
else if (v1 == 0xfc)
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
else if (v1 == 0xfb)
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
else if (v1 == 0xfa)
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
else if (v1 == 0xf9)
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
else
rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask);
} else {
odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2);
}
continue;
} else { /* This line is the start line of branch. */
if (!CheckCondition(Array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else { /* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2) {
if (biol) {
if (rtw_IOL_cmd_boundary_handle(pxmit_frame))
bndy_cnt++;
if (v1 == 0xffe)
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 50);
else if (v1 == 0xfd)
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 5);
else if (v1 == 0xfc)
rtw_IOL_append_DELAY_MS_cmd(pxmit_frame, 1);
else if (v1 == 0xfb)
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 50);
else if (v1 == 0xfa)
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 5);
else if (v1 == 0xf9)
rtw_IOL_append_DELAY_US_cmd(pxmit_frame, 1);
else
rtw_IOL_append_WRF_cmd(pxmit_frame, RF_PATH_A, (u16)v1, v2, bRFRegOffsetMask);
} else {
odm_ConfigRF_RadioA_8188E(pDM_Odm, v1, v2);
}
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
if (biol) {
if (!rtw_IOL_exec_cmds_sync(pDM_Odm->Adapter, pxmit_frame, 1000, bndy_cnt)) {
rst = HAL_STATUS_FAILURE;
pr_info("~~~ IOL Config %s Failed !!!\n", __func__);
}
}
return rst;
}

View File

@ -0,0 +1,49 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
/* 3============================================================ */
/* 3 IQ Calibration */
/* 3============================================================ */
void ODM_ResetIQKResult(struct odm_dm_struct *pDM_Odm)
{
}
u8 ODM_GetRightChnlPlaceforIQK(u8 chnl)
{
u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
155, 157, 159, 161, 163, 165
};
u8 place = chnl;
if (chnl > 14) {
for (place = 14; place < sizeof(channel_all); place++) {
if (channel_all[place] == chnl)
return place-13;
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,132 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
/*++
Copyright (c) Realtek Semiconductor Corp. All rights reserved.
Module Name:
HalPwrSeqCmd.c
Abstract:
Implement HW Power sequence configuration CMD handling routine for Realtek devices.
Major Change History:
When Who What
---------- --------------- -------------------------------
2011-10-26 Lucas Modify to be compatible with SD4-CE driver.
2011-07-07 Roger Create.
--*/
#include <HalPwrSeqCmd.h>
/* Description: */
/* This routine deals with the Power Configuration CMDs parsing
* for RTL8723/RTL8188E Series IC.
* Assumption:
* We should follow specific format which was released from HW SD.
*/
u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
u8 ifacetype, struct wl_pwr_cfg pwrseqcmd[])
{
struct wl_pwr_cfg pwrcfgcmd = {0};
u8 poll_bit = false;
u32 aryidx = 0;
u8 value = 0;
u32 offset = 0;
u32 poll_count = 0; /* polling autoload done. */
u32 max_poll_count = 5000;
do {
pwrcfgcmd = pwrseqcmd[aryidx];
RT_TRACE(_module_hal_init_c_ , _drv_info_,
("HalPwrSeqCmdParsing: offset(%#x) cut_msk(%#x) fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) msk(%#x) value(%#x)\n",
GET_PWR_CFG_OFFSET(pwrcfgcmd),
GET_PWR_CFG_CUT_MASK(pwrcfgcmd),
GET_PWR_CFG_FAB_MASK(pwrcfgcmd),
GET_PWR_CFG_INTF_MASK(pwrcfgcmd),
GET_PWR_CFG_BASE(pwrcfgcmd),
GET_PWR_CFG_CMD(pwrcfgcmd),
GET_PWR_CFG_MASK(pwrcfgcmd),
GET_PWR_CFG_VALUE(pwrcfgcmd)));
/* 2 Only Handle the command whose FAB, CUT, and Interface are matched */
if ((GET_PWR_CFG_FAB_MASK(pwrcfgcmd) & fab_vers) &&
(GET_PWR_CFG_CUT_MASK(pwrcfgcmd) & cut_vers) &&
(GET_PWR_CFG_INTF_MASK(pwrcfgcmd) & ifacetype)) {
switch (GET_PWR_CFG_CMD(pwrcfgcmd)) {
case PWR_CMD_READ:
RT_TRACE(_module_hal_init_c_ , _drv_info_, ("HalPwrSeqCmdParsing: PWR_CMD_READ\n"));
break;
case PWR_CMD_WRITE:
RT_TRACE(_module_hal_init_c_ , _drv_info_, ("HalPwrSeqCmdParsing: PWR_CMD_WRITE\n"));
offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
/* Read the value from system register */
value = rtw_read8(padapter, offset);
value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
/* Write the value back to system register */
rtw_write8(padapter, offset, value);
break;
case PWR_CMD_POLLING:
RT_TRACE(_module_hal_init_c_ , _drv_info_, ("HalPwrSeqCmdParsing: PWR_CMD_POLLING\n"));
poll_bit = false;
offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
do {
value = rtw_read8(padapter, offset);
value &= GET_PWR_CFG_MASK(pwrcfgcmd);
if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
poll_bit = true;
else
rtw_udelay_os(10);
if (poll_count++ > max_poll_count) {
DBG_88E("Fail to polling Offset[%#x]\n", offset);
return false;
}
} while (!poll_bit);
break;
case PWR_CMD_DELAY:
RT_TRACE(_module_hal_init_c_ , _drv_info_, ("HalPwrSeqCmdParsing: PWR_CMD_DELAY\n"));
if (GET_PWR_CFG_VALUE(pwrcfgcmd) == PWRSEQ_DELAY_US)
rtw_udelay_os(GET_PWR_CFG_OFFSET(pwrcfgcmd));
else
rtw_udelay_os(GET_PWR_CFG_OFFSET(pwrcfgcmd)*1000);
break;
case PWR_CMD_END:
/* When this command is parsed, end the process */
RT_TRACE(_module_hal_init_c_ , _drv_info_, ("HalPwrSeqCmdParsing: PWR_CMD_END\n"));
return true;
break;
default:
RT_TRACE(_module_hal_init_c_ , _drv_err_, ("HalPwrSeqCmdParsing: Unknown CMD!!\n"));
break;
}
}
aryidx++;/* Add Array Index */
} while (1);
return true;
}

View File

@ -0,0 +1,381 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include <osdep_service.h>
#include <drv_types.h>
#include <hal_intf.h>
#include <hal_com.h>
#include <rtl8188e_hal.h>
#define _HAL_INIT_C_
void dump_chip_info(struct HAL_VERSION chip_vers)
{
uint cnt = 0;
char buf[128];
if (IS_81XXC(chip_vers)) {
cnt += sprintf((buf+cnt), "Chip Version Info: %s_",
IS_92C_SERIAL(chip_vers) ?
"CHIP_8192C" : "CHIP_8188C");
} else if (IS_92D(chip_vers)) {
cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8192D_");
} else if (IS_8723_SERIES(chip_vers)) {
cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8723A_");
} else if (IS_8188E(chip_vers)) {
cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
}
cnt += sprintf((buf+cnt), "%s_", IS_NORMAL_CHIP(chip_vers) ?
"Normal_Chip" : "Test_Chip");
cnt += sprintf((buf+cnt), "%s_", IS_CHIP_VENDOR_TSMC(chip_vers) ?
"TSMC" : "UMC");
if (IS_A_CUT(chip_vers))
cnt += sprintf((buf+cnt), "A_CUT_");
else if (IS_B_CUT(chip_vers))
cnt += sprintf((buf+cnt), "B_CUT_");
else if (IS_C_CUT(chip_vers))
cnt += sprintf((buf+cnt), "C_CUT_");
else if (IS_D_CUT(chip_vers))
cnt += sprintf((buf+cnt), "D_CUT_");
else if (IS_E_CUT(chip_vers))
cnt += sprintf((buf+cnt), "E_CUT_");
else
cnt += sprintf((buf+cnt), "UNKNOWN_CUT(%d)_",
chip_vers.CUTVersion);
if (IS_1T1R(chip_vers))
cnt += sprintf((buf+cnt), "1T1R_");
else if (IS_1T2R(chip_vers))
cnt += sprintf((buf+cnt), "1T2R_");
else if (IS_2T2R(chip_vers))
cnt += sprintf((buf+cnt), "2T2R_");
else
cnt += sprintf((buf+cnt), "UNKNOWN_RFTYPE(%d)_",
chip_vers.RFType);
cnt += sprintf((buf+cnt), "RomVer(%d)\n", chip_vers.ROMVer);
pr_info("%s", buf);
}
#define CHAN_PLAN_HW 0x80
u8 /* return the final channel plan decision */
hal_com_get_channel_plan(struct adapter *padapter, u8 hw_channel_plan,
u8 sw_channel_plan, u8 def_channel_plan,
bool load_fail)
{
u8 sw_cfg;
u8 chnlplan;
sw_cfg = true;
if (!load_fail) {
if (!rtw_is_channel_plan_valid(sw_channel_plan))
sw_cfg = false;
if (hw_channel_plan & CHAN_PLAN_HW)
sw_cfg = false;
}
if (sw_cfg)
chnlplan = sw_channel_plan;
else
chnlplan = hw_channel_plan & (~CHAN_PLAN_HW);
if (!rtw_is_channel_plan_valid(chnlplan))
chnlplan = def_channel_plan;
return chnlplan;
}
u8 MRateToHwRate(u8 rate)
{
u8 ret = DESC_RATE1M;
switch (rate) {
/* CCK and OFDM non-HT rates */
case IEEE80211_CCK_RATE_1MB:
ret = DESC_RATE1M;
break;
case IEEE80211_CCK_RATE_2MB:
ret = DESC_RATE2M;
break;
case IEEE80211_CCK_RATE_5MB:
ret = DESC_RATE5_5M;
break;
case IEEE80211_CCK_RATE_11MB:
ret = DESC_RATE11M;
break;
case IEEE80211_OFDM_RATE_6MB:
ret = DESC_RATE6M;
break;
case IEEE80211_OFDM_RATE_9MB:
ret = DESC_RATE9M;
break;
case IEEE80211_OFDM_RATE_12MB:
ret = DESC_RATE12M;
break;
case IEEE80211_OFDM_RATE_18MB:
ret = DESC_RATE18M;
break;
case IEEE80211_OFDM_RATE_24MB:
ret = DESC_RATE24M;
break;
case IEEE80211_OFDM_RATE_36MB:
ret = DESC_RATE36M;
break;
case IEEE80211_OFDM_RATE_48MB:
ret = DESC_RATE48M;
break;
case IEEE80211_OFDM_RATE_54MB:
ret = DESC_RATE54M;
break;
default:
break;
}
return ret;
}
void HalSetBrateCfg(struct adapter *adapt, u8 *brates, u16 *rate_cfg)
{
u8 i, is_brate, brate;
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
is_brate = brates[i] & IEEE80211_BASIC_RATE_MASK;
brate = brates[i] & 0x7f;
if (is_brate) {
switch (brate) {
case IEEE80211_CCK_RATE_1MB:
*rate_cfg |= RATE_1M;
break;
case IEEE80211_CCK_RATE_2MB:
*rate_cfg |= RATE_2M;
break;
case IEEE80211_CCK_RATE_5MB:
*rate_cfg |= RATE_5_5M;
break;
case IEEE80211_CCK_RATE_11MB:
*rate_cfg |= RATE_11M;
break;
case IEEE80211_OFDM_RATE_6MB:
*rate_cfg |= RATE_6M;
break;
case IEEE80211_OFDM_RATE_9MB:
*rate_cfg |= RATE_9M;
break;
case IEEE80211_OFDM_RATE_12MB:
*rate_cfg |= RATE_12M;
break;
case IEEE80211_OFDM_RATE_18MB:
*rate_cfg |= RATE_18M;
break;
case IEEE80211_OFDM_RATE_24MB:
*rate_cfg |= RATE_24M;
break;
case IEEE80211_OFDM_RATE_36MB:
*rate_cfg |= RATE_36M;
break;
case IEEE80211_OFDM_RATE_48MB:
*rate_cfg |= RATE_48M;
break;
case IEEE80211_OFDM_RATE_54MB:
*rate_cfg |= RATE_54M;
break;
}
}
}
}
static void one_out_pipe(struct adapter *adapter)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
}
static void two_out_pipe(struct adapter *adapter, bool wifi_cfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
if (wifi_cfg) { /* WMM */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 0, 1, 0, 1, 0, 0, 0, 0, 0}; */
/* 0:H, 1:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
} else {/* typical setting */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 1, 1, 0, 0, 0, 0, 0, 0, 0}; */
/* 0:H, 1:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
}
}
static void three_out_pipe(struct adapter *adapter, bool wifi_cfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
if (wifi_cfg) {/* for WMM */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 1, 2, 1, 0, 0, 0, 0, 0, 0}; */
/* 0:H, 1:N, 2:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
} else {/* typical setting */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 2, 2, 1, 0, 0, 0, 0, 0, 0}; */
/* 0:H, 1:N, 2:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
}
}
bool Hal_MappingOutPipe(struct adapter *adapter, u8 numoutpipe)
{
struct registry_priv *pregistrypriv = &adapter->registrypriv;
bool wifi_cfg = (pregistrypriv->wifi_spec) ? true : false;
bool result = true;
switch (numoutpipe) {
case 2:
two_out_pipe(adapter, wifi_cfg);
break;
case 3:
three_out_pipe(adapter, wifi_cfg);
break;
case 1:
one_out_pipe(adapter);
break;
default:
result = false;
break;
}
return result;
}
void hal_init_macaddr(struct adapter *adapter)
{
rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR,
adapter->eeprompriv.mac_addr);
}
/*
* C2H event format:
* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
* BITS [127:120] [119:16] [15:8] [7:4] [3:0]
*/
void c2h_evt_clear(struct adapter *adapter)
{
rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
}
s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
{
s32 ret = _FAIL;
struct c2h_evt_hdr *c2h_evt;
int i;
u8 trigger;
if (buf == NULL)
goto exit;
trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
if (trigger == C2H_EVT_HOST_CLOSE)
goto exit; /* Not ready */
else if (trigger != C2H_EVT_FW_CLOSE)
goto clear_evt; /* Not a valid value */
c2h_evt = (struct c2h_evt_hdr *)buf;
memset(c2h_evt, 0, 16);
*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
*(buf+1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read(): ",
&c2h_evt , sizeof(c2h_evt));
/* Read the content */
for (i = 0; i < c2h_evt->plen; i++)
c2h_evt->payload[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
sizeof(*c2h_evt) + i);
RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
"c2h_evt_read(): Command Content:\n",
c2h_evt->payload, c2h_evt->plen);
ret = _SUCCESS;
clear_evt:
/*
* Clear event to notify FW we have read the command.
* If this field isn't clear, the FW won't update the next
* command message.
*/
c2h_evt_clear(adapter);
exit:
return ret;
}

View File

@ -0,0 +1,468 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 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 _HAL_INTF_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <hal_intf.h>
#include <usb_hal.h>
void rtw_hal_chip_configure(struct adapter *adapt)
{
if (adapt->HalFunc.intf_chip_configure)
adapt->HalFunc.intf_chip_configure(adapt);
}
void rtw_hal_read_chip_info(struct adapter *adapt)
{
if (adapt->HalFunc.read_adapter_info)
adapt->HalFunc.read_adapter_info(adapt);
}
void rtw_hal_read_chip_version(struct adapter *adapt)
{
if (adapt->HalFunc.read_chip_version)
adapt->HalFunc.read_chip_version(adapt);
}
void rtw_hal_def_value_init(struct adapter *adapt)
{
if (adapt->HalFunc.init_default_value)
adapt->HalFunc.init_default_value(adapt);
}
void rtw_hal_free_data(struct adapter *adapt)
{
if (adapt->HalFunc.free_hal_data)
adapt->HalFunc.free_hal_data(adapt);
}
void rtw_hal_dm_init(struct adapter *adapt)
{
if (adapt->HalFunc.dm_init)
adapt->HalFunc.dm_init(adapt);
}
void rtw_hal_dm_deinit(struct adapter *adapt)
{
/* cancel dm timer */
if (adapt->HalFunc.dm_deinit)
adapt->HalFunc.dm_deinit(adapt);
}
void rtw_hal_sw_led_init(struct adapter *adapt)
{
if (adapt->HalFunc.InitSwLeds)
adapt->HalFunc.InitSwLeds(adapt);
}
void rtw_hal_sw_led_deinit(struct adapter *adapt)
{
if (adapt->HalFunc.DeInitSwLeds)
adapt->HalFunc.DeInitSwLeds(adapt);
}
u32 rtw_hal_power_on(struct adapter *adapt)
{
if (adapt->HalFunc.hal_power_on)
return adapt->HalFunc.hal_power_on(adapt);
return _FAIL;
}
uint rtw_hal_init(struct adapter *adapt)
{
uint status = _SUCCESS;
adapt->hw_init_completed = false;
status = adapt->HalFunc.hal_init(adapt);
if (status == _SUCCESS) {
adapt->hw_init_completed = true;
if (adapt->registrypriv.notch_filter == 1)
rtw_hal_notch_filter(adapt, 1);
rtw_hal_reset_security_engine(adapt);
} else {
adapt->hw_init_completed = false;
DBG_88E("rtw_hal_init: hal__init fail\n");
}
RT_TRACE(_module_hal_init_c_, _drv_err_,
("-rtl871x_hal_init:status=0x%x\n", status));
return status;
}
uint rtw_hal_deinit(struct adapter *adapt)
{
uint status = _SUCCESS;
status = adapt->HalFunc.hal_deinit(adapt);
if (status == _SUCCESS)
adapt->hw_init_completed = false;
else
DBG_88E("\n rtw_hal_deinit: hal_init fail\n");
return status;
}
void rtw_hal_set_hwreg(struct adapter *adapt, u8 variable, u8 *val)
{
if (adapt->HalFunc.SetHwRegHandler)
adapt->HalFunc.SetHwRegHandler(adapt, variable, val);
}
void rtw_hal_get_hwreg(struct adapter *adapt, u8 variable, u8 *val)
{
if (adapt->HalFunc.GetHwRegHandler)
adapt->HalFunc.GetHwRegHandler(adapt, variable, val);
}
u8 rtw_hal_set_def_var(struct adapter *adapt, enum hal_def_variable var,
void *val)
{
if (adapt->HalFunc.SetHalDefVarHandler)
return adapt->HalFunc.SetHalDefVarHandler(adapt, var, val);
return _FAIL;
}
u8 rtw_hal_get_def_var(struct adapter *adapt,
enum hal_def_variable var, void *val)
{
if (adapt->HalFunc.GetHalDefVarHandler)
return adapt->HalFunc.GetHalDefVarHandler(adapt, var, val);
return _FAIL;
}
void rtw_hal_set_odm_var(struct adapter *adapt,
enum hal_odm_variable var, void *val1,
bool set)
{
if (adapt->HalFunc.SetHalODMVarHandler)
adapt->HalFunc.SetHalODMVarHandler(adapt, var,
val1, set);
}
void rtw_hal_get_odm_var(struct adapter *adapt,
enum hal_odm_variable var, void *val1,
bool set)
{
if (adapt->HalFunc.GetHalODMVarHandler)
adapt->HalFunc.GetHalODMVarHandler(adapt, var,
val1, set);
}
void rtw_hal_enable_interrupt(struct adapter *adapt)
{
if (adapt->HalFunc.enable_interrupt)
adapt->HalFunc.enable_interrupt(adapt);
else
DBG_88E("%s: HalFunc.enable_interrupt is NULL!\n", __func__);
}
void rtw_hal_disable_interrupt(struct adapter *adapt)
{
if (adapt->HalFunc.disable_interrupt)
adapt->HalFunc.disable_interrupt(adapt);
else
DBG_88E("%s: HalFunc.disable_interrupt is NULL!\n", __func__);
}
u32 rtw_hal_inirp_init(struct adapter *adapt)
{
u32 rst = _FAIL;
if (adapt->HalFunc.inirp_init)
rst = adapt->HalFunc.inirp_init(adapt);
else
DBG_88E(" %s HalFunc.inirp_init is NULL!!!\n", __func__);
return rst;
}
u32 rtw_hal_inirp_deinit(struct adapter *adapt)
{
if (adapt->HalFunc.inirp_deinit)
return adapt->HalFunc.inirp_deinit(adapt);
return _FAIL;
}
u8 rtw_hal_intf_ps_func(struct adapter *adapt,
enum hal_intf_ps_func efunc_id, u8 *val)
{
if (adapt->HalFunc.interface_ps_func)
return adapt->HalFunc.interface_ps_func(adapt, efunc_id,
val);
return _FAIL;
}
s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter,
struct xmit_frame *pxmitframe)
{
if(padapter->HalFunc.hal_xmitframe_enqueue)
return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
return false;
}
s32 rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
if (adapt->HalFunc.hal_xmit)
return adapt->HalFunc.hal_xmit(adapt, pxmitframe);
return false;
}
s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
{
s32 ret = _FAIL;
if (adapt->HalFunc.mgnt_xmit)
ret = adapt->HalFunc.mgnt_xmit(adapt, pmgntframe);
return ret;
}
s32 rtw_hal_init_xmit_priv(struct adapter *adapt)
{
if (adapt->HalFunc.init_xmit_priv != NULL)
return adapt->HalFunc.init_xmit_priv(adapt);
return _FAIL;
}
void rtw_hal_free_xmit_priv(struct adapter *adapt)
{
if (adapt->HalFunc.free_xmit_priv != NULL)
adapt->HalFunc.free_xmit_priv(adapt);
}
s32 rtw_hal_init_recv_priv(struct adapter *adapt)
{
if (adapt->HalFunc.init_recv_priv)
return adapt->HalFunc.init_recv_priv(adapt);
return _FAIL;
}
void rtw_hal_free_recv_priv(struct adapter *adapt)
{
if (adapt->HalFunc.free_recv_priv)
adapt->HalFunc.free_recv_priv(adapt);
}
void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level)
{
struct mlme_priv *pmlmepriv = &(adapt->mlmepriv);
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
#ifdef CONFIG_88EU_AP_MODE
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &adapt->stapriv;
if ((mac_id-1) > 0)
psta = pstapriv->sta_aid[(mac_id-1) - 1];
if (psta)
add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/
#endif
} else {
if (adapt->HalFunc.UpdateRAMaskHandler)
adapt->HalFunc.UpdateRAMaskHandler(adapt, mac_id,
rssi_level);
}
}
void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg,
u8 rssi_level)
{
if (adapt->HalFunc.Add_RateATid)
adapt->HalFunc.Add_RateATid(adapt, bitmap, arg,
rssi_level);
}
/* Start specifical interface thread */
void rtw_hal_start_thread(struct adapter *adapt)
{
if (adapt->HalFunc.run_thread)
adapt->HalFunc.run_thread(adapt);
}
/* Start specifical interface thread */
void rtw_hal_stop_thread(struct adapter *adapt)
{
if (adapt->HalFunc.cancel_thread)
adapt->HalFunc.cancel_thread(adapt);
}
u32 rtw_hal_read_bbreg(struct adapter *adapt, u32 regaddr, u32 bitmask)
{
u32 data = 0;
if (adapt->HalFunc.read_bbreg)
data = adapt->HalFunc.read_bbreg(adapt, regaddr, bitmask);
return data;
}
void rtw_hal_write_bbreg(struct adapter *adapt, u32 regaddr, u32 bitmask,
u32 data)
{
if (adapt->HalFunc.write_bbreg)
adapt->HalFunc.write_bbreg(adapt, regaddr, bitmask, data);
}
u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
u32 regaddr, u32 bitmask)
{
u32 data = 0;
if (adapt->HalFunc.read_rfreg)
data = adapt->HalFunc.read_rfreg(adapt, rfpath, regaddr,
bitmask);
return data;
}
void rtw_hal_write_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
u32 regaddr, u32 bitmask, u32 data)
{
if (adapt->HalFunc.write_rfreg)
adapt->HalFunc.write_rfreg(adapt, rfpath, regaddr,
bitmask, data);
}
s32 rtw_hal_interrupt_handler(struct adapter *adapt)
{
if (adapt->HalFunc.interrupt_handler)
return adapt->HalFunc.interrupt_handler(adapt);
return _FAIL;
}
void rtw_hal_set_bwmode(struct adapter *adapt,
enum ht_channel_width bandwidth, u8 offset)
{
if (adapt->HalFunc.set_bwmode_handler)
adapt->HalFunc.set_bwmode_handler(adapt, bandwidth,
offset);
}
void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
{
if (adapt->HalFunc.set_channel_handler)
adapt->HalFunc.set_channel_handler(adapt, channel);
}
void rtw_hal_dm_watchdog(struct adapter *adapt)
{
if (adapt->HalFunc.hal_dm_watchdog)
adapt->HalFunc.hal_dm_watchdog(adapt);
}
void rtw_hal_bcn_related_reg_setting(struct adapter *adapt)
{
if (adapt->HalFunc.SetBeaconRelatedRegistersHandler)
adapt->HalFunc.SetBeaconRelatedRegistersHandler(adapt);
}
u8 rtw_hal_antdiv_before_linked(struct adapter *adapt)
{
if (adapt->HalFunc.AntDivBeforeLinkHandler)
return adapt->HalFunc.AntDivBeforeLinkHandler(adapt);
return false;
}
void rtw_hal_antdiv_rssi_compared(struct adapter *adapt,
struct wlan_bssid_ex *dst,
struct wlan_bssid_ex *src)
{
if (adapt->HalFunc.AntDivCompareHandler)
adapt->HalFunc.AntDivCompareHandler(adapt, dst, src);
}
void rtw_hal_sreset_init(struct adapter *adapt)
{
if (adapt->HalFunc.sreset_init_value)
adapt->HalFunc.sreset_init_value(adapt);
}
void rtw_hal_sreset_reset(struct adapter *adapt)
{
if (adapt->HalFunc.silentreset)
adapt->HalFunc.silentreset(adapt);
}
void rtw_hal_sreset_reset_value(struct adapter *adapt)
{
if (adapt->HalFunc.sreset_reset_value)
adapt->HalFunc.sreset_reset_value(adapt);
}
void rtw_hal_sreset_xmit_status_check(struct adapter *adapt)
{
if (adapt->HalFunc.sreset_xmit_status_check)
adapt->HalFunc.sreset_xmit_status_check(adapt);
}
void rtw_hal_sreset_linked_status_check(struct adapter *adapt)
{
if (adapt->HalFunc.sreset_linked_status_check)
adapt->HalFunc.sreset_linked_status_check(adapt);
}
u8 rtw_hal_sreset_get_wifi_status(struct adapter *adapt)
{
u8 status = 0;
if (adapt->HalFunc.sreset_get_wifi_status)
status = adapt->HalFunc.sreset_get_wifi_status(adapt);
return status;
}
int rtw_hal_iol_cmd(struct adapter *adapter, struct xmit_frame *xmit_frame,
u32 max_wating_ms, u32 bndy_cnt)
{
if (adapter->HalFunc.IOL_exec_cmds_sync)
return adapter->HalFunc.IOL_exec_cmds_sync(adapter, xmit_frame,
max_wating_ms,
bndy_cnt);
return _FAIL;
}
void rtw_hal_notch_filter(struct adapter *adapter, bool enable)
{
if (adapter->HalFunc.hal_notch_filter)
adapter->HalFunc.hal_notch_filter(adapter, enable);
}
void rtw_hal_reset_security_engine(struct adapter *adapter)
{
if (adapter->HalFunc.hal_reset_security_engine)
adapter->HalFunc.hal_reset_security_engine(adapter);
}
s32 rtw_hal_c2h_handler(struct adapter *adapter, struct c2h_evt_hdr *c2h_evt)
{
s32 ret = _FAIL;
if (adapter->HalFunc.c2h_handler)
ret = adapter->HalFunc.c2h_handler(adapter, c2h_evt);
return ret;
}
c2h_id_filter rtw_hal_c2h_id_filter_ccx(struct adapter *adapter)
{
return adapter->HalFunc.c2h_id_filter_ccx;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,601 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
/* include files */
#include "odm_precomp.h"
#define READ_AND_CONFIG READ_AND_CONFIG_MP
#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(dm_odm))
#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(dm_odm))
static u8 odm_QueryRxPwrPercentage(s8 AntPower)
{
if ((AntPower <= -100) || (AntPower >= 20))
return 0;
else if (AntPower >= 0)
return 100;
else
return 100+AntPower;
}
/* 2012/01/12 MH MOve some signal strength smooth method to MP HAL layer. */
/* IF other SW team do not support the feature, remove this section.?? */
static s32 odm_sig_patch_lenove(struct odm_dm_struct *dm_odm, s32 CurrSig)
{
return 0;
}
static s32 odm_sig_patch_netcore(struct odm_dm_struct *dm_odm, s32 CurrSig)
{
return 0;
}
static s32 odm_SignalScaleMapping_92CSeries(struct odm_dm_struct *dm_odm, s32 CurrSig)
{
s32 RetSig = 0;
if ((dm_odm->SupportInterface == ODM_ITRF_USB) ||
(dm_odm->SupportInterface == ODM_ITRF_SDIO)) {
if (CurrSig >= 51 && CurrSig <= 100)
RetSig = 100;
else if (CurrSig >= 41 && CurrSig <= 50)
RetSig = 80 + ((CurrSig - 40)*2);
else if (CurrSig >= 31 && CurrSig <= 40)
RetSig = 66 + (CurrSig - 30);
else if (CurrSig >= 21 && CurrSig <= 30)
RetSig = 54 + (CurrSig - 20);
else if (CurrSig >= 10 && CurrSig <= 20)
RetSig = 42 + (((CurrSig - 10) * 2) / 3);
else if (CurrSig >= 5 && CurrSig <= 9)
RetSig = 22 + (((CurrSig - 5) * 3) / 2);
else if (CurrSig >= 1 && CurrSig <= 4)
RetSig = 6 + (((CurrSig - 1) * 3) / 2);
else
RetSig = CurrSig;
}
return RetSig;
}
static s32 odm_SignalScaleMapping(struct odm_dm_struct *dm_odm, s32 CurrSig)
{
if ((dm_odm->SupportPlatform == ODM_MP) &&
(dm_odm->SupportInterface != ODM_ITRF_PCIE) && /* USB & SDIO */
(dm_odm->PatchID == 10))
return odm_sig_patch_netcore(dm_odm, CurrSig);
else if ((dm_odm->SupportPlatform == ODM_MP) &&
(dm_odm->SupportInterface == ODM_ITRF_PCIE) &&
(dm_odm->PatchID == 19))
return odm_sig_patch_lenove(dm_odm, CurrSig);
else
return odm_SignalScaleMapping_92CSeries(dm_odm, CurrSig);
}
/* pMgntInfo->CustomerID == RT_CID_819x_Lenovo */
static u8 odm_SQ_process_patch_RT_CID_819x_Lenovo(struct odm_dm_struct *dm_odm,
u8 isCCKrate, u8 PWDB_ALL, u8 path, u8 RSSI)
{
return 0;
}
static u8 odm_EVMdbToPercentage(s8 Value)
{
/* -33dB~0dB to 0%~99% */
s8 ret_val;
ret_val = Value;
if (ret_val >= 0)
ret_val = 0;
if (ret_val <= -33)
ret_val = -33;
ret_val = 0 - ret_val;
ret_val *= 3;
if (ret_val == 99)
ret_val = 100;
return ret_val;
}
static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm,
struct odm_phy_status_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_per_pkt_info *pPktinfo,
struct adapter *adapt)
{
struct sw_ant_switch *pDM_SWAT_Table = &dm_odm->DM_SWAT_Table;
u8 i, Max_spatial_stream;
s8 rx_pwr[4], rx_pwr_all = 0;
u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
u8 RSSI, total_rssi = 0;
u8 isCCKrate = 0;
u8 rf_rx_num = 0;
u8 cck_highpwr = 0;
u8 LNA_idx, VGA_idx;
struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
isCCKrate = ((pPktinfo->Rate >= DESC92C_RATE1M) && (pPktinfo->Rate <= DESC92C_RATE11M)) ? true : false;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
if (isCCKrate) {
u8 report;
u8 cck_agc_rpt;
dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
/* (1)Hardware does not provide RSSI for CCK */
/* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
cck_highpwr = dm_odm->bCckHighPower;
cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ;
/* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
/* The RSSI formula should be modified according to the gain table */
/* In 88E, cck_highpwr is always set to 1 */
if (dm_odm->SupportICType & (ODM_RTL8188E|ODM_RTL8812)) {
LNA_idx = ((cck_agc_rpt & 0xE0) >> 5);
VGA_idx = (cck_agc_rpt & 0x1F);
switch (LNA_idx) {
case 7:
if (VGA_idx <= 27)
rx_pwr_all = -100 + 2*(27-VGA_idx); /* VGA_idx = 27~2 */
else
rx_pwr_all = -100;
break;
case 6:
rx_pwr_all = -48 + 2*(2-VGA_idx); /* VGA_idx = 2~0 */
break;
case 5:
rx_pwr_all = -42 + 2*(7-VGA_idx); /* VGA_idx = 7~5 */
break;
case 4:
rx_pwr_all = -36 + 2*(7-VGA_idx); /* VGA_idx = 7~4 */
break;
case 3:
rx_pwr_all = -24 + 2*(7-VGA_idx); /* VGA_idx = 7~0 */
break;
case 2:
if (cck_highpwr)
rx_pwr_all = -12 + 2*(5-VGA_idx); /* VGA_idx = 5~0 */
else
rx_pwr_all = -6 + 2*(5-VGA_idx);
break;
case 1:
rx_pwr_all = 8-2*VGA_idx;
break;
case 0:
rx_pwr_all = 14-2*VGA_idx;
break;
default:
break;
}
rx_pwr_all += 6;
PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
if (!cck_highpwr) {
if (PWDB_ALL >= 80)
PWDB_ALL = ((PWDB_ALL-80)<<1)+((PWDB_ALL-80)>>1)+80;
else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20))
PWDB_ALL += 3;
if (PWDB_ALL > 100)
PWDB_ALL = 100;
}
} else {
if (!cck_highpwr) {
report = (cck_agc_rpt & 0xc0)>>6;
switch (report) {
/* 03312009 modified by cosa */
/* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */
/* Note: different RF with the different RNA gain. */
case 0x3:
rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
break;
case 0x2:
rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
break;
case 0x1:
rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
break;
case 0x0:
rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
break;
}
} else {
report = (cck_agc_rpt & 0x60)>>5;
switch (report) {
case 0x3:
rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1) ;
break;
case 0x2:
rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1);
break;
case 0x1:
rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1);
break;
case 0x0:
rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1);
break;
}
}
PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
/* Modification for ext-LNA board */
if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
if ((cck_agc_rpt>>7) == 0) {
PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL+6);
} else {
if (PWDB_ALL > 38)
PWDB_ALL -= 16;
else
PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL>>2) : (PWDB_ALL-12);
}
/* CCK modification */
if (PWDB_ALL > 25 && PWDB_ALL <= 60)
PWDB_ALL += 6;
} else {/* Modification for int-LNA board */
if (PWDB_ALL > 99)
PWDB_ALL -= 8;
else if (PWDB_ALL > 50 && PWDB_ALL <= 68)
PWDB_ALL += 4;
}
}
pPhyInfo->RxPWDBAll = PWDB_ALL;
pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
pPhyInfo->RecvSignalPower = rx_pwr_all;
/* (3) Get Signal Quality (EVM) */
if (pPktinfo->bPacketMatchBSSID) {
u8 SQ, SQ_rpt;
if ((dm_odm->SupportPlatform == ODM_MP) && (dm_odm->PatchID == 19)) {
SQ = odm_SQ_process_patch_RT_CID_819x_Lenovo(dm_odm, isCCKrate, PWDB_ALL, 0, 0);
} else if (pPhyInfo->RxPWDBAll > 40 && !dm_odm->bInHctTest) {
SQ = 100;
} else {
SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
if (SQ_rpt > 64)
SQ = 0;
else if (SQ_rpt < 20)
SQ = 100;
else
SQ = ((64-SQ_rpt) * 100) / 44;
}
pPhyInfo->SignalQuality = SQ;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
}
} else { /* is OFDM rate */
dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
/* (1)Get RSSI for HT rate */
for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
/* 2008/01/30 MH we will judge RF RX path now. */
if (dm_odm->RFPathRxEnable & BIT(i))
rf_rx_num++;
rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110;
if (i == RF_PATH_A)
adapt->signal_strength = rx_pwr[i];
pPhyInfo->RxPwr[i] = rx_pwr[i];
/* Translate DBM to percentage. */
RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]);
total_rssi += RSSI;
/* Modification for ext-LNA board */
if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
if ((pPhyStaRpt->path_agc[i].trsw) == 1)
RSSI = (RSSI > 94) ? 100 : (RSSI + 6);
else
RSSI = (RSSI <= 16) ? (RSSI >> 3) : (RSSI - 16);
if ((RSSI <= 34) && (RSSI >= 4))
RSSI -= 4;
}
pPhyInfo->RxMIMOSignalStrength[i] = (u8)RSSI;
/* Get Rx snr value in DB */
pPhyInfo->RxSNR[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
/* Record Signal Strength for next packet */
if (pPktinfo->bPacketMatchBSSID) {
if ((dm_odm->SupportPlatform == ODM_MP) && (dm_odm->PatchID == 19)) {
if (i == RF_PATH_A)
pPhyInfo->SignalQuality = odm_SQ_process_patch_RT_CID_819x_Lenovo(dm_odm, isCCKrate, PWDB_ALL, i, RSSI);
}
}
}
/* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110;
PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
PWDB_ALL_BT = PWDB_ALL;
pPhyInfo->RxPWDBAll = PWDB_ALL;
pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
pPhyInfo->RxPower = rx_pwr_all;
pPhyInfo->RecvSignalPower = rx_pwr_all;
if ((dm_odm->SupportPlatform == ODM_MP) && (dm_odm->PatchID == 19)) {
/* do nothing */
} else {
/* (3)EVM of HT rate */
if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
Max_spatial_stream = 2; /* both spatial stream make sense */
else
Max_spatial_stream = 1; /* only spatial stream 1 makes sense */
for (i = 0; i < Max_spatial_stream; i++) {
/* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
/* fill most significant bit to "zero" when doing shifting operation which may change a negative */
/* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
if (pPktinfo->bPacketMatchBSSID) {
if (i == RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */
pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
}
}
}
}
/* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
/* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
if (isCCKrate) {
pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(dm_odm, PWDB_ALL));/* PWDB_ALL; */
} else {
if (rf_rx_num != 0)
pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(dm_odm, total_rssi /= rf_rx_num));
}
/* For 92C/92D HW (Hybrid) Antenna Diversity */
pDM_SWAT_Table->antsel = pPhyStaRpt->ant_sel;
/* For 88E HW Antenna Diversity */
dm_odm->DM_FatTable.antsel_rx_keep_0 = pPhyStaRpt->ant_sel;
dm_odm->DM_FatTable.antsel_rx_keep_1 = pPhyStaRpt->ant_sel_b;
dm_odm->DM_FatTable.antsel_rx_keep_2 = pPhyStaRpt->antsel_rx_keep_2;
}
void odm_Init_RSSIForDM(struct odm_dm_struct *dm_odm)
{
}
static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
struct odm_phy_status_info *pPhyInfo,
struct odm_per_pkt_info *pPktinfo)
{
s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
s32 UndecoratedSmoothedOFDM, RSSI_Ave;
u8 isCCKrate = 0;
u8 RSSI_max, RSSI_min, i;
u32 OFDM_pkt = 0;
u32 Weighting = 0;
struct sta_info *pEntry;
if (pPktinfo->StationID == 0xFF)
return;
pEntry = dm_odm->pODM_StaInfo[pPktinfo->StationID];
if (!IS_STA_VALID(pEntry))
return;
if ((!pPktinfo->bPacketMatchBSSID))
return;
isCCKrate = ((pPktinfo->Rate >= DESC92C_RATE1M) && (pPktinfo->Rate <= DESC92C_RATE11M)) ? true : false;
/* Smart Antenna Debug Message------------------ */
if (dm_odm->SupportICType == ODM_RTL8188E) {
u8 antsel_tr_mux;
struct fast_ant_train *pDM_FatTable = &dm_odm->DM_FatTable;
if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV) {
if (pDM_FatTable->FAT_State == FAT_TRAINING_STATE) {
if (pPktinfo->bPacketToSelf) {
antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2<<2) |
(pDM_FatTable->antsel_rx_keep_1<<1) |
pDM_FatTable->antsel_rx_keep_0;
pDM_FatTable->antSumRSSI[antsel_tr_mux] += pPhyInfo->RxPWDBAll;
pDM_FatTable->antRSSIcnt[antsel_tr_mux]++;
}
}
} else if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) {
if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2<<2) |
(pDM_FatTable->antsel_rx_keep_1<<1) | pDM_FatTable->antsel_rx_keep_0;
ODM_AntselStatistics_88E(dm_odm, antsel_tr_mux, pPktinfo->StationID, pPhyInfo->RxPWDBAll);
}
}
}
/* Smart Antenna Debug Message------------------ */
UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
if (!isCCKrate) { /* ofdm rate */
if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
} else {
if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
} else {
RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
}
if ((RSSI_max - RSSI_min) < 3)
RSSI_Ave = RSSI_max;
else if ((RSSI_max - RSSI_min) < 6)
RSSI_Ave = RSSI_max - 1;
else if ((RSSI_max - RSSI_min) < 10)
RSSI_Ave = RSSI_max - 2;
else
RSSI_Ave = RSSI_max - 3;
}
/* 1 Process OFDM RSSI */
if (UndecoratedSmoothedOFDM <= 0) { /* initialize */
UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
} else {
if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
UndecoratedSmoothedOFDM =
(((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) +
(RSSI_Ave)) / (Rx_Smooth_Factor);
UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
} else {
UndecoratedSmoothedOFDM =
(((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) +
(RSSI_Ave)) / (Rx_Smooth_Factor);
}
}
pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0;
} else {
RSSI_Ave = pPhyInfo->RxPWDBAll;
/* 1 Process CCK RSSI */
if (UndecoratedSmoothedCCK <= 0) { /* initialize */
UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
} else {
if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
UndecoratedSmoothedCCK =
((UndecoratedSmoothedCCK * (Rx_Smooth_Factor-1)) +
pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
} else {
UndecoratedSmoothedCCK =
((UndecoratedSmoothedCCK * (Rx_Smooth_Factor-1)) +
pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
}
}
pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1;
}
/* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
if (pEntry->rssi_stat.ValidBit >= 64)
pEntry->rssi_stat.ValidBit = 64;
else
pEntry->rssi_stat.ValidBit++;
for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0;
if (pEntry->rssi_stat.ValidBit == 64) {
Weighting = ((OFDM_pkt<<4) > 64) ? 64 : (OFDM_pkt<<4);
UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6;
} else {
if (pEntry->rssi_stat.ValidBit != 0)
UndecoratedSmoothedPWDB = (OFDM_pkt * UndecoratedSmoothedOFDM +
(pEntry->rssi_stat.ValidBit-OFDM_pkt) *
UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit;
else
UndecoratedSmoothedPWDB = 0;
}
pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
}
}
/* Endianness before calling this API */
static void ODM_PhyStatusQuery_92CSeries(struct odm_dm_struct *dm_odm,
struct odm_phy_status_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_per_pkt_info *pPktinfo,
struct adapter *adapt)
{
odm_RxPhyStatus92CSeries_Parsing(dm_odm, pPhyInfo, pPhyStatus,
pPktinfo, adapt);
if (dm_odm->RSSI_test) {
/* Select the packets to do RSSI checking for antenna switching. */
if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon)
ODM_SwAntDivChkPerPktRssi(dm_odm, pPktinfo->StationID, pPhyInfo);
} else {
odm_Process_RSSIForDM(dm_odm, pPhyInfo, pPktinfo);
}
}
void ODM_PhyStatusQuery(struct odm_dm_struct *dm_odm,
struct odm_phy_status_info *pPhyInfo,
u8 *pPhyStatus, struct odm_per_pkt_info *pPktinfo,
struct adapter *adapt)
{
ODM_PhyStatusQuery_92CSeries(dm_odm, pPhyInfo, pPhyStatus, pPktinfo, adapt);
}
/* For future use. */
void ODM_MacStatusQuery(struct odm_dm_struct *dm_odm, u8 *mac_stat,
u8 macid, bool pkt_match_bssid,
bool pkttoself, bool pkt_beacon)
{
/* 2011/10/19 Driver team will handle in the future. */
}
enum HAL_STATUS ODM_ConfigRFWithHeaderFile(struct odm_dm_struct *dm_odm,
enum rf_radio_path content,
enum rf_radio_path rfpath)
{
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("===>ODM_ConfigRFWithHeaderFile\n"));
if (dm_odm->SupportICType == ODM_RTL8188E) {
if (rfpath == RF_PATH_A)
READ_AND_CONFIG(8188E, _RadioA_1T_);
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, (" ===> ODM_ConfigRFWithHeaderFile() Radio_A:Rtl8188ERadioA_1TArray\n"));
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, (" ===> ODM_ConfigRFWithHeaderFile() Radio_B:Rtl8188ERadioB_1TArray\n"));
}
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("ODM_ConfigRFWithHeaderFile: Radio No %x\n", rfpath));
return HAL_STATUS_SUCCESS;
}
enum HAL_STATUS ODM_ConfigBBWithHeaderFile(struct odm_dm_struct *dm_odm,
enum odm_bb_config_type config_tp)
{
if (dm_odm->SupportICType == ODM_RTL8188E) {
if (config_tp == CONFIG_BB_PHY_REG) {
READ_AND_CONFIG(8188E, _PHY_REG_1T_);
} else if (config_tp == CONFIG_BB_AGC_TAB) {
READ_AND_CONFIG(8188E, _AGC_TAB_1T_);
} else if (config_tp == CONFIG_BB_PHY_REG_PG) {
READ_AND_CONFIG(8188E, _PHY_REG_PG_);
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> phy_ConfigBBWithHeaderFile() agc:Rtl8188EPHY_REG_PGArray\n"));
}
}
return HAL_STATUS_SUCCESS;
}
enum HAL_STATUS ODM_ConfigMACWithHeaderFile(struct odm_dm_struct *dm_odm)
{
u8 result = HAL_STATUS_SUCCESS;
if (dm_odm->SupportICType == ODM_RTL8188E)
result = READ_AND_CONFIG(8188E, _MAC_REG_);
return result;
}

View File

@ -0,0 +1,400 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
void ODM_DIG_LowerBound_88E(struct odm_dm_struct *dm_odm)
{
struct rtw_dig *pDM_DigTable = &dm_odm->DM_DigTable;
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
pDM_DigTable->rx_gain_range_min = (u8) pDM_DigTable->AntDiv_RSSI_max;
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("ODM_DIG_LowerBound_88E(): pDM_DigTable->AntDiv_RSSI_max=%d\n", pDM_DigTable->AntDiv_RSSI_max));
}
/* If only one Entry connected */
}
static void odm_RX_HWAntDivInit(struct odm_dm_struct *dm_odm)
{
u32 value32;
if (*(dm_odm->mp_mode) == 1) {
dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT7, 0); /* disable HW AntDiv */
ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT31, 1); /* 1:CG, 0:CS */
return;
}
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_RX_HWAntDivInit()\n"));
/* MAC Setting */
value32 = ODM_GetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
ODM_SetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord, value32|(BIT23|BIT25)); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */
/* Pin Settings */
ODM_SetBBReg(dm_odm, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0); /* Reg864[10]=1'b0 antsel2 by HW */
ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT22, 1); /* Regb2c[22]=1'b0 disable CS/CG switch */
ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT31, 1); /* Regb2c[31]=1'b1 output at CG only */
/* OFDM Settings */
ODM_SetBBReg(dm_odm, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord, 0x000000a0);
/* CCK Settings */
ODM_SetBBReg(dm_odm, ODM_REG_BB_PWR_SAV4_11N, BIT7, 1); /* Fix CCK PHY status report issue */
ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1); /* CCK complete HW AntDiv within 64 samples */
ODM_UpdateRxIdleAnt_88E(dm_odm, MAIN_ANT);
ODM_SetBBReg(dm_odm, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201); /* antenna mapping table */
}
static void odm_TRX_HWAntDivInit(struct odm_dm_struct *dm_odm)
{
u32 value32;
if (*(dm_odm->mp_mode) == 1) {
dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT7, 0); /* disable HW AntDiv */
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT5|BIT4|BIT3, 0); /* Default RX (0/1) */
return;
}
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_TRX_HWAntDivInit()\n"));
/* MAC Setting */
value32 = ODM_GetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
ODM_SetMACReg(dm_odm, ODM_REG_ANTSEL_PIN_11N, bMaskDWord, value32|(BIT23|BIT25)); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */
/* Pin Settings */
ODM_SetBBReg(dm_odm, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0); /* Reg864[10]=1'b0 antsel2 by HW */
ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT22, 0); /* Regb2c[22]=1'b0 disable CS/CG switch */
ODM_SetBBReg(dm_odm, ODM_REG_LNA_SWITCH_11N, BIT31, 1); /* Regb2c[31]=1'b1 output at CG only */
/* OFDM Settings */
ODM_SetBBReg(dm_odm, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord, 0x000000a0);
/* CCK Settings */
ODM_SetBBReg(dm_odm, ODM_REG_BB_PWR_SAV4_11N, BIT7, 1); /* Fix CCK PHY status report issue */
ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1); /* CCK complete HW AntDiv within 64 samples */
/* Tx Settings */
ODM_SetBBReg(dm_odm, ODM_REG_TX_ANT_CTRL_11N, BIT21, 0); /* Reg80c[21]=1'b0 from TX Reg */
ODM_UpdateRxIdleAnt_88E(dm_odm, MAIN_ANT);
/* antenna mapping table */
if (!dm_odm->bIsMPChip) { /* testchip */
ODM_SetBBReg(dm_odm, ODM_REG_RX_DEFUALT_A_11N, BIT10|BIT9|BIT8, 1); /* Reg858[10:8]=3'b001 */
ODM_SetBBReg(dm_odm, ODM_REG_RX_DEFUALT_A_11N, BIT13|BIT12|BIT11, 2); /* Reg858[13:11]=3'b010 */
} else { /* MPchip */
ODM_SetBBReg(dm_odm, ODM_REG_ANT_MAPPING1_11N, bMaskDWord, 0x0201); /* Reg914=3'b010, Reg915=3'b001 */
}
}
static void odm_FastAntTrainingInit(struct odm_dm_struct *dm_odm)
{
u32 value32, i;
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
u32 AntCombination = 2;
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("odm_FastAntTrainingInit()\n"));
if (*(dm_odm->mp_mode) == 1) {
ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD, ("dm_odm->AntDivType: %d\n", dm_odm->AntDivType));
return;
}
for (i = 0; i < 6; i++) {
dm_fat_tbl->Bssid[i] = 0;
dm_fat_tbl->antSumRSSI[i] = 0;
dm_fat_tbl->antRSSIcnt[i] = 0;
dm_fat_tbl->antAveRSSI[i] = 0;
}
dm_fat_tbl->TrainIdx = 0;
dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
/* MAC Setting */
value32 = ODM_GetMACReg(dm_odm, 0x4c, bMaskDWord);
ODM_SetMACReg(dm_odm, 0x4c, bMaskDWord, value32|(BIT23|BIT25)); /* Reg4C[25]=1, Reg4C[23]=1 for pin output */
value32 = ODM_GetMACReg(dm_odm, 0x7B4, bMaskDWord);
ODM_SetMACReg(dm_odm, 0x7b4, bMaskDWord, value32|(BIT16|BIT17)); /* Reg7B4[16]=1 enable antenna training, Reg7B4[17]=1 enable A2 match */
/* Match MAC ADDR */
ODM_SetMACReg(dm_odm, 0x7b4, 0xFFFF, 0);
ODM_SetMACReg(dm_odm, 0x7b0, bMaskDWord, 0);
ODM_SetBBReg(dm_odm, 0x870, BIT9|BIT8, 0);/* Reg870[8]=1'b0, Reg870[9]=1'b0 antsel antselb by HW */
ODM_SetBBReg(dm_odm, 0x864, BIT10, 0); /* Reg864[10]=1'b0 antsel2 by HW */
ODM_SetBBReg(dm_odm, 0xb2c, BIT22, 0); /* Regb2c[22]=1'b0 disable CS/CG switch */
ODM_SetBBReg(dm_odm, 0xb2c, BIT31, 1); /* Regb2c[31]=1'b1 output at CG only */
ODM_SetBBReg(dm_odm, 0xca4, bMaskDWord, 0x000000a0);
/* antenna mapping table */
if (AntCombination == 2) {
if (!dm_odm->bIsMPChip) { /* testchip */
ODM_SetBBReg(dm_odm, 0x858, BIT10|BIT9|BIT8, 1); /* Reg858[10:8]=3'b001 */
ODM_SetBBReg(dm_odm, 0x858, BIT13|BIT12|BIT11, 2); /* Reg858[13:11]=3'b010 */
} else { /* MPchip */
ODM_SetBBReg(dm_odm, 0x914, bMaskByte0, 1);
ODM_SetBBReg(dm_odm, 0x914, bMaskByte1, 2);
}
} else if (AntCombination == 7) {
if (!dm_odm->bIsMPChip) { /* testchip */
ODM_SetBBReg(dm_odm, 0x858, BIT10|BIT9|BIT8, 0); /* Reg858[10:8]=3'b000 */
ODM_SetBBReg(dm_odm, 0x858, BIT13|BIT12|BIT11, 1); /* Reg858[13:11]=3'b001 */
ODM_SetBBReg(dm_odm, 0x878, BIT16, 0);
ODM_SetBBReg(dm_odm, 0x858, BIT15|BIT14, 2); /* Reg878[0],Reg858[14:15])=3'b010 */
ODM_SetBBReg(dm_odm, 0x878, BIT19|BIT18|BIT17, 3);/* Reg878[3:1]=3b'011 */
ODM_SetBBReg(dm_odm, 0x878, BIT22|BIT21|BIT20, 4);/* Reg878[6:4]=3b'100 */
ODM_SetBBReg(dm_odm, 0x878, BIT25|BIT24|BIT23, 5);/* Reg878[9:7]=3b'101 */
ODM_SetBBReg(dm_odm, 0x878, BIT28|BIT27|BIT26, 6);/* Reg878[12:10]=3b'110 */
ODM_SetBBReg(dm_odm, 0x878, BIT31|BIT30|BIT29, 7);/* Reg878[15:13]=3b'111 */
} else { /* MPchip */
ODM_SetBBReg(dm_odm, 0x914, bMaskByte0, 0);
ODM_SetBBReg(dm_odm, 0x914, bMaskByte1, 1);
ODM_SetBBReg(dm_odm, 0x914, bMaskByte2, 2);
ODM_SetBBReg(dm_odm, 0x914, bMaskByte3, 3);
ODM_SetBBReg(dm_odm, 0x918, bMaskByte0, 4);
ODM_SetBBReg(dm_odm, 0x918, bMaskByte1, 5);
ODM_SetBBReg(dm_odm, 0x918, bMaskByte2, 6);
ODM_SetBBReg(dm_odm, 0x918, bMaskByte3, 7);
}
}
/* Default Ant Setting when no fast training */
ODM_SetBBReg(dm_odm, 0x80c, BIT21, 1); /* Reg80c[21]=1'b1 from TX Info */
ODM_SetBBReg(dm_odm, 0x864, BIT5|BIT4|BIT3, 0); /* Default RX */
ODM_SetBBReg(dm_odm, 0x864, BIT8|BIT7|BIT6, 1); /* Optional RX */
/* Enter Traing state */
ODM_SetBBReg(dm_odm, 0x864, BIT2|BIT1|BIT0, (AntCombination-1)); /* Reg864[2:0]=3'd6 ant combination=reg864[2:0]+1 */
ODM_SetBBReg(dm_odm, 0xc50, BIT7, 1); /* RegC50[7]=1'b1 enable HW AntDiv */
}
void ODM_AntennaDiversityInit_88E(struct odm_dm_struct *dm_odm)
{
if (dm_odm->SupportICType != ODM_RTL8188E)
return;
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("dm_odm->AntDivType=%d\n", dm_odm->AntDivType));
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("dm_odm->bIsMPChip=%s\n", (dm_odm->bIsMPChip ? "true" : "false")));
if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
odm_RX_HWAntDivInit(dm_odm);
else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
odm_TRX_HWAntDivInit(dm_odm);
else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
odm_FastAntTrainingInit(dm_odm);
}
void ODM_UpdateRxIdleAnt_88E(struct odm_dm_struct *dm_odm, u8 Ant)
{
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
u32 DefaultAnt, OptionalAnt;
if (dm_fat_tbl->RxIdleAnt != Ant) {
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Need to Update Rx Idle Ant\n"));
if (Ant == MAIN_ANT) {
DefaultAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
OptionalAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
} else {
DefaultAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
OptionalAnt = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
}
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT5|BIT4|BIT3, DefaultAnt); /* Default RX */
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT8|BIT7|BIT6, OptionalAnt); /* Optional RX */
ODM_SetBBReg(dm_odm, ODM_REG_ANTSEL_CTRL_11N, BIT14|BIT13|BIT12, DefaultAnt); /* Default TX */
ODM_SetMACReg(dm_odm, ODM_REG_RESP_TX_11N, BIT6|BIT7, DefaultAnt); /* Resp Tx */
} else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT5|BIT4|BIT3, DefaultAnt); /* Default RX */
ODM_SetBBReg(dm_odm, ODM_REG_RX_ANT_CTRL_11N, BIT8|BIT7|BIT6, OptionalAnt); /* Optional RX */
}
}
dm_fat_tbl->RxIdleAnt = Ant;
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("RxIdleAnt=%s\n", (Ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT"));
if (Ant != MAIN_ANT)
pr_info("RxIdleAnt=AUX_ANT\n");
}
static void odm_UpdateTxAnt_88E(struct odm_dm_struct *dm_odm, u8 Ant, u32 MacId)
{
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
u8 TargetAnt;
if (Ant == MAIN_ANT)
TargetAnt = MAIN_ANT_CG_TRX;
else
TargetAnt = AUX_ANT_CG_TRX;
dm_fat_tbl->antsel_a[MacId] = TargetAnt&BIT0;
dm_fat_tbl->antsel_b[MacId] = (TargetAnt&BIT1)>>1;
dm_fat_tbl->antsel_c[MacId] = (TargetAnt&BIT2)>>2;
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("Tx from TxInfo, TargetAnt=%s\n",
(Ant == MAIN_ANT) ? "MAIN_ANT" : "AUX_ANT"));
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("antsel_tr_mux=3'b%d%d%d\n",
dm_fat_tbl->antsel_c[MacId], dm_fat_tbl->antsel_b[MacId], dm_fat_tbl->antsel_a[MacId]));
}
void ODM_SetTxAntByTxInfo_88E(struct odm_dm_struct *dm_odm, u8 *pDesc, u8 macId)
{
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
SET_TX_DESC_ANTSEL_A_88E(pDesc, dm_fat_tbl->antsel_a[macId]);
SET_TX_DESC_ANTSEL_B_88E(pDesc, dm_fat_tbl->antsel_b[macId]);
SET_TX_DESC_ANTSEL_C_88E(pDesc, dm_fat_tbl->antsel_c[macId]);
}
}
void ODM_AntselStatistics_88E(struct odm_dm_struct *dm_odm, u8 antsel_tr_mux, u32 MacId, u8 RxPWDBAll)
{
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
dm_fat_tbl->MainAnt_Sum[MacId] += RxPWDBAll;
dm_fat_tbl->MainAnt_Cnt[MacId]++;
} else {
dm_fat_tbl->AuxAnt_Sum[MacId] += RxPWDBAll;
dm_fat_tbl->AuxAnt_Cnt[MacId]++;
}
} else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
dm_fat_tbl->MainAnt_Sum[MacId] += RxPWDBAll;
dm_fat_tbl->MainAnt_Cnt[MacId]++;
} else {
dm_fat_tbl->AuxAnt_Sum[MacId] += RxPWDBAll;
dm_fat_tbl->AuxAnt_Cnt[MacId]++;
}
}
}
static void odm_HWAntDiv(struct odm_dm_struct *dm_odm)
{
u32 i, MinRSSI = 0xFF, AntDivMaxRSSI = 0, MaxRSSI = 0, LocalMinRSSI, LocalMaxRSSI;
u32 Main_RSSI, Aux_RSSI;
u8 RxIdleAnt = 0, TargetAnt = 7;
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
struct rtw_dig *pDM_DigTable = &dm_odm->DM_DigTable;
struct sta_info *pEntry;
for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
pEntry = dm_odm->pODM_StaInfo[i];
if (IS_STA_VALID(pEntry)) {
/* 2 Caculate RSSI per Antenna */
Main_RSSI = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ? (dm_fat_tbl->MainAnt_Sum[i]/dm_fat_tbl->MainAnt_Cnt[i]) : 0;
Aux_RSSI = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ? (dm_fat_tbl->AuxAnt_Sum[i]/dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
TargetAnt = (Main_RSSI >= Aux_RSSI) ? MAIN_ANT : AUX_ANT;
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("MacID=%d, MainAnt_Sum=%d, MainAnt_Cnt=%d\n",
i, dm_fat_tbl->MainAnt_Sum[i],
dm_fat_tbl->MainAnt_Cnt[i]));
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("MacID=%d, AuxAnt_Sum=%d, AuxAnt_Cnt=%d\n",
i, dm_fat_tbl->AuxAnt_Sum[i], dm_fat_tbl->AuxAnt_Cnt[i]));
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
("MacID=%d, Main_RSSI= %d, Aux_RSSI= %d\n",
i, Main_RSSI, Aux_RSSI));
/* 2 Select MaxRSSI for DIG */
LocalMaxRSSI = (Main_RSSI > Aux_RSSI) ? Main_RSSI : Aux_RSSI;
if ((LocalMaxRSSI > AntDivMaxRSSI) && (LocalMaxRSSI < 40))
AntDivMaxRSSI = LocalMaxRSSI;
if (LocalMaxRSSI > MaxRSSI)
MaxRSSI = LocalMaxRSSI;
/* 2 Select RX Idle Antenna */
if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) && (Main_RSSI == 0))
Main_RSSI = Aux_RSSI;
else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) && (Aux_RSSI == 0))
Aux_RSSI = Main_RSSI;
LocalMinRSSI = (Main_RSSI > Aux_RSSI) ? Aux_RSSI : Main_RSSI;
if (LocalMinRSSI < MinRSSI) {
MinRSSI = LocalMinRSSI;
RxIdleAnt = TargetAnt;
}
/* 2 Select TRX Antenna */
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
odm_UpdateTxAnt_88E(dm_odm, TargetAnt, i);
}
dm_fat_tbl->MainAnt_Sum[i] = 0;
dm_fat_tbl->AuxAnt_Sum[i] = 0;
dm_fat_tbl->MainAnt_Cnt[i] = 0;
dm_fat_tbl->AuxAnt_Cnt[i] = 0;
}
/* 2 Set RX Idle Antenna */
ODM_UpdateRxIdleAnt_88E(dm_odm, RxIdleAnt);
pDM_DigTable->AntDiv_RSSI_max = AntDivMaxRSSI;
pDM_DigTable->RSSI_max = MaxRSSI;
}
void ODM_AntennaDiversity_88E(struct odm_dm_struct *dm_odm)
{
struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
if ((dm_odm->SupportICType != ODM_RTL8188E) || (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV)))
return;
if (!dm_odm->bLinked) {
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_AntennaDiversity_88E(): No Link.\n"));
if (dm_fat_tbl->bBecomeLinked) {
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Need to Turn off HW AntDiv\n"));
ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT7, 0); /* RegC50[7]=1'b1 enable HW AntDiv */
ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT15, 0); /* Enable CCK AntDiv */
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
ODM_SetBBReg(dm_odm, ODM_REG_TX_ANT_CTRL_11N, BIT21, 0); /* Reg80c[21]=1'b0 from TX Reg */
dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
}
return;
} else {
if (!dm_fat_tbl->bBecomeLinked) {
ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Need to Turn on HW AntDiv\n"));
/* Because HW AntDiv is disabled before Link, we enable HW AntDiv after link */
ODM_SetBBReg(dm_odm, ODM_REG_IGI_A_11N, BIT7, 1); /* RegC50[7]=1'b1 enable HW AntDiv */
ODM_SetBBReg(dm_odm, ODM_REG_CCK_ANTDIV_PARA1_11N, BIT15, 1); /* Enable CCK AntDiv */
if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
ODM_SetBBReg(dm_odm, ODM_REG_TX_ANT_CTRL_11N, BIT21, 1); /* Reg80c[21]=1'b1 from TX Info */
dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
}
}
if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
odm_HWAntDiv(dm_odm);
}
/* 3============================================================ */
/* 3 Dynamic Primary CCA */
/* 3============================================================ */
void odm_PrimaryCCA_Init(struct odm_dm_struct *dm_odm)
{
struct dyn_primary_cca *PrimaryCCA = &(dm_odm->DM_PriCCA);
PrimaryCCA->DupRTS_flag = 0;
PrimaryCCA->intf_flag = 0;
PrimaryCCA->intf_type = 0;
PrimaryCCA->Monitor_flag = 0;
PrimaryCCA->PriCCA_flag = 0;
}
bool ODM_DynamicPrimaryCCA_DupRTS(struct odm_dm_struct *dm_odm)
{
struct dyn_primary_cca *PrimaryCCA = &(dm_odm->DM_PriCCA);
return PrimaryCCA->DupRTS_flag;
}
void odm_DynamicPrimaryCCA(struct odm_dm_struct *dm_odm)
{
return;
}

View File

@ -0,0 +1,130 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
void odm_ConfigRFReg_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
u32 Data, enum rf_radio_path RF_PATH,
u32 RegAddr)
{
if (Addr == 0xffe) {
ODM_sleep_ms(50);
} else if (Addr == 0xfd) {
ODM_delay_ms(5);
} else if (Addr == 0xfc) {
ODM_delay_ms(1);
} else if (Addr == 0xfb) {
ODM_delay_us(50);
} else if (Addr == 0xfa) {
ODM_delay_us(5);
} else if (Addr == 0xf9) {
ODM_delay_us(1);
} else {
ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
/* Add 1us delay between BB/RF register setting. */
ODM_delay_us(1);
}
}
void odm_ConfigRF_RadioA_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data)
{
u32 content = 0x1000; /* RF_Content: radioa_txt */
u32 maskforPhySet = (u32)(content&0xE000);
odm_ConfigRFReg_8188E(pDM_Odm, Addr, Data, RF_PATH_A, Addr|maskforPhySet);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> ODM_ConfigRFWithHeaderFile: [RadioA] %08X %08X\n", Addr, Data));
}
void odm_ConfigRF_RadioB_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Data)
{
u32 content = 0x1001; /* RF_Content: radiob_txt */
u32 maskforPhySet = (u32)(content&0xE000);
odm_ConfigRFReg_8188E(pDM_Odm, Addr, Data, RF_PATH_B, Addr|maskforPhySet);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> ODM_ConfigRFWithHeaderFile: [RadioB] %08X %08X\n", Addr, Data));
}
void odm_ConfigMAC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u8 Data)
{
ODM_Write1Byte(pDM_Odm, Addr, Data);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE, ("===> ODM_ConfigMACWithHeaderFile: [MAC_REG] %08X %08X\n", Addr, Data));
}
void odm_ConfigBB_AGC_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data)
{
ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
/* Add 1us delay between BB/RF register setting. */
ODM_delay_us(1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE,
("===> ODM_ConfigBBWithHeaderFile: [AGC_TAB] %08X %08X\n",
Addr, Data));
}
void odm_ConfigBB_PHY_REG_PG_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr,
u32 Bitmask, u32 Data)
{
if (Addr == 0xfe) {
ODM_sleep_ms(50);
} else if (Addr == 0xfd) {
ODM_delay_ms(5);
} else if (Addr == 0xfc) {
ODM_delay_ms(1);
} else if (Addr == 0xfb) {
ODM_delay_us(50);
} else if (Addr == 0xfa) {
ODM_delay_us(5);
} else if (Addr == 0xf9) {
ODM_delay_us(1);
} else{
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> @@@@@@@ ODM_ConfigBBWithHeaderFile: [PHY_REG] %08X %08X %08X\n",
Addr, Bitmask, Data));
storePwrIndexDiffRateOffset(pDM_Odm->Adapter, Addr, Bitmask, Data);
}
}
void odm_ConfigBB_PHY_8188E(struct odm_dm_struct *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data)
{
if (Addr == 0xfe) {
ODM_sleep_ms(50);
} else if (Addr == 0xfd) {
ODM_delay_ms(5);
} else if (Addr == 0xfc) {
ODM_delay_ms(1);
} else if (Addr == 0xfb) {
ODM_delay_us(50);
} else if (Addr == 0xfa) {
ODM_delay_us(5);
} else if (Addr == 0xf9) {
ODM_delay_us(1);
} else {
if (Addr == 0xa24)
pDM_Odm->RFCalibrateInfo.RegA24 = Data;
ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
/* Add 1us delay between BB/RF register setting. */
ODM_delay_us(1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE,
("===> ODM_ConfigBBWithHeaderFile: [PHY_REG] %08X %08X\n",
Addr, Data));
}
}

View File

@ -0,0 +1,32 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
/* include files */
#include "odm_precomp.h"
void ODM_InitDebugSetting(struct odm_dm_struct *pDM_Odm)
{
pDM_Odm->DebugLevel = ODM_DBG_TRACE;
pDM_Odm->DebugComponents = 0;
}
u32 GlobalDebugLevel;

View File

@ -0,0 +1,205 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include "odm_precomp.h"
/* ODM IO Relative API. */
u8 ODM_Read1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
{
struct adapter *Adapter = pDM_Odm->Adapter;
return rtw_read8(Adapter, RegAddr);
}
u16 ODM_Read2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
{
struct adapter *Adapter = pDM_Odm->Adapter;
return rtw_read16(Adapter, RegAddr);
}
u32 ODM_Read4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr)
{
struct adapter *Adapter = pDM_Odm->Adapter;
return rtw_read32(Adapter, RegAddr);
}
void ODM_Write1Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u8 Data)
{
struct adapter *Adapter = pDM_Odm->Adapter;
rtw_write8(Adapter, RegAddr, Data);
}
void ODM_Write2Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u16 Data)
{
struct adapter *Adapter = pDM_Odm->Adapter;
rtw_write16(Adapter, RegAddr, Data);
}
void ODM_Write4Byte(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 Data)
{
struct adapter *Adapter = pDM_Odm->Adapter;
rtw_write32(Adapter, RegAddr, Data);
}
void ODM_SetMACReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data)
{
struct adapter *Adapter = pDM_Odm->Adapter;
PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
}
u32 ODM_GetMACReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask)
{
struct adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
}
void ODM_SetBBReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data)
{
struct adapter *Adapter = pDM_Odm->Adapter;
PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
}
u32 ODM_GetBBReg(struct odm_dm_struct *pDM_Odm, u32 RegAddr, u32 BitMask)
{
struct adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
}
void ODM_SetRFReg(struct odm_dm_struct *pDM_Odm, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
{
struct adapter *Adapter = pDM_Odm->Adapter;
PHY_SetRFReg(Adapter, (enum rf_radio_path)eRFPath, RegAddr, BitMask, Data);
}
u32 ODM_GetRFReg(struct odm_dm_struct *pDM_Odm, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask)
{
struct adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryRFReg(Adapter, (enum rf_radio_path)eRFPath, RegAddr, BitMask);
}
/* ODM Memory relative API. */
void ODM_AllocateMemory(struct odm_dm_struct *pDM_Odm, void **pPtr, u32 length)
{
*pPtr = rtw_zvmalloc(length);
}
/* length could be ignored, used to detect memory leakage. */
void ODM_FreeMemory(struct odm_dm_struct *pDM_Odm, void *pPtr, u32 length)
{
rtw_vmfree(pPtr, length);
}
s32 ODM_CompareMemory(struct odm_dm_struct *pDM_Odm, void *pBuf1, void *pBuf2, u32 length)
{
return !memcmp(pBuf1, pBuf2, length);
}
/* ODM MISC relative API. */
void ODM_AcquireSpinLock(struct odm_dm_struct *pDM_Odm, enum RT_SPINLOCK_TYPE type)
{
}
void ODM_ReleaseSpinLock(struct odm_dm_struct *pDM_Odm, enum RT_SPINLOCK_TYPE type)
{
}
/* Work item relative API. FOr MP driver only~! */
void ODM_InitializeWorkItem(struct odm_dm_struct *pDM_Odm, void *pRtWorkItem,
RT_WORKITEM_CALL_BACK RtWorkItemCallback,
void *pContext, const char *szID)
{
}
void ODM_StartWorkItem(void *pRtWorkItem)
{
}
void ODM_StopWorkItem(void *pRtWorkItem)
{
}
void ODM_FreeWorkItem(void *pRtWorkItem)
{
}
void ODM_ScheduleWorkItem(void *pRtWorkItem)
{
}
void ODM_IsWorkItemScheduled(void *pRtWorkItem)
{
}
/* ODM Timer relative API. */
void ODM_StallExecution(u32 usDelay)
{
rtw_udelay_os(usDelay);
}
void ODM_delay_ms(u32 ms)
{
rtw_mdelay_os(ms);
}
void ODM_delay_us(u32 us)
{
rtw_udelay_os(us);
}
void ODM_sleep_ms(u32 ms)
{
rtw_msleep_os(ms);
}
void ODM_sleep_us(u32 us)
{
rtw_usleep_os(us);
}
void ODM_SetTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer, u32 msDelay)
{
_set_timer(pTimer, msDelay); /* ms */
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
void ODM_InitializeTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer,
void *CallBackFunc, void *pContext,
const char *szID)
{
struct adapter *Adapter = pDM_Odm->Adapter;
_init_timer(pTimer, Adapter->pnetdev, CallBackFunc, pDM_Odm);
}
#endif
void ODM_CancelTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer)
{
_cancel_timer_ex(pTimer);
}
void ODM_ReleaseTimer(struct odm_dm_struct *pDM_Odm, struct timer_list *pTimer)
{
}
/* ODM FW relative API. */
u32 ODM_FillH2CCmd(u8 *pH2CBuffer, u32 H2CBufferLen, u32 CmdNum,
u32 *pElementID, u32 *pCmdLen,
u8 **pCmbBuffer, u8 *CmdStartSeq)
{
return true;
}

View File

@ -0,0 +1,762 @@
/******************************************************************************
*
* 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_CMD_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <cmd_osdep.h>
#include <mlme_osdep.h>
#include <rtw_ioctl_set.h>
#include <rtl8188e_hal.h>
#define RTL88E_MAX_H2C_BOX_NUMS 4
#define RTL88E_MAX_CMD_LEN 7
#define RTL88E_MESSAGE_BOX_SIZE 4
#define RTL88E_EX_MESSAGE_BOX_SIZE 4
static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
{
u8 read_down = false;
int retry_cnts = 100;
u8 valid;
do {
valid = rtw_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
if (0 == valid)
read_down = true;
} while ((!read_down) && (retry_cnts--));
return read_down;
}
/*****************************************
* H2C Msg format :
* 0x1DF - 0x1D0
*| 31 - 8 | 7-5 4 - 0 |
*| h2c_msg |Class_ID CMD_ID |
*
* Extend 0x1FF - 0x1F0
*|31 - 0 |
*|ext_msg|
******************************************/
static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
{
u8 bcmd_down = false;
s32 retry_cnts = 100;
u8 h2c_box_num;
u32 msgbox_addr;
u32 msgbox_ex_addr;
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
u8 cmd_idx, ext_cmd_len;
u32 h2c_cmd = 0;
u32 h2c_cmd_ex = 0;
s32 ret = _FAIL;
if (!adapt->bFWReady) {
DBG_88E("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n");
return ret;
}
if (!pCmdBuffer)
goto exit;
if (CmdLen > RTL88E_MAX_CMD_LEN)
goto exit;
if (adapt->bSurpriseRemoved)
goto exit;
/* pay attention to if race condition happened in H2C cmd setting. */
do {
h2c_box_num = haldata->LastHMEBoxNum;
if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) {
DBG_88E(" fw read cmd failed...\n");
goto exit;
}
*(u8 *)(&h2c_cmd) = ElementID;
if (CmdLen <= 3) {
memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
} else {
memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3);
ext_cmd_len = CmdLen-3;
memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, ext_cmd_len);
/* Write Ext command */
msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++) {
rtw_write8(adapt, msgbox_ex_addr+cmd_idx, *((u8 *)(&h2c_cmd_ex)+cmd_idx));
}
}
/* Write command */
msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++) {
rtw_write8(adapt, msgbox_addr+cmd_idx, *((u8 *)(&h2c_cmd)+cmd_idx));
}
bcmd_down = true;
haldata->LastHMEBoxNum = (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS;
} while ((!bcmd_down) && (retry_cnts--));
ret = _SUCCESS;
exit:
return ret;
}
u8 rtl8188e_set_rssi_cmd(struct adapter *adapt, u8 *param)
{
u8 res = _SUCCESS;
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
if (haldata->fw_ractrl) {
;
} else {
DBG_88E("==>%s fw dont support RA\n", __func__);
res = _FAIL;
}
return res;
}
u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask)
{
u8 buf[3];
u8 res = _SUCCESS;
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
if (haldata->fw_ractrl) {
__le32 lmask;
memset(buf, 0, 3);
lmask = cpu_to_le32(mask);
memcpy(buf, &lmask, 3);
FillH2CCmd_88E(adapt, H2C_DM_MACID_CFG, 3, buf);
} else {
DBG_88E("==>%s fw dont support RA\n", __func__);
res = _FAIL;
}
return res;
}
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
/* arg[0:4] = macid */
/* arg[5] = Short GI */
void rtl8188e_Add_RateATid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
{
struct hal_data_8188e *haldata = GET_HAL_DATA(pAdapter);
u8 macid, init_rate, raid, shortGIrate = false;
macid = arg&0x1f;
raid = (bitmap>>28) & 0x0f;
bitmap &= 0x0fffffff;
if (rssi_level != DM_RATR_STA_INIT)
bitmap = ODM_Get_Rate_Bitmap(&haldata->odmpriv, macid, bitmap, rssi_level);
bitmap |= ((raid<<28)&0xf0000000);
init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
shortGIrate = (arg&BIT(5)) ? true : false;
if (shortGIrate)
init_rate |= BIT(6);
raid = (bitmap>>28) & 0x0f;
bitmap &= 0x0fffffff;
DBG_88E("%s=> mac_id:%d, raid:%d, ra_bitmap=0x%x, shortGIrate=0x%02x\n",
__func__, macid, raid, bitmap, shortGIrate);
ODM_RA_UpdateRateInfo_8188E(&(haldata->odmpriv), macid, raid, bitmap, shortGIrate);
}
void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
{
struct setpwrmode_parm H2CSetPwrMode;
struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv;
u8 RLBM = 0; /* 0:Min, 1:Max, 2:User define */
DBG_88E("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__,
Mode, pwrpriv->smart_ps, adapt->registrypriv.uapsd_enable);
switch (Mode) {
case PS_MODE_ACTIVE:
H2CSetPwrMode.Mode = 0;
break;
case PS_MODE_MIN:
H2CSetPwrMode.Mode = 1;
break;
case PS_MODE_MAX:
RLBM = 1;
H2CSetPwrMode.Mode = 1;
break;
case PS_MODE_DTIM:
RLBM = 2;
H2CSetPwrMode.Mode = 1;
break;
case PS_MODE_UAPSD_WMM:
H2CSetPwrMode.Mode = 2;
break;
default:
H2CSetPwrMode.Mode = 0;
break;
}
H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps<<4)&0xf0) | (RLBM & 0x0f));
H2CSetPwrMode.AwakeInterval = 1;
H2CSetPwrMode.bAllQueueUAPSD = adapt->registrypriv.uapsd_enable;
if (Mode > 0)
H2CSetPwrMode.PwrState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
else
H2CSetPwrMode.PwrState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
FillH2CCmd_88E(adapt, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
}
void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt)
{
u8 opmode, macid;
u16 mst_rpt = le16_to_cpu(mstatus_rpt);
opmode = (u8) mst_rpt;
macid = (u8)(mst_rpt >> 8);
DBG_88E("### %s: MStatus=%x MACID=%d\n", __func__, opmode, macid);
FillH2CCmd_88E(adapt, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt);
}
static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
{
struct rtw_ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u32 rate_len, pktlen;
struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
fctrl = &(pwlanhdr->frame_ctl);
*(fctrl) = 0;
memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN);
memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
SetFrameSubType(pframe, WIFI_BEACON);
pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
/* timestamp will be inserted by hardware */
pframe += 8;
pktlen += 8;
/* beacon interval: 2 bytes */
memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
/* capability info: 2 bytes */
memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ie);
memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fixed_ie), pktlen);
goto _ConstructBeacon;
}
/* below for ad-hoc mode */
/* SSID */
pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
/* DS parameter set */
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
u32 ATIMWindow;
/* IBSS Parameter Set... */
ATIMWindow = 0;
pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
}
/* todo: ERP IE */
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8)
pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
/* todo:HT for adhoc */
_ConstructBeacon:
if ((pktlen + TXDESC_SIZE) > 512) {
DBG_88E("beacon frame too large\n");
return;
}
*pLength = pktlen;
}
static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength)
{
struct rtw_ieee80211_hdr *pwlanhdr;
struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
__le16 *fctrl;
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
/* Frame control. */
fctrl = &(pwlanhdr->frame_ctl);
*(fctrl) = 0;
SetPwrMgt(fctrl);
SetFrameSubType(pframe, WIFI_PSPOLL);
/* AID. */
SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
/* BSSID. */
memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
/* TA. */
memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN);
*pLength = 16;
}
static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
u32 *pLength,
u8 *StaAddr,
u8 bQoS,
u8 AC,
u8 bEosp,
u8 bForcePowerSave)
{
struct rtw_ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u32 pktlen;
struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
struct wlan_network *cur_network = &pmlmepriv->cur_network;
struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
fctrl = &pwlanhdr->frame_ctl;
*(fctrl) = 0;
if (bForcePowerSave)
SetPwrMgt(fctrl);
switch (cur_network->network.InfrastructureMode) {
case Ndis802_11Infrastructure:
SetToDs(fctrl);
memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN);
memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
break;
case Ndis802_11APMode:
SetFrDs(fctrl);
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
memcpy(pwlanhdr->addr3, myid(&(adapt->eeprompriv)), ETH_ALEN);
break;
case Ndis802_11IBSS:
default:
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN);
memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
break;
}
SetSeqNum(pwlanhdr, 0);
if (bQoS) {
struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe;
SetPriority(&pwlanqoshdr->qc, AC);
SetEOSP(&pwlanqoshdr->qc, bEosp);
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
} else {
SetFrameSubType(pframe, WIFI_DATA_NULL);
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
}
*pLength = pktlen;
}
static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
{
struct rtw_ieee80211_hdr *pwlanhdr;
__le16 *fctrl;
u8 *mac, *bssid;
u32 pktlen;
struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
mac = myid(&(adapt->eeprompriv));
bssid = cur_network->MacAddress;
fctrl = &(pwlanhdr->frame_ctl);
*(fctrl) = 0;
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
SetSeqNum(pwlanhdr, 0);
SetFrameSubType(fctrl, WIFI_PROBERSP);
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
pframe += pktlen;
if (cur_network->IELength > MAX_IE_SZ)
return;
memcpy(pframe, cur_network->IEs, cur_network->IELength);
pframe += cur_network->IELength;
pktlen += cur_network->IELength;
*pLength = pktlen;
}
/* To check if reserved page content is destroyed by beacon because beacon is too large. */
/* 2010.06.23. Added by tynli. */
void CheckFwRsvdPageContent(struct adapter *Adapter)
{
}
/* */
/* Description: Fill the reserved packets that FW will use to RSVD page. */
/* Now we just send 4 types packet to rsvd page. */
/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
/* Input: */
/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
/* so we need to set the packet length to total length. */
/* true: At the second time, we should send the first packet (default:beacon) */
/* to Hw again and set the length in descriptor to the real beacon length. */
/* 2009.10.15 by tynli. */
static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
{
struct hal_data_8188e *haldata;
struct xmit_frame *pmgntframe;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
struct mlme_ext_priv *pmlmeext;
struct mlme_ext_info *pmlmeinfo;
u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
u32 NullDataLength, QosNullLength;
u8 *ReservedPagePacket;
u8 PageNum, PageNeed, TxDescLen;
u16 BufIndex;
u32 TotalPacketLen;
struct rsvdpage_loc RsvdPageLoc;
DBG_88E("%s\n", __func__);
ReservedPagePacket = (u8 *)rtw_zmalloc(1000);
if (ReservedPagePacket == NULL) {
DBG_88E("%s: alloc ReservedPagePacket fail!\n", __func__);
return;
}
haldata = GET_HAL_DATA(adapt);
pxmitpriv = &adapt->xmitpriv;
pmlmeext = &adapt->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
/* 3 (1) beacon * 2 pages */
BufIndex = TXDESC_OFFSET;
ConstructBeacon(adapt, &ReservedPagePacket[BufIndex], &BeaconLength);
/* When we count the first page size, we need to reserve description size for the RSVD */
/* packet, it will be filled in front of the packet in TXPKTBUF. */
PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
/* To reserved 2 pages for beacon buffer. 2010.06.24. */
if (PageNeed == 1)
PageNeed += 1;
PageNum += PageNeed;
haldata->FwRsvdPageStartOffset = PageNum;
BufIndex += PageNeed*128;
/* 3 (2) ps-poll *1 page */
RsvdPageLoc.LocPsPoll = PageNum;
ConstructPSPoll(adapt, &ReservedPagePacket[BufIndex], &PSPollLength);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (3) null data * 1 page */
RsvdPageLoc.LocNullData = PageNum;
ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, get_my_bssid(&pmlmeinfo->network), false, 0, 0, false);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (4) probe response * 1page */
RsvdPageLoc.LocProbeRsp = PageNum;
ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, get_my_bssid(&pmlmeinfo->network), false);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (5) Qos null data */
RsvdPageLoc.LocQosNull = PageNum;
ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex],
&QosNullLength, get_my_bssid(&pmlmeinfo->network), true, 0, 0, false);
rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
PageNum += PageNeed;
TotalPacketLen = BufIndex + QosNullLength;
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
if (pmgntframe == NULL)
goto exit;
/* update attribute */
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib(adapt, pattrib);
pattrib->qsel = 0x10;
pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
pattrib->pktlen = pattrib->last_txcmdsz;
memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
rtw_hal_mgnt_xmit(adapt, pmgntframe);
DBG_88E("%s: Set RSVD page location to Fw\n", __func__);
FillH2CCmd_88E(adapt, H2C_COM_RSVD_PAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
exit:
kfree(ReservedPagePacket);
}
void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
{
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
bool bSendBeacon = false;
bool bcn_valid = false;
u8 DLBcnCount = 0;
u32 poll = 0;
DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
if (mstatus == 1) {
/* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
/* Suggested by filen. Added by tynli. */
rtw_write16(adapt, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
/* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
/* Set REG_CR bit 8. DMA beacon by SW. */
haldata->RegCR_1 |= BIT0;
rtw_write8(adapt, REG_CR+1, haldata->RegCR_1);
/* Disable Hw protection for a time which revserd for Hw sending beacon. */
/* Fix download reserved page packet fail that access collision with the protection time. */
/* 2010.05.11. Added by tynli. */
rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)|BIT(4));
if (haldata->RegFwHwTxQCtrl&BIT6) {
DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
bSendBeacon = true;
}
/* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
rtw_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT6)));
haldata->RegFwHwTxQCtrl &= (~BIT6);
/* Clear beacon valid check bit. */
rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
DLBcnCount = 0;
poll = 0;
do {
/* download rsvd page. */
SetFwRsvdPagePkt(adapt, false);
DLBcnCount++;
do {
rtw_yield_os();
/* rtw_mdelay_os(10); */
/* check rsvd page download OK. */
rtw_hal_get_hwreg(adapt, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid));
poll++;
} while (!bcn_valid && (poll%10) != 0 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
} while (!bcn_valid && DLBcnCount <= 100 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
if (adapt->bSurpriseRemoved || adapt->bDriverStopped)
;
else if (!bcn_valid)
DBG_88E("%s: 1 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
else
DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
/* */
/* We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */
/* because we need to free the Tx BCN Desc which is used by the first reserved page packet. */
/* At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return */
/* the beacon TCB in the following code. 2011.11.23. by tynli. */
/* */
/* Enable Bcn */
rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)|BIT(3));
rtw_write8(adapt, REG_BCN_CTRL, rtw_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
/* To make sure that if there exists an adapter which would like to send beacon. */
/* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
/* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
/* the beacon cannot be sent by HW. */
/* 2010.06.23. Added by tynli. */
if (bSendBeacon) {
rtw_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl|BIT6));
haldata->RegFwHwTxQCtrl |= BIT6;
}
/* Update RSVD page location H2C to Fw. */
if (bcn_valid) {
rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
DBG_88E("Set RSVD page location to Fw.\n");
}
/* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
/* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
haldata->RegCR_1 &= (~BIT0);
rtw_write8(adapt, REG_CR+1, haldata->RegCR_1);
}
}
void rtl8188e_set_p2p_ps_offload_cmd(struct adapter *adapt, u8 p2p_ps_state)
{
#ifdef CONFIG_88EU_P2P
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct wifidirect_info *pwdinfo = &(adapt->wdinfo);
struct P2P_PS_Offload_t *p2p_ps_offload = &haldata->p2p_ps_offload;
u8 i;
switch (p2p_ps_state) {
case P2P_PS_DISABLE:
DBG_88E("P2P_PS_DISABLE\n");
memset(p2p_ps_offload, 0, 1);
break;
case P2P_PS_ENABLE:
DBG_88E("P2P_PS_ENABLE\n");
/* update CTWindow value. */
if (pwdinfo->ctwindow > 0) {
p2p_ps_offload->CTWindow_En = 1;
rtw_write8(adapt, REG_P2P_CTWIN, pwdinfo->ctwindow);
}
/* hw only support 2 set of NoA */
for (i = 0; i < pwdinfo->noa_num; i++) {
/* To control the register setting for which NOA */
rtw_write8(adapt, REG_NOA_DESC_SEL, (i << 4));
if (i == 0)
p2p_ps_offload->NoA0_En = 1;
else
p2p_ps_offload->NoA1_En = 1;
/* config P2P NoA Descriptor Register */
rtw_write32(adapt, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
rtw_write32(adapt, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
rtw_write32(adapt, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
rtw_write8(adapt, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
}
if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
/* rst p2p circuit */
rtw_write8(adapt, REG_DUAL_TSF_RST, BIT(4));
p2p_ps_offload->Offload_En = 1;
if (pwdinfo->role == P2P_ROLE_GO) {
p2p_ps_offload->role = 1;
p2p_ps_offload->AllStaSleep = 0;
} else {
p2p_ps_offload->role = 0;
}
p2p_ps_offload->discovery = 0;
}
break;
case P2P_PS_SCAN:
DBG_88E("P2P_PS_SCAN\n");
p2p_ps_offload->discovery = 1;
break;
case P2P_PS_SCAN_DONE:
DBG_88E("P2P_PS_SCAN_DONE\n");
p2p_ps_offload->discovery = 0;
pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
break;
default:
break;
}
FillH2CCmd_88E(adapt, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload);
#endif
}

View File

@ -0,0 +1,267 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
/* */
/* Description: */
/* */
/* This file is for 92CE/92CU dynamic mechanism only */
/* */
/* */
/* */
#define _RTL8188E_DM_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8188e_hal.h>
static void dm_CheckStatistics(struct adapter *Adapter)
{
}
/* Initialize GPIO setting registers */
static void dm_InitGPIOSetting(struct adapter *Adapter)
{
u8 tmp1byte;
tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
}
/* */
/* functions */
/* */
static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
{
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &hal_data->dmpriv;
struct odm_dm_struct *dm_odm = &(hal_data->odmpriv);
u8 cut_ver, fab_ver;
/* Init Value */
memset(dm_odm, 0, sizeof(*dm_odm));
dm_odm->Adapter = Adapter;
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PLATFORM, ODM_CE);
if (Adapter->interface_type == RTW_GSPI)
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_INTERFACE, ODM_ITRF_SDIO);
else
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_INTERFACE, Adapter->interface_type);/* RTL871X_HCI_TYPE */
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8188E);
fab_ver = ODM_TSMC;
cut_ver = ODM_CUT_A;
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_FAB_VER, fab_ver);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_CUT_VER, cut_ver);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(hal_data->VersionID));
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_PATCH_ID, hal_data->CustomerID);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
if (hal_data->rf_type == RF_1T1R)
ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
else if (hal_data->rf_type == RF_2T2R)
ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
else if (hal_data->rf_type == RF_1T2R)
ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType);
pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
ODM_RF_TX_PWR_TRACK;
ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
}
static void Update_ODM_ComInfo_88E(struct adapter *Adapter)
{
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
struct odm_dm_struct *dm_odm = &(hal_data->odmpriv);
struct dm_priv *pdmpriv = &hal_data->dmpriv;
int i;
pdmpriv->InitODMFlag = ODM_BB_DIG |
ODM_BB_RA_MASK |
ODM_BB_DYNAMIC_TXPWR |
ODM_BB_FA_CNT |
ODM_BB_RSSI_MONITOR |
ODM_BB_CCK_PD |
ODM_BB_PWR_SAVE |
ODM_MAC_EDCA_TURBO |
ODM_RF_CALIBRATION |
ODM_RF_TX_PWR_TRACK;
if (hal_data->AntDivCfg)
pdmpriv->InitODMFlag |= ODM_BB_ANT_DIV;
if (Adapter->registrypriv.mp_mode == 1) {
pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
ODM_RF_TX_PWR_TRACK;
}
ODM_CmnInfoUpdate(dm_odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_TX_UNI, &(Adapter->xmitpriv.tx_bytes));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_RX_UNI, &(Adapter->recvpriv.rx_bytes));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_WM_MODE, &(pmlmeext->cur_wireless_mode));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_CHNL_OFFSET, &(hal_data->nCur40MhzPrimeSC));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SEC_MODE, &(Adapter->securitypriv.dot11PrivacyAlgrthm));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_BW, &(hal_data->CurrentChannelBW));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_CHNL, &(hal_data->CurrentChannel));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_NET_CLOSED, &(Adapter->net_closed));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_MP_MODE, &(Adapter->registrypriv.mp_mode));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_SCAN, &(pmlmepriv->bScanInProcess));
ODM_CmnInfoHook(dm_odm, ODM_CMNINFO_POWER_SAVING, &(pwrctrlpriv->bpower_saving));
ODM_CmnInfoInit(dm_odm, ODM_CMNINFO_RF_ANTENNA_TYPE, hal_data->TRxAntDivType);
for (i = 0; i < NUM_STA; i++)
ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, NULL);
}
void rtl8188e_InitHalDm(struct adapter *Adapter)
{
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &hal_data->dmpriv;
struct odm_dm_struct *dm_odm = &(hal_data->odmpriv);
dm_InitGPIOSetting(Adapter);
pdmpriv->DM_Type = DM_Type_ByDriver;
pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
Update_ODM_ComInfo_88E(Adapter);
ODM_DMInit(dm_odm);
Adapter->fix_rate = 0xFF;
}
void rtl8188e_HalDmWatchDog(struct adapter *Adapter)
{
bool fw_cur_in_ps = false;
bool fw_ps_awake = true;
u8 hw_init_completed = false;
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
hw_init_completed = Adapter->hw_init_completed;
if (!hw_init_completed)
goto skip_dm;
fw_cur_in_ps = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&fw_ps_awake));
/* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
/* modifed by thomas. 2011.06.11. */
if (Adapter->wdinfo.p2p_ps_mode)
fw_ps_awake = false;
if (hw_init_completed && ((!fw_cur_in_ps) && fw_ps_awake)) {
/* Calculate Tx/Rx statistics. */
dm_CheckStatistics(Adapter);
}
/* ODM */
if (hw_init_completed) {
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
u8 bLinked = false;
if ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))) {
if (Adapter->stapriv.asoc_sta_count > 2)
bLinked = true;
} else {/* Station mode */
if (check_fwstate(pmlmepriv, _FW_LINKED))
bLinked = true;
}
ODM_CmnInfoUpdate(&hal_data->odmpriv, ODM_CMNINFO_LINK, bLinked);
ODM_DMWatchdog(&hal_data->odmpriv);
}
skip_dm:
/* Check GPIO to determine current RF on/off and Pbc status. */
/* Check Hardware Radio ON/OFF or not */
return;
}
void rtl8188e_init_dm_priv(struct adapter *Adapter)
{
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &hal_data->dmpriv;
struct odm_dm_struct *podmpriv = &hal_data->odmpriv;
memset(pdmpriv, 0, sizeof(struct dm_priv));
Init_ODM_ComInfo_88E(Adapter);
ODM_InitDebugSetting(podmpriv);
}
void rtl8188e_deinit_dm_priv(struct adapter *Adapter)
{
}
/* Add new function to reset the state of antenna diversity before link. */
/* Compare RSSI for deciding antenna */
void AntDivCompare8188E(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src)
{
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
if (0 != hal_data->AntDivCfg) {
/* select optimum_antenna for before linked =>For antenna diversity */
if (dst->Rssi >= src->Rssi) {/* keep org parameter */
src->Rssi = dst->Rssi;
src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna;
}
}
}
/* Add new function to reset the state of antenna diversity before link. */
u8 AntDivBeforeLink8188E(struct adapter *Adapter)
{
struct hal_data_8188e *hal_data = GET_HAL_DATA(Adapter);
struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table;
struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
/* Condition that does not need to use antenna diversity. */
if (hal_data->AntDivCfg == 0)
return false;
if (check_fwstate(pmlmepriv, _FW_LINKED))
return false;
if (dm_swat_tbl->SWAS_NoLink_State == 0) {
/* switch channel */
dm_swat_tbl->SWAS_NoLink_State = 1;
dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ? Antenna_B : Antenna_A;
rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false);
return true;
} else {
dm_swat_tbl->SWAS_NoLink_State = 0;
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,851 @@
/******************************************************************************
*
* 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_MP_C_
#include <drv_types.h>
#include <rtw_mp.h>
#include <rtl8188e_hal.h>
#include <rtl8188e_dm.h>
s32 Hal_SetPowerTracking(struct adapter *padapter, u8 enable)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
if (!netif_running(padapter->pnetdev)) {
RT_TRACE(_module_mp_, _drv_warning_,
("SetPowerTracking! Fail: interface not opened!\n"));
return _FAIL;
}
if (!check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE)) {
RT_TRACE(_module_mp_, _drv_warning_,
("SetPowerTracking! Fail: not in MP mode!\n"));
return _FAIL;
}
if (enable)
pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true;
else
pDM_Odm->RFCalibrateInfo.bTXPowerTrackingInit = false;
return _SUCCESS;
}
void Hal_GetPowerTracking(struct adapter *padapter, u8 *enable)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
*enable = pDM_Odm->RFCalibrateInfo.TxPowerTrackControl;
}
/*-----------------------------------------------------------------------------
* Function: mpt_SwitchRfSetting
*
* Overview: Change RF Setting when we siwthc channel/rate/BW for MP.
*
* Input: struct adapter * pAdapter
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 01/08/2009 MHC Suggestion from SD3 Willis for 92S series.
* 01/09/2009 MHC Add CCK modification for 40MHZ. Suggestion from SD3.
*
*---------------------------------------------------------------------------*/
void Hal_mpt_SwitchRfSetting(struct adapter *pAdapter)
{
struct mp_priv *pmp = &pAdapter->mppriv;
/* <20120525, Kordan> Dynamic mechanism for APK, asked by Dennis. */
pmp->MptCtx.backup0x52_RF_A = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
pmp->MptCtx.backup0x52_RF_B = (u8)PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0);
PHY_SetRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0, 0xD);
PHY_SetRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0, 0xD);
return;
}
/*---------------------------hal\rtl8192c\MPT_Phy.c---------------------------*/
/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
void Hal_MPT_CCKTxPowerAdjust(struct adapter *Adapter, bool bInCH14)
{
u32 TempVal = 0, TempVal2 = 0, TempVal3 = 0;
u32 CurrCCKSwingVal = 0, CCKSwingIndex = 12;
u8 i;
/* get current cck swing value and check 0xa22 & 0xa23 later to match the table. */
CurrCCKSwingVal = read_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord);
if (!bInCH14) {
/* Readback the current bb cck swing value and compare with the table to */
/* get the current swing index */
for (i = 0; i < CCK_TABLE_SIZE; i++) {
if (((CurrCCKSwingVal&0xff) == (u32)CCKSwingTable_Ch1_Ch13[i][0]) &&
(((CurrCCKSwingVal&0xff00)>>8) == (u32)CCKSwingTable_Ch1_Ch13[i][1])) {
CCKSwingIndex = i;
break;
}
}
/* Write 0xa22 0xa23 */
TempVal = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][0] +
(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][1]<<8);
/* Write 0xa24 ~ 0xa27 */
TempVal2 = 0;
TempVal2 = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][2] +
(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][3]<<8) +
(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][4]<<16)+
(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][5]<<24);
/* Write 0xa28 0xa29 */
TempVal3 = 0;
TempVal3 = CCKSwingTable_Ch1_Ch13[CCKSwingIndex][6] +
(CCKSwingTable_Ch1_Ch13[CCKSwingIndex][7]<<8);
} else {
for (i = 0; i < CCK_TABLE_SIZE; i++) {
if (((CurrCCKSwingVal&0xff) == (u32)CCKSwingTable_Ch14[i][0]) &&
(((CurrCCKSwingVal&0xff00)>>8) == (u32)CCKSwingTable_Ch14[i][1])) {
CCKSwingIndex = i;
break;
}
}
/* Write 0xa22 0xa23 */
TempVal = CCKSwingTable_Ch14[CCKSwingIndex][0] +
(CCKSwingTable_Ch14[CCKSwingIndex][1]<<8);
/* Write 0xa24 ~ 0xa27 */
TempVal2 = 0;
TempVal2 = CCKSwingTable_Ch14[CCKSwingIndex][2] +
(CCKSwingTable_Ch14[CCKSwingIndex][3]<<8) +
(CCKSwingTable_Ch14[CCKSwingIndex][4]<<16)+
(CCKSwingTable_Ch14[CCKSwingIndex][5]<<24);
/* Write 0xa28 0xa29 */
TempVal3 = 0;
TempVal3 = CCKSwingTable_Ch14[CCKSwingIndex][6] +
(CCKSwingTable_Ch14[CCKSwingIndex][7]<<8);
}
write_bbreg(Adapter, rCCK0_TxFilter1, bMaskHWord, TempVal);
write_bbreg(Adapter, rCCK0_TxFilter2, bMaskDWord, TempVal2);
write_bbreg(Adapter, rCCK0_DebugPort, bMaskLWord, TempVal3);
}
void Hal_MPT_CCKTxPowerAdjustbyIndex(struct adapter *pAdapter, bool beven)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
struct mpt_context *pMptCtx = &pAdapter->mppriv.MptCtx;
struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
s32 TempCCk;
u8 CCK_index, CCK_index_old = 0;
u8 Action = 0; /* 0: no action, 1: even->odd, 2:odd->even */
s32 i = 0;
if (!IS_92C_SERIAL(pHalData->VersionID))
return;
if (beven && !pMptCtx->bMptIndexEven) {
/* odd->even */
Action = 2;
pMptCtx->bMptIndexEven = true;
} else if (!beven && pMptCtx->bMptIndexEven) {
/* even->odd */
Action = 1;
pMptCtx->bMptIndexEven = false;
}
if (Action != 0) {
/* Query CCK default setting From 0xa24 */
TempCCk = read_bbreg(pAdapter, rCCK0_TxFilter2, bMaskDWord) & bMaskCCK;
for (i = 0; i < CCK_TABLE_SIZE; i++) {
if (pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch14[i][2], 4)) {
CCK_index_old = (u8)i;
break;
}
} else {
if (!memcmp((void *)&TempCCk, (void *)&CCKSwingTable_Ch1_Ch13[i][2], 4)) {
CCK_index_old = (u8)i;
break;
}
}
}
if (Action == 1)
CCK_index = CCK_index_old - 1;
else
CCK_index = CCK_index_old + 1;
/* Adjust CCK according to gain index */
if (!pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]);
rtw_write8(pAdapter, 0xa23, CCKSwingTable_Ch1_Ch13[CCK_index][1]);
rtw_write8(pAdapter, 0xa24, CCKSwingTable_Ch1_Ch13[CCK_index][2]);
rtw_write8(pAdapter, 0xa25, CCKSwingTable_Ch1_Ch13[CCK_index][3]);
rtw_write8(pAdapter, 0xa26, CCKSwingTable_Ch1_Ch13[CCK_index][4]);
rtw_write8(pAdapter, 0xa27, CCKSwingTable_Ch1_Ch13[CCK_index][5]);
rtw_write8(pAdapter, 0xa28, CCKSwingTable_Ch1_Ch13[CCK_index][6]);
rtw_write8(pAdapter, 0xa29, CCKSwingTable_Ch1_Ch13[CCK_index][7]);
} else {
rtw_write8(pAdapter, 0xa22, CCKSwingTable_Ch14[CCK_index][0]);
rtw_write8(pAdapter, 0xa23, CCKSwingTable_Ch14[CCK_index][1]);
rtw_write8(pAdapter, 0xa24, CCKSwingTable_Ch14[CCK_index][2]);
rtw_write8(pAdapter, 0xa25, CCKSwingTable_Ch14[CCK_index][3]);
rtw_write8(pAdapter, 0xa26, CCKSwingTable_Ch14[CCK_index][4]);
rtw_write8(pAdapter, 0xa27, CCKSwingTable_Ch14[CCK_index][5]);
rtw_write8(pAdapter, 0xa28, CCKSwingTable_Ch14[CCK_index][6]);
rtw_write8(pAdapter, 0xa29, CCKSwingTable_Ch14[CCK_index][7]);
}
}
}
/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
/*
* SetChannel
* Description
* Use H2C command to change channel,
* not only modify rf register, but also other setting need to be done.
*/
void Hal_SetChannel(struct adapter *pAdapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
struct mp_priv *pmp = &pAdapter->mppriv;
struct odm_dm_struct *pDM_Odm = &(pHalData->odmpriv);
u8 eRFPath;
u8 channel = pmp->channel;
/* set RF channel register */
for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
_write_rfreg(pAdapter, eRFPath, ODM_CHANNEL, 0x3FF, channel);
Hal_mpt_SwitchRfSetting(pAdapter);
SelectChannel(pAdapter, channel);
if (pHalData->CurrentChannel == 14 && !pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
pDM_Odm->RFCalibrateInfo.bCCKinCH14 = true;
Hal_MPT_CCKTxPowerAdjust(pAdapter, pDM_Odm->RFCalibrateInfo.bCCKinCH14);
} else if (pHalData->CurrentChannel != 14 && pDM_Odm->RFCalibrateInfo.bCCKinCH14) {
pDM_Odm->RFCalibrateInfo.bCCKinCH14 = false;
Hal_MPT_CCKTxPowerAdjust(pAdapter, pDM_Odm->RFCalibrateInfo.bCCKinCH14);
}
}
/*
* Notice
* Switch bandwitdth may change center frequency(channel)
*/
void Hal_SetBandwidth(struct adapter *pAdapter)
{
struct mp_priv *pmp = &pAdapter->mppriv;
SetBWMode(pAdapter, pmp->bandwidth, pmp->prime_channel_offset);
Hal_mpt_SwitchRfSetting(pAdapter);
}
void Hal_SetCCKTxPower(struct adapter *pAdapter, u8 *TxPower)
{
u32 tmpval = 0;
/* rf-A cck tx power */
write_bbreg(pAdapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, TxPower[RF_PATH_A]);
tmpval = (TxPower[RF_PATH_A]<<16) | (TxPower[RF_PATH_A]<<8) | TxPower[RF_PATH_A];
write_bbreg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
/* rf-B cck tx power */
write_bbreg(pAdapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, TxPower[RF_PATH_B]);
tmpval = (TxPower[RF_PATH_B]<<16) | (TxPower[RF_PATH_B]<<8) | TxPower[RF_PATH_B];
write_bbreg(pAdapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
RT_TRACE(_module_mp_, _drv_notice_,
("-SetCCKTxPower: A[0x%02x] B[0x%02x]\n",
TxPower[RF_PATH_A], TxPower[RF_PATH_B]));
}
void Hal_SetOFDMTxPower(struct adapter *pAdapter, u8 *TxPower)
{
u32 TxAGC = 0;
u8 tmpval = 0;
/* HT Tx-rf(A) */
tmpval = TxPower[RF_PATH_A];
TxAGC = (tmpval<<24) | (tmpval<<16) | (tmpval<<8) | tmpval;
write_bbreg(pAdapter, rTxAGC_A_Rate18_06, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_A_Rate54_24, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_A_Mcs03_Mcs00, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_A_Mcs07_Mcs04, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_A_Mcs11_Mcs08, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_A_Mcs15_Mcs12, bMaskDWord, TxAGC);
/* HT Tx-rf(B) */
tmpval = TxPower[RF_PATH_B];
TxAGC = (tmpval<<24) | (tmpval<<16) | (tmpval<<8) | tmpval;
write_bbreg(pAdapter, rTxAGC_B_Rate18_06, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_B_Rate54_24, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_B_Mcs03_Mcs00, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_B_Mcs07_Mcs04, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_B_Mcs11_Mcs08, bMaskDWord, TxAGC);
write_bbreg(pAdapter, rTxAGC_B_Mcs15_Mcs12, bMaskDWord, TxAGC);
}
void Hal_SetAntennaPathPower(struct adapter *pAdapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
u8 TxPowerLevel[RF_PATH_MAX];
u8 rfPath;
TxPowerLevel[RF_PATH_A] = pAdapter->mppriv.txpoweridx;
TxPowerLevel[RF_PATH_B] = pAdapter->mppriv.txpoweridx_b;
switch (pAdapter->mppriv.antenna_tx) {
case ANTENNA_A:
default:
rfPath = RF_PATH_A;
break;
case ANTENNA_B:
rfPath = RF_PATH_B;
break;
case ANTENNA_C:
rfPath = RF_PATH_C;
break;
}
switch (pHalData->rf_chip) {
case RF_8225:
case RF_8256:
case RF_6052:
Hal_SetCCKTxPower(pAdapter, TxPowerLevel);
if (pAdapter->mppriv.rateidx < MPT_RATE_6M) /* CCK rate */
Hal_MPT_CCKTxPowerAdjustbyIndex(pAdapter, TxPowerLevel[rfPath]%2 == 0);
Hal_SetOFDMTxPower(pAdapter, TxPowerLevel);
break;
default:
break;
}
}
void Hal_SetTxPower(struct adapter *pAdapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
u8 TxPower = pAdapter->mppriv.txpoweridx;
u8 TxPowerLevel[RF_PATH_MAX];
u8 rf, rfPath;
for (rf = 0; rf < RF_PATH_MAX; rf++)
TxPowerLevel[rf] = TxPower;
switch (pAdapter->mppriv.antenna_tx) {
case ANTENNA_A:
default:
rfPath = RF_PATH_A;
break;
case ANTENNA_B:
rfPath = RF_PATH_B;
break;
case ANTENNA_C:
rfPath = RF_PATH_C;
break;
}
switch (pHalData->rf_chip) {
/* 2008/09/12 MH Test only !! We enable the TX power tracking for MP!!!!! */
/* We should call normal driver API later!! */
case RF_8225:
case RF_8256:
case RF_6052:
Hal_SetCCKTxPower(pAdapter, TxPowerLevel);
if (pAdapter->mppriv.rateidx < MPT_RATE_6M) /* CCK rate */
Hal_MPT_CCKTxPowerAdjustbyIndex(pAdapter, TxPowerLevel[rfPath]%2 == 0);
Hal_SetOFDMTxPower(pAdapter, TxPowerLevel);
break;
default:
break;
}
}
void Hal_SetDataRate(struct adapter *pAdapter)
{
Hal_mpt_SwitchRfSetting(pAdapter);
}
void Hal_SetAntenna(struct adapter *pAdapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
struct ant_sel_ofdm *p_ofdm_tx; /* OFDM Tx register */
struct ant_sel_cck *p_cck_txrx;
u8 r_rx_antenna_ofdm = 0, r_ant_select_cck_val = 0;
u8 chgTx = 0, chgRx = 0;
u32 r_ant_select_ofdm_val = 0, r_ofdm_tx_en_val = 0;
p_ofdm_tx = (struct ant_sel_ofdm *)&r_ant_select_ofdm_val;
p_cck_txrx = (struct ant_sel_cck *)&r_ant_select_cck_val;
p_ofdm_tx->r_ant_ht1 = 0x1;
p_ofdm_tx->r_ant_ht2 = 0x2; /* Second TX RF path is A */
p_ofdm_tx->r_ant_non_ht = 0x3; /* 0x1+0x2=0x3 */
switch (pAdapter->mppriv.antenna_tx) {
case ANTENNA_A:
p_ofdm_tx->r_tx_antenna = 0x1;
r_ofdm_tx_en_val = 0x1;
p_ofdm_tx->r_ant_l = 0x1;
p_ofdm_tx->r_ant_ht_s1 = 0x1;
p_ofdm_tx->r_ant_non_ht_s1 = 0x1;
p_cck_txrx->r_ccktx_enable = 0x8;
chgTx = 1;
/* From SD3 Willis suggestion !!! Set RF A=TX and B as standby */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1);
r_ofdm_tx_en_val = 0x3;
/* Power save */
/* We need to close RFB by SW control */
if (pHalData->rf_type == RF_2T2R) {
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 1);
PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 1);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 0);
}
break;
case ANTENNA_B:
p_ofdm_tx->r_tx_antenna = 0x2;
r_ofdm_tx_en_val = 0x2;
p_ofdm_tx->r_ant_l = 0x2;
p_ofdm_tx->r_ant_ht_s1 = 0x2;
p_ofdm_tx->r_ant_non_ht_s1 = 0x2;
p_cck_txrx->r_ccktx_enable = 0x4;
chgTx = 1;
/* From SD3 Willis suggestion !!! Set RF A as standby */
PHY_SetBBReg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1);
PHY_SetBBReg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
/* Power save */
/* cosa r_ant_select_ofdm_val = 0x22222222; */
/* 2008/10/31 MH From SD3 Willi's suggestion. We must read RF 1T table. */
/* 2009/01/08 MH From Sd3 Willis. We need to close RFA by SW control */
if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_1T2R) {
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 1);
PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 1);
}
break;
case ANTENNA_AB: /* For 8192S */
p_ofdm_tx->r_tx_antenna = 0x3;
r_ofdm_tx_en_val = 0x3;
p_ofdm_tx->r_ant_l = 0x3;
p_ofdm_tx->r_ant_ht_s1 = 0x3;
p_ofdm_tx->r_ant_non_ht_s1 = 0x3;
p_cck_txrx->r_ccktx_enable = 0xC;
chgTx = 1;
/* From SD3 Willis suggestion !!! Set RF B as standby */
PHY_SetBBReg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
PHY_SetBBReg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
/* Disable Power save */
/* cosa r_ant_select_ofdm_val = 0x3321333; */
/* 2009/01/08 MH From Sd3 Willis. We need to enable RFA/B by SW control */
if (pHalData->rf_type == RF_2T2R) {
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT1, 1);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFParameter, BIT17, 1);
}
break;
default:
break;
}
/* r_rx_antenna_ofdm, bit0=A, bit1=B, bit2=C, bit3=D */
/* r_cckrx_enable : CCK default, 0=A, 1=B, 2=C, 3=D */
/* r_cckrx_enable_2 : CCK option, 0=A, 1=B, 2=C, 3=D */
switch (pAdapter->mppriv.antenna_rx) {
case ANTENNA_A:
r_rx_antenna_ofdm = 0x1; /* A */
p_cck_txrx->r_cckrx_enable = 0x0; /* default: A */
p_cck_txrx->r_cckrx_enable_2 = 0x0; /* option: A */
chgRx = 1;
break;
case ANTENNA_B:
r_rx_antenna_ofdm = 0x2; /* B */
p_cck_txrx->r_cckrx_enable = 0x1; /* default: B */
p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option: B */
chgRx = 1;
break;
case ANTENNA_AB:
r_rx_antenna_ofdm = 0x3; /* AB */
p_cck_txrx->r_cckrx_enable = 0x0; /* default:A */
p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option:B */
chgRx = 1;
break;
default:
break;
}
if (chgTx && chgRx) {
switch (pHalData->rf_chip) {
case RF_8225:
case RF_8256:
case RF_6052:
/* r_ant_sel_cck_val = r_ant_select_cck_val; */
PHY_SetBBReg(pAdapter, rFPGA1_TxInfo, 0x7fffffff, r_ant_select_ofdm_val); /* OFDM Tx */
PHY_SetBBReg(pAdapter, rFPGA0_TxInfo, 0x0000000f, r_ofdm_tx_en_val); /* OFDM Tx */
PHY_SetBBReg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); /* OFDM Rx */
PHY_SetBBReg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); /* OFDM Rx */
PHY_SetBBReg(pAdapter, rCCK0_AFESetting, bMaskByte3, r_ant_select_cck_val); /* CCK TxRx */
break;
default:
break;
}
}
RT_TRACE(_module_mp_, _drv_notice_, ("-SwitchAntenna: finished\n"));
}
s32 Hal_SetThermalMeter(struct adapter *pAdapter, u8 target_ther)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
if (!netif_running(pAdapter->pnetdev)) {
RT_TRACE(_module_mp_, _drv_warning_, ("SetThermalMeter! Fail: interface not opened!\n"));
return _FAIL;
}
if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == false) {
RT_TRACE(_module_mp_, _drv_warning_, ("SetThermalMeter: Fail! not in MP mode!\n"));
return _FAIL;
}
target_ther &= 0xff;
if (target_ther < 0x07)
target_ther = 0x07;
else if (target_ther > 0x1d)
target_ther = 0x1d;
pHalData->EEPROMThermalMeter = target_ther;
return _SUCCESS;
}
void Hal_TriggerRFThermalMeter(struct adapter *pAdapter)
{
_write_rfreg(pAdapter, RF_PATH_A , RF_T_METER_88E , BIT17 | BIT16 , 0x03);
}
u8 Hal_ReadRFThermalMeter(struct adapter *pAdapter)
{
u32 ThermalValue = 0;
ThermalValue = _read_rfreg(pAdapter, RF_PATH_A, RF_T_METER_88E, 0xfc00);
return (u8)ThermalValue;
}
void Hal_GetThermalMeter(struct adapter *pAdapter, u8 *value)
{
Hal_TriggerRFThermalMeter(pAdapter);
rtw_msleep_os(1000);
*value = Hal_ReadRFThermalMeter(pAdapter);
}
void Hal_SetSingleCarrierTx(struct adapter *pAdapter, u8 bStart)
{
pAdapter->mppriv.MptCtx.bSingleCarrier = bStart;
if (bStart) {
/* Start Single Carrier. */
RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleCarrierTx: test start\n"));
/* 1. if OFDM block on? */
if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);/* set OFDM block on */
/* 2. set CCK test mode off, set to CCK normal mode */
write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
/* 3. turn on scramble setting */
write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
/* 4. Turn On Single Carrier Tx and turn off the other test modes. */
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
/* for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
} else {
/* Stop Single Carrier. */
RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleCarrierTx: test stop\n"));
/* Turn off all test modes. */
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
rtw_msleep_os(10);
/* BB Reset */
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
/* Stop for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
}
void Hal_SetSingleToneTx(struct adapter *pAdapter, u8 bStart)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
bool is92C = IS_92C_SERIAL(pHalData->VersionID);
u8 rfPath;
u32 reg58 = 0x0;
switch (pAdapter->mppriv.antenna_tx) {
case ANTENNA_A:
default:
rfPath = RF_PATH_A;
break;
case ANTENNA_B:
rfPath = RF_PATH_B;
break;
case ANTENNA_C:
rfPath = RF_PATH_C;
break;
}
pAdapter->mppriv.MptCtx.bSingleTone = bStart;
if (bStart) {
/* Start Single Tone. */
RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleToneTx: test start\n"));
/* <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu) */
if (IS_HARDWARE_TYPE_8188E(pAdapter)) {
reg58 = PHY_QueryRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask);
reg58 &= 0xFFFFFFF0;
reg58 += 2;
PHY_SetRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask, reg58);
}
PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x0);
PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x0);
if (is92C) {
_write_rfreg(pAdapter, RF_PATH_A, 0x21, BIT19, 0x01);
rtw_usleep_os(100);
if (rfPath == RF_PATH_A)
write_rfreg(pAdapter, RF_PATH_B, 0x00, 0x10000); /* PAD all on. */
else if (rfPath == RF_PATH_B)
write_rfreg(pAdapter, RF_PATH_A, 0x00, 0x10000); /* PAD all on. */
write_rfreg(pAdapter, rfPath, 0x00, 0x2001f); /* PAD all on. */
rtw_usleep_os(100);
} else {
write_rfreg(pAdapter, rfPath, 0x21, 0xd4000);
rtw_usleep_os(100);
write_rfreg(pAdapter, rfPath, 0x00, 0x2001f); /* PAD all on. */
rtw_usleep_os(100);
}
/* for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
} else {
/* Stop Single Tone. */
RT_TRACE(_module_mp_, _drv_alert_, ("SetSingleToneTx: test stop\n"));
/* <20120326, Kordan> To amplify the power of tone for Xtal calibration. (asked by Edlu) */
/* <20120326, Kordan> Only in single tone mode. (asked by Edlu) */
if (IS_HARDWARE_TYPE_8188E(pAdapter)) {
reg58 = PHY_QueryRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask);
reg58 &= 0xFFFFFFF0;
PHY_SetRFReg(pAdapter, RF_PATH_A, LNA_Low_Gain_3, bRFRegOffsetMask, reg58);
}
write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, 0x1);
write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
if (is92C) {
_write_rfreg(pAdapter, RF_PATH_A, 0x21, BIT19, 0x00);
rtw_usleep_os(100);
write_rfreg(pAdapter, RF_PATH_A, 0x00, 0x32d75); /* PAD all on. */
write_rfreg(pAdapter, RF_PATH_B, 0x00, 0x32d75); /* PAD all on. */
rtw_usleep_os(100);
} else {
write_rfreg(pAdapter, rfPath, 0x21, 0x54000);
rtw_usleep_os(100);
write_rfreg(pAdapter, rfPath, 0x00, 0x30000); /* PAD all on. */
rtw_usleep_os(100);
}
/* Stop for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
}
void Hal_SetCarrierSuppressionTx(struct adapter *pAdapter, u8 bStart)
{
pAdapter->mppriv.MptCtx.bCarrierSuppression = bStart;
if (bStart) {
/* Start Carrier Suppression. */
RT_TRACE(_module_mp_, _drv_alert_, ("SetCarrierSuppressionTx: test start\n"));
if (pAdapter->mppriv.rateidx <= MPT_RATE_11M) {
/* 1. if CCK block on? */
if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn))
write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/* set CCK block on */
/* Turn Off All Test Mode */
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /* transmit mode */
write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x0); /* turn off scramble setting */
/* Set CCK Tx Test Rate */
write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, 0x0); /* Set FTxRate to 1Mbps */
}
/* for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
} else {
/* Stop Carrier Suppression. */
RT_TRACE(_module_mp_, _drv_alert_, ("SetCarrierSuppressionTx: test stop\n"));
if (pAdapter->mppriv.rateidx <= MPT_RATE_11M) {
write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /* normal mode */
write_bbreg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /* turn on scramble setting */
/* BB Reset */
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
}
/* Stop for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
}
void Hal_SetCCKContinuousTx(struct adapter *pAdapter, u8 bStart)
{
u32 cckrate;
if (bStart) {
RT_TRACE(_module_mp_, _drv_alert_,
("SetCCKContinuousTx: test start\n"));
/* 1. if CCK block on? */
if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn))
write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/* set CCK block on */
/* Turn Off All Test Mode */
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
/* Set CCK Tx Test Rate */
cckrate = pAdapter->mppriv.rateidx;
write_bbreg(pAdapter, rCCK0_System, bCCKTxRate, cckrate);
write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /* transmit mode */
write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable); /* turn on scramble setting */
/* for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
} else {
RT_TRACE(_module_mp_, _drv_info_,
("SetCCKContinuousTx: test stop\n"));
write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /* normal mode */
write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable); /* turn on scramble setting */
/* BB Reset */
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
/* Stop for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
pAdapter->mppriv.MptCtx.bCckContTx = bStart;
pAdapter->mppriv.MptCtx.bOfdmContTx = false;
} /* mpt_StartCckContTx */
void Hal_SetOFDMContinuousTx(struct adapter *pAdapter, u8 bStart)
{
if (bStart) {
RT_TRACE(_module_mp_, _drv_info_, ("SetOFDMContinuousTx: test start\n"));
/* 1. if OFDM block on? */
if (!read_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
write_bbreg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);/* set OFDM block on */
/* 2. set CCK test mode off, set to CCK normal mode */
write_bbreg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
/* 3. turn on scramble setting */
write_bbreg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
/* 4. Turn On Continue Tx and turn off the other test modes. */
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bEnable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
/* for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
} else {
RT_TRACE(_module_mp_, _drv_info_, ("SetOFDMContinuousTx: test stop\n"));
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
write_bbreg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
/* Delay 10 ms */
rtw_msleep_os(10);
/* BB Reset */
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
write_bbreg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
/* Stop for dynamic set Power index. */
write_bbreg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
write_bbreg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
pAdapter->mppriv.MptCtx.bCckContTx = false;
pAdapter->mppriv.MptCtx.bOfdmContTx = bStart;
} /* mpt_StartOfdmContTx */
void Hal_SetContinuousTx(struct adapter *pAdapter, u8 bStart)
{
RT_TRACE(_module_mp_, _drv_info_,
("SetContinuousTx: rate:%d\n", pAdapter->mppriv.rateidx));
pAdapter->mppriv.MptCtx.bStartContTx = bStart;
if (pAdapter->mppriv.rateidx <= MPT_RATE_11M)
Hal_SetCCKContinuousTx(pAdapter, bStart);
else if ((pAdapter->mppriv.rateidx >= MPT_RATE_6M) &&
(pAdapter->mppriv.rateidx <= MPT_RATE_MCS15))
Hal_SetOFDMContinuousTx(pAdapter, bStart);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,569 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
/******************************************************************************
*
*
* Module: rtl8192c_rf6052.c ( Source C File)
*
* Note: Provide RF 6052 series relative API.
*
* Function:
*
* Export:
*
* Abbrev:
*
* History:
* Data Who Remark
*
* 09/25/2008 MHC Create initial version.
* 11/05/2008 MHC Add API for tw power setting.
*
*
******************************************************************************/
#define _RTL8188E_RF6052_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8188e_hal.h>
/*---------------------------Define Local Constant---------------------------*/
/* Define local structure for debug!!!!! */
struct rf_shadow {
/* Shadow register value */
u32 Value;
/* Compare or not flag */
u8 Compare;
/* Record If it had ever modified unpredicted */
u8 ErrorOrNot;
/* Recorver Flag */
u8 Recorver;
/* */
u8 Driver_Write;
};
/*---------------------------Define Local Constant---------------------------*/
/*------------------------Define global variable-----------------------------*/
/*------------------------Define local variable------------------------------*/
/*-----------------------------------------------------------------------------
* Function: RF_ChangeTxPath
*
* Overview: For RL6052, we must change some RF settign for 1T or 2T.
*
* Input: u16 DataRate 0x80-8f, 0x90-9f
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 09/25/2008 MHC Create Version 0.
* Firmwaer support the utility later.
*
*---------------------------------------------------------------------------*/
void rtl8188e_RF_ChangeTxPath(struct adapter *Adapter, u16 DataRate)
{
/* We do not support gain table change inACUT now !!!! Delete later !!! */
} /* RF_ChangeTxPath */
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetBandwidth()
*
* Overview: This function is called by SetBWModeCallback8190Pci() only
*
* Input: struct adapter *Adapter
* WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
*
* Output: NONE
*
* Return: NONE
*
* Note: For RF type 0222D
*---------------------------------------------------------------------------*/
void rtl8188e_PHY_RF6052SetBandwidth(struct adapter *Adapter,
enum ht_channel_width Bandwidth)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
switch (Bandwidth) {
case HT_CHANNEL_WIDTH_20:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10) | BIT(11));
PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
break;
case HT_CHANNEL_WIDTH_40:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10));
PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
break;
default:
break;
}
}
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetCckTxPower
*
* Overview:
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/05/2008 MHC Simulate 8192series..
*
*---------------------------------------------------------------------------*/
void
rtl8188e_PHY_RF6052SetCckTxPower(
struct adapter *Adapter,
u8 *pPowerlevel)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
u32 TxAGC[2] = {0, 0}, tmpval = 0, pwrtrac_value;
bool TurboScanOff = false;
u8 idx1, idx2;
u8 *ptr;
u8 direction;
/* FOR CE ,must disable turbo scan */
TurboScanOff = true;
if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
TxAGC[RF_PATH_A] = 0x3f3f3f3f;
TxAGC[RF_PATH_B] = 0x3f3f3f3f;
TurboScanOff = true;/* disable turbo scan */
if (TurboScanOff) {
for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
TxAGC[idx1] =
pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
(pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
/* 2010/10/18 MH For external PA module. We need to limit power index to be less than 0x20. */
if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA)
TxAGC[idx1] = 0x20;
}
}
} else {
/* Driver dynamic Tx power shall not affect Tx power.
* It shall be determined by power training mechanism.
i * Currently, we cannot fully disable driver dynamic
* tx power mechanism because it is referenced by BT
* coexist mechanism.
* In the future, two mechanism shall be separated from
* each other and maintained independently. */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
TxAGC[RF_PATH_A] = 0x10101010;
TxAGC[RF_PATH_B] = 0x10101010;
} else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
TxAGC[RF_PATH_A] = 0x00000000;
TxAGC[RF_PATH_B] = 0x00000000;
} else {
for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
TxAGC[idx1] =
pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
(pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
}
if (pHalData->EEPROMRegulatory == 0) {
tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) +
(pHalData->MCSTxPowerLevelOriginalOffset[0][7]<<8);
TxAGC[RF_PATH_A] += tmpval;
tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) +
(pHalData->MCSTxPowerLevelOriginalOffset[0][15]<<24);
TxAGC[RF_PATH_B] += tmpval;
}
}
}
for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
ptr = (u8 *)(&(TxAGC[idx1]));
for (idx2 = 0; idx2 < 4; idx2++) {
if (*ptr > RF6052_MAX_TX_PWR)
*ptr = RF6052_MAX_TX_PWR;
ptr++;
}
}
ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value);
if (direction == 1) {
/* Increase TX power */
TxAGC[0] += pwrtrac_value;
TxAGC[1] += pwrtrac_value;
} else if (direction == 2) {
/* Decrease TX power */
TxAGC[0] -= pwrtrac_value;
TxAGC[1] -= pwrtrac_value;
}
/* rf-A cck tx power */
tmpval = TxAGC[RF_PATH_A]&0xff;
PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
tmpval = TxAGC[RF_PATH_A]>>8;
PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
/* rf-B cck tx power */
tmpval = TxAGC[RF_PATH_B]>>24;
PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
tmpval = TxAGC[RF_PATH_B]&0x00ffffff;
PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
} /* PHY_RF6052SetCckTxPower */
/* */
/* powerbase0 for OFDM rates */
/* powerbase1 for HT MCS rates */
/* */
static void getpowerbase88e(struct adapter *Adapter, u8 *pPowerLevelOFDM,
u8 *pPowerLevelBW20, u8 *pPowerLevelBW40, u8 Channel, u32 *OfdmBase, u32 *MCSBase)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
u32 powerBase0, powerBase1;
u8 i, powerlevel[2];
for (i = 0; i < 2; i++) {
powerBase0 = pPowerLevelOFDM[i];
powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0;
*(OfdmBase+i) = powerBase0;
}
for (i = 0; i < pHalData->NumTotalRFPath; i++) {
/* Check HT20 to HT40 diff */
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
powerlevel[i] = pPowerLevelBW20[i];
else
powerlevel[i] = pPowerLevelBW40[i];
powerBase1 = powerlevel[i];
powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1;
*(MCSBase+i) = powerBase1;
}
}
static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel,
u8 index, u32 *powerBase0, u32 *powerBase1,
u32 *pOutWriteVal)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
s8 pwr_diff = 0;
u32 writeVal, customer_limit, rf;
u8 Regulatory = pHalData->EEPROMRegulatory;
/* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
for (rf = 0; rf < 2; rf++) {
switch (Regulatory) {
case 0: /* Realtek better performance */
/* increase power diff defined by Realtek for large power */
chnlGroup = 0;
writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
case 1: /* Realtek regulatory */
/* increase power diff defined by Realtek for regulatory */
if (pHalData->pwrGroupCnt == 1)
chnlGroup = 0;
if (pHalData->pwrGroupCnt >= pHalData->PGMaxGroup) {
if (Channel < 3) /* Channel 1-2 */
chnlGroup = 0;
else if (Channel < 6) /* Channel 3-5 */
chnlGroup = 1;
else if (Channel < 9) /* Channel 6-8 */
chnlGroup = 2;
else if (Channel < 12) /* Channel 9-11 */
chnlGroup = 3;
else if (Channel < 14) /* Channel 12-13 */
chnlGroup = 4;
else if (Channel == 14) /* Channel 14 */
chnlGroup = 5;
}
writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
case 2: /* Better regulatory */
/* don't increase any power diff */
writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
case 3: /* Customer defined power diff. */
/* increase power diff defined by customer. */
chnlGroup = 0;
if (index < 2)
pwr_diff = pHalData->TxPwrLegacyHtDiff[rf][Channel-1];
else if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
pwr_diff = pHalData->TxPwrHt20Diff[rf][Channel-1];
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
customer_pwr_limit = pHalData->PwrGroupHT40[rf][Channel-1];
else
customer_pwr_limit = pHalData->PwrGroupHT20[rf][Channel-1];
if (pwr_diff >= customer_pwr_limit)
pwr_diff = 0;
else
pwr_diff = customer_pwr_limit - pwr_diff;
for (i = 0; i < 4; i++) {
pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)]&(0x7f<<(i*8)))>>(i*8));
if (pwr_diff_limit[i] > pwr_diff)
pwr_diff_limit[i] = pwr_diff;
}
customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) |
(pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]);
writeVal = customer_limit + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
default:
chnlGroup = 0;
writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
}
/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
/* In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
/* 92d do not need this */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
writeVal = 0x14141414;
else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
writeVal = 0x00000000;
/* 20100628 Joseph: High power mode for BT-Coexist mechanism. */
/* This mechanism is only applied when Driver-Highpower-Mechanism is OFF. */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1)
writeVal = writeVal - 0x06060606;
else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT2)
writeVal = writeVal;
*(pOutWriteVal+rf) = writeVal;
}
}
static void writeOFDMPowerReg88E(struct adapter *Adapter, u8 index, u32 *pValue)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
u16 regoffset_a[6] = {
rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12};
u16 regoffset_b[6] = {
rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12};
u8 i, rf, pwr_val[4];
u32 writeVal;
u16 regoffset;
for (rf = 0; rf < 2; rf++) {
writeVal = pValue[rf];
for (i = 0; i < 4; i++) {
pwr_val[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8));
if (pwr_val[i] > RF6052_MAX_TX_PWR)
pwr_val[i] = RF6052_MAX_TX_PWR;
}
writeVal = (pwr_val[3]<<24) | (pwr_val[2]<<16) | (pwr_val[1]<<8) | pwr_val[0];
if (rf == 0)
regoffset = regoffset_a[index];
else
regoffset = regoffset_b[index];
PHY_SetBBReg(Adapter, regoffset, bMaskDWord, writeVal);
/* 201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */
if (((pHalData->rf_type == RF_2T2R) &&
(regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs15_Mcs12)) ||
((pHalData->rf_type != RF_2T2R) &&
(regoffset == rTxAGC_A_Mcs07_Mcs04 || regoffset == rTxAGC_B_Mcs07_Mcs04))) {
writeVal = pwr_val[3];
if (regoffset == rTxAGC_A_Mcs15_Mcs12 || regoffset == rTxAGC_A_Mcs07_Mcs04)
regoffset = 0xc90;
if (regoffset == rTxAGC_B_Mcs15_Mcs12 || regoffset == rTxAGC_B_Mcs07_Mcs04)
regoffset = 0xc98;
for (i = 0; i < 3; i++) {
if (i != 2)
writeVal = (writeVal > 8) ? (writeVal-8) : 0;
else
writeVal = (writeVal > 6) ? (writeVal-6) : 0;
rtw_write8(Adapter, (u32)(regoffset+i), (u8)writeVal);
}
}
}
}
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetOFDMTxPower
*
* Overview: For legacy and HY OFDM, we must read EEPROM TX power index for
* different channel and read original value in TX power register area from
* 0xe00. We increase offset and original value to be correct tx pwr.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/05/2008 MHC Simulate 8192 series method.
* 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to
* A/B pwr difference or legacy/HT pwr diff.
* 2. We concern with path B legacy/HT OFDM difference.
* 01/22/2009 MHC Support new EPRO format from SD3.
*
*---------------------------------------------------------------------------*/
void
rtl8188e_PHY_RF6052SetOFDMTxPower(
struct adapter *Adapter,
u8 *pPowerLevelOFDM,
u8 *pPowerLevelBW20,
u8 *pPowerLevelBW40,
u8 Channel)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
u32 writeVal[2], powerBase0[2], powerBase1[2], pwrtrac_value;
u8 direction;
u8 index = 0;
getpowerbase88e(Adapter, pPowerLevelOFDM, pPowerLevelBW20, pPowerLevelBW40, Channel, &powerBase0[0], &powerBase1[0]);
/* 2012/04/23 MH According to power tracking value, we need to revise OFDM tx power. */
/* This is ued to fix unstable power tracking mode. */
ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 0, &direction, &pwrtrac_value);
for (index = 0; index < 6; index++) {
get_rx_power_val_by_reg(Adapter, Channel, index,
&powerBase0[0], &powerBase1[0],
&writeVal[0]);
if (direction == 1) {
writeVal[0] += pwrtrac_value;
writeVal[1] += pwrtrac_value;
} else if (direction == 2) {
writeVal[0] -= pwrtrac_value;
writeVal[1] -= pwrtrac_value;
}
writeOFDMPowerReg88E(Adapter, index, &writeVal[0]);
}
}
static int phy_RF6052_Config_ParaFile(struct adapter *Adapter)
{
struct bb_reg_def *pPhyReg;
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
u32 u4RegValue = 0;
u8 eRFPath;
int rtStatus = _SUCCESS;
/* 3----------------------------------------------------------------- */
/* 3 <2> Initialize RF */
/* 3----------------------------------------------------------------- */
for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
pPhyReg = &pHalData->PHYRegDef[eRFPath];
/*----Store original RFENV control type----*/
switch (eRFPath) {
case RF_PATH_A:
case RF_PATH_C:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
break;
case RF_PATH_B:
case RF_PATH_D:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16);
break;
}
/*----Set RF_ENV enable----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
rtw_udelay_os(1);/* PlatformStallExecution(1); */
/*----Set RF_ENV output high----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
rtw_udelay_os(1);/* PlatformStallExecution(1); */
/* Set bit number of Address and Data for RF register */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
rtw_udelay_os(1);/* PlatformStallExecution(1); */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
rtw_udelay_os(1);/* PlatformStallExecution(1); */
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF_PATH_A:
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, (enum rf_radio_path)eRFPath, (enum rf_radio_path)eRFPath))
rtStatus = _FAIL;
break;
case RF_PATH_B:
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, (enum rf_radio_path)eRFPath, (enum rf_radio_path)eRFPath))
rtStatus = _FAIL;
break;
case RF_PATH_C:
break;
case RF_PATH_D:
break;
}
/*----Restore RFENV control type----*/;
switch (eRFPath) {
case RF_PATH_A:
case RF_PATH_C:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
break;
case RF_PATH_B:
case RF_PATH_D:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
break;
}
if (rtStatus != _SUCCESS)
goto phy_RF6052_Config_ParaFile_Fail;
}
return rtStatus;
phy_RF6052_Config_ParaFile_Fail:
return rtStatus;
}
int PHY_RF6052_Config8188E(struct adapter *Adapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
int rtStatus = _SUCCESS;
/* */
/* Initialize general global value */
/* */
/* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
if (pHalData->rf_type == RF_1T1R)
pHalData->NumTotalRFPath = 1;
else
pHalData->NumTotalRFPath = 2;
/* */
/* Config BB and RF */
/* */
rtStatus = phy_RF6052_Config_ParaFile(Adapter);
return rtStatus;
}

View File

@ -0,0 +1,202 @@
/******************************************************************************
*
* 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 <osdep_service.h>
#include <drv_types.h>
#include <rtl8188e_hal.h>
static void process_rssi(struct adapter *padapter, struct recv_frame *prframe)
{
struct rx_pkt_attrib *pattrib = &prframe->attrib;
struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;
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;
} /* Process_UI_RSSI_8192C */
static void process_link_qual(struct adapter *padapter, struct recv_frame *prframe)
{
struct rx_pkt_attrib *pattrib;
struct signal_stat *signal_stat;
if (prframe == NULL || padapter == NULL)
return;
pattrib = &prframe->attrib;
signal_stat = &padapter->recvpriv.signal_qual_data;
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;
}
void rtl8188e_process_phy_info(struct adapter *padapter, void *prframe)
{
struct recv_frame *precvframe = (struct recv_frame *)prframe;
/* Check RSSI */
process_rssi(padapter, precvframe);
/* Check EVM */
process_link_qual(padapter, precvframe);
}
void update_recvframe_attrib_88e(struct recv_frame *precvframe, struct recv_stat *prxstat)
{
struct rx_pkt_attrib *pattrib;
struct recv_stat report;
report.rxdw0 = prxstat->rxdw0;
report.rxdw1 = prxstat->rxdw1;
report.rxdw2 = prxstat->rxdw2;
report.rxdw3 = prxstat->rxdw3;
report.rxdw4 = prxstat->rxdw4;
report.rxdw5 = prxstat->rxdw5;
pattrib = &precvframe->attrib;
memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);;/* u8)prxreport->crc32; */
/* update rx report to recv_frame attribute */
pattrib->pkt_rpt_type = (u8)((le32_to_cpu(report.rxdw3) >> 14) & 0x3);/* prxreport->rpt_sel; */
if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
pattrib->pkt_len = (u16)(le32_to_cpu(report.rxdw0) & 0x00003fff);/* u16)prxreport->pktlen; */
pattrib->drvinfo_sz = (u8)((le32_to_cpu(report.rxdw0) >> 16) & 0xf) * 8;/* u8)(prxreport->drvinfosize << 3); */
pattrib->physt = (u8)((le32_to_cpu(report.rxdw0) >> 26) & 0x1);/* u8)prxreport->physt; */
pattrib->bdecrypted = (le32_to_cpu(report.rxdw0) & BIT(27)) ? 0 : 1;/* u8)(prxreport->swdec ? 0 : 1); */
pattrib->encrypt = (u8)((le32_to_cpu(report.rxdw0) >> 20) & 0x7);/* u8)prxreport->security; */
pattrib->qos = (u8)((le32_to_cpu(report.rxdw0) >> 23) & 0x1);/* u8)prxreport->qos; */
pattrib->priority = (u8)((le32_to_cpu(report.rxdw1) >> 8) & 0xf);/* u8)prxreport->tid; */
pattrib->amsdu = (u8)((le32_to_cpu(report.rxdw1) >> 13) & 0x1);/* u8)prxreport->amsdu; */
pattrib->seq_num = (u16)(le32_to_cpu(report.rxdw2) & 0x00000fff);/* u16)prxreport->seq; */
pattrib->frag_num = (u8)((le32_to_cpu(report.rxdw2) >> 12) & 0xf);/* u8)prxreport->frag; */
pattrib->mfrag = (u8)((le32_to_cpu(report.rxdw1) >> 27) & 0x1);/* u8)prxreport->mf; */
pattrib->mdata = (u8)((le32_to_cpu(report.rxdw1) >> 26) & 0x1);/* u8)prxreport->md; */
pattrib->mcs_rate = (u8)(le32_to_cpu(report.rxdw3) & 0x3f);/* u8)prxreport->rxmcs; */
pattrib->rxht = (u8)((le32_to_cpu(report.rxdw3) >> 6) & 0x1);/* u8)prxreport->rxht; */
pattrib->icv_err = (u8)((le32_to_cpu(report.rxdw0) >> 15) & 0x1);/* u8)prxreport->icverr; */
pattrib->shift_sz = (u8)((le32_to_cpu(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)(le32_to_cpu(report.rxdw0) & 0x3FF);/* Rx length[9:0] */
pattrib->drvinfo_sz = 0;
/* */
/* Get TX report MAC ID valid. */
/* */
pattrib->MacIDValidEntry[0] = le32_to_cpu(report.rxdw4);
pattrib->MacIDValidEntry[1] = le32_to_cpu(report.rxdw5);
} else if (pattrib->pkt_rpt_type == HIS_REPORT) { /* USB HISR RPT */
pattrib->pkt_len = (u16)(le32_to_cpu(report.rxdw0) & 0x00003fff);/* u16)prxreport->pktlen; */
}
}
/*
* Notice:
* Before calling this function,
* precvframe->rx_data should be ready!
*/
void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, struct phy_stat *pphy_status)
{
struct adapter *padapter = precvframe->adapter;
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
struct odm_phy_status_info *pPHYInfo = (struct odm_phy_status_info *)(&pattrib->phy_info);
u8 *wlanhdr;
struct odm_per_pkt_info pkt_info;
u8 *sa = NULL;
struct sta_priv *pstapriv;
struct sta_info *psta;
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 &&
!memcmp(get_hdr_bssid(wlanhdr),
get_bssid(&padapter->mlmepriv), ETH_ALEN));
pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
(!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))
sa = padapter->mlmepriv.cur_network.network.MacAddress;
/* to do Ad-hoc */
} 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;
pkt_info.Rate = pattrib->mcs_rate;
ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info), padapter);
precvframe->psta = NULL;
if (pkt_info.bPacketMatchBSSID &&
(check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE))) {
if (psta) {
precvframe->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)) {
if (psta)
precvframe->psta = psta;
}
rtl8188e_process_phy_info(padapter, precvframe);
}
}

View File

@ -0,0 +1,80 @@
/******************************************************************************
*
* 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_SRESET_C_
#include <rtl8188e_sreset.h>
#include <rtl8188e_hal.h>
void rtl8188e_silentreset_for_specific_platform(struct adapter *padapter)
{
}
void rtl8188e_sreset_xmit_status_check(struct adapter *padapter)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
unsigned long current_time;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
unsigned int diff_time;
u32 txdma_status;
txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
if (txdma_status != 0x00) {
DBG_88E("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
rtw_write32(padapter, REG_TXDMA_STATUS, txdma_status);
rtl8188e_silentreset_for_specific_platform(padapter);
}
/* total xmit irp = 4 */
current_time = jiffies;
if (0 == pxmitpriv->free_xmitbuf_cnt) {
diff_time = jiffies_to_msecs(current_time - psrtpriv->last_tx_time);
if (diff_time > 2000) {
if (psrtpriv->last_tx_complete_time == 0) {
psrtpriv->last_tx_complete_time = current_time;
} else {
diff_time = jiffies_to_msecs(current_time - psrtpriv->last_tx_complete_time);
if (diff_time > 4000) {
DBG_88E("%s tx hang\n", __func__);
rtl8188e_silentreset_for_specific_platform(padapter);
}
}
}
}
}
void rtl8188e_sreset_linked_status_check(struct adapter *padapter)
{
u32 rx_dma_status = 0;
u8 fw_status = 0;
rx_dma_status = rtw_read32(padapter, REG_RXDMA_STATUS);
if (rx_dma_status != 0x00) {
DBG_88E("%s REG_RXDMA_STATUS:0x%08x\n", __func__, rx_dma_status);
rtw_write32(padapter, REG_RXDMA_STATUS, rx_dma_status);
}
fw_status = rtw_read8(padapter, REG_FMETHR);
if (fw_status != 0x00) {
if (fw_status == 1)
DBG_88E("%s REG_FW_STATUS (0x%02x), Read_Efuse_Fail !!\n", __func__, fw_status);
else if (fw_status == 2)
DBG_88E("%s REG_FW_STATUS (0x%02x), Condition_No_Match !!\n", __func__, fw_status);
}
}

View File

@ -0,0 +1,91 @@
/******************************************************************************
*
* 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_XMIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8188e_hal.h>
void dump_txrpt_ccx_88e(void *buf)
{
struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf;
DBG_88E("%s:\n"
"tag1:%u, pkt_num:%u, txdma_underflow:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n"
"mac_id:%u, pkt_ok:%u, bmc:%u\n"
"retry_cnt:%u, lifetime_over:%u, retry_over:%u\n"
"ccx_qtime:%u\n"
"final_data_rate:0x%02x\n"
"qsel:%u, sw:0x%03x\n",
__func__, txrpt_ccx->tag1, txrpt_ccx->pkt_num,
txrpt_ccx->txdma_underflow, txrpt_ccx->int_bt,
txrpt_ccx->int_tri, txrpt_ccx->int_ccx,
txrpt_ccx->mac_id, txrpt_ccx->pkt_ok, txrpt_ccx->bmc,
txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over,
txrpt_ccx->retry_over, txrpt_ccx_qtime_88e(txrpt_ccx),
txrpt_ccx->final_data_rate, txrpt_ccx->qsel,
txrpt_ccx_sw_88e(txrpt_ccx)
);
}
void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf)
{
struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf;
if (txrpt_ccx->int_ccx) {
if (txrpt_ccx->pkt_ok)
rtw_ack_tx_done(&adapter->xmitpriv,
RTW_SCTX_DONE_SUCCESS);
else
rtw_ack_tx_done(&adapter->xmitpriv,
RTW_SCTX_DONE_CCX_PKT_FAIL);
}
}
void _dbg_dump_tx_info(struct adapter *padapter, int frame_tag,
struct tx_desc *ptxdesc)
{
u8 dmp_txpkt;
bool dump_txdesc = false;
rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(dmp_txpkt));
if (dmp_txpkt == 1) {/* dump txdesc for data frame */
DBG_88E("dump tx_desc for data frame\n");
if ((frame_tag & 0x0f) == DATA_FRAMETAG)
dump_txdesc = true;
} else if (dmp_txpkt == 2) {/* dump txdesc for mgnt frame */
DBG_88E("dump tx_desc for mgnt frame\n");
if ((frame_tag & 0x0f) == MGNT_FRAMETAG)
dump_txdesc = true;
}
if (dump_txdesc) {
DBG_88E("=====================================\n");
DBG_88E("txdw0(0x%08x)\n", ptxdesc->txdw0);
DBG_88E("txdw1(0x%08x)\n", ptxdesc->txdw1);
DBG_88E("txdw2(0x%08x)\n", ptxdesc->txdw2);
DBG_88E("txdw3(0x%08x)\n", ptxdesc->txdw3);
DBG_88E("txdw4(0x%08x)\n", ptxdesc->txdw4);
DBG_88E("txdw5(0x%08x)\n", ptxdesc->txdw5);
DBG_88E("txdw6(0x%08x)\n", ptxdesc->txdw6);
DBG_88E("txdw7(0x%08x)\n", ptxdesc->txdw7);
DBG_88E("=====================================\n");
}
}

View File

@ -0,0 +1,111 @@
/******************************************************************************
*
* 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
*
*
******************************************************************************/
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8188e_hal.h>
#include <rtl8188e_led.h>
/* LED object. */
/* LED_819xUsb routines. */
/* Description: */
/* Turn on LED according to LedPin specified. */
void SwLedOn(struct adapter *padapter, struct LED_871x *pLed)
{
u8 LedCfg;
if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
return;
LedCfg = rtw_read8(padapter, REG_LEDCFG2);
switch (pLed->LedPin) {
case LED_PIN_LED0:
rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
break;
case LED_PIN_LED1:
rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x0f)|BIT5); /* SW control led1 on. */
break;
default:
break;
}
pLed->bLedOn = true;
}
/* Description: */
/* Turn off LED according to LedPin specified. */
void SwLedOff(struct adapter *padapter, struct LED_871x *pLed)
{
u8 LedCfg;
struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
goto exit;
LedCfg = rtw_read8(padapter, REG_LEDCFG2);/* 0x4E */
switch (pLed->LedPin) {
case LED_PIN_LED0:
if (pHalData->bLedOpenDrain) {
/* Open-drain arrangement for controlling the LED) */
LedCfg &= 0x90; /* Set to software control. */
rtw_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3));
LedCfg = rtw_read8(padapter, REG_MAC_PINMUX_CFG);
LedCfg &= 0xFE;
rtw_write8(padapter, REG_MAC_PINMUX_CFG, LedCfg);
} else {
rtw_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3|BIT5|BIT6));
}
break;
case LED_PIN_LED1:
LedCfg &= 0x0f; /* Set to software control. */
rtw_write8(padapter, REG_LEDCFG2, (LedCfg|BIT3));
break;
default:
break;
}
exit:
pLed->bLedOn = false;
}
/* Interface to manipulate LED objects. */
/* Default LED behavior. */
/* Description: */
/* Initialize all LED_871x objects. */
void rtl8188eu_InitSwLeds(struct adapter *padapter)
{
struct led_priv *pledpriv = &(padapter->ledpriv);
pledpriv->LedControlHandler = LedControl8188eu;
InitLed871x(padapter, &(pledpriv->SwLed0), LED_PIN_LED0);
InitLed871x(padapter, &(pledpriv->SwLed1), LED_PIN_LED1);
}
/* Description: */
/* DeInitialize all LED_819xUsb objects. */
void rtl8188eu_DeInitSwLeds(struct adapter *padapter)
{
struct led_priv *ledpriv = &(padapter->ledpriv);
DeInitLed871x(&(ledpriv->SwLed0));
DeInitLed871x(&(ledpriv->SwLed1));
}

View File

@ -0,0 +1,136 @@
/******************************************************************************
*
* 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 _RTL8188EU_RECV_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <mlme_osdep.h>
#include <ip.h>
#include <if_ether.h>
#include <ethernet.h>
#include <usb_ops.h>
#include <wifi.h>
#include <rtl8188e_hal.h>
void rtl8188eu_init_recvbuf(struct adapter *padapter, struct recv_buf *precvbuf)
{
precvbuf->transfer_len = 0;
precvbuf->len = 0;
precvbuf->ref_cnt = 0;
if (precvbuf->pbuf) {
precvbuf->pdata = precvbuf->pbuf;
precvbuf->phead = precvbuf->pbuf;
precvbuf->ptail = precvbuf->pbuf;
precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
}
}
int rtl8188eu_init_recv_priv(struct adapter *padapter)
{
struct recv_priv *precvpriv = &padapter->recvpriv;
int i, res = _SUCCESS;
struct recv_buf *precvbuf;
tasklet_init(&precvpriv->recv_tasklet,
(void(*)(unsigned long))rtl8188eu_recv_tasklet,
(unsigned long)padapter);
/* init recv_buf */
_rtw_init_queue(&precvpriv->free_recv_buf_queue);
precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4);
if (precvpriv->pallocated_recv_buf == NULL) {
res = _FAIL;
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
goto exit;
}
memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF * sizeof(struct recv_buf) + 4);
precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_recv_buf), 4);
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
INIT_LIST_HEAD(&precvbuf->list);
spin_lock_init(&precvbuf->recvbuf_lock);
precvbuf->alloc_sz = MAX_RECVBUF_SZ;
res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
if (res == _FAIL)
break;
precvbuf->ref_cnt = 0;
precvbuf->adapter = padapter;
precvbuf++;
}
precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
skb_queue_head_init(&precvpriv->rx_skb_queue);
{
int i;
size_t tmpaddr = 0;
size_t alignment = 0;
struct sk_buff *pskb = NULL;
skb_queue_head_init(&precvpriv->free_recv_skb_queue);
for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
pskb = __netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, GFP_KERNEL);
if (pskb) {
pskb->dev = padapter->pnetdev;
tmpaddr = (size_t)pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
}
pskb = NULL;
}
}
exit:
return res;
}
void rtl8188eu_free_recv_priv(struct adapter *padapter)
{
int i;
struct recv_buf *precvbuf;
struct recv_priv *precvpriv = &padapter->recvpriv;
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
rtw_os_recvbuf_resource_free(padapter, precvbuf);
precvbuf++;
}
kfree(precvpriv->pallocated_recv_buf);
if (skb_queue_len(&precvpriv->rx_skb_queue))
DBG_88E(KERN_WARNING "rx_skb_queue not empty\n");
skb_queue_purge(&precvpriv->rx_skb_queue);
if (skb_queue_len(&precvpriv->free_recv_skb_queue))
DBG_88E(KERN_WARNING "free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
skb_queue_purge(&precvpriv->free_recv_skb_queue);
}

View File

@ -0,0 +1,703 @@
/******************************************************************************
*
* 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_XMIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <wifi.h>
#include <osdep_intf.h>
#include <usb_ops.h>
#include <rtl8188e_hal.h>
s32 rtl8188eu_init_xmit_priv(struct adapter *adapt)
{
struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
tasklet_init(&pxmitpriv->xmit_tasklet,
(void(*)(unsigned long))rtl8188eu_xmit_tasklet,
(unsigned long)adapt);
return _SUCCESS;
}
void rtl8188eu_free_xmit_priv(struct adapter *adapt)
{
}
static u8 urb_zero_packet_chk(struct adapter *adapt, int sz)
{
u8 set_tx_desc_offset;
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
set_tx_desc_offset = (((sz + TXDESC_SIZE) % haldata->UsbBulkOutSize) == 0) ? 1 : 0;
return set_tx_desc_offset;
}
static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
{
u16 *usptr = (u16 *)ptxdesc;
u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
u32 index;
u16 checksum = 0;
/* Clear first */
ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
for (index = 0; index < count; index++)
checksum = checksum ^ le16_to_cpu(*(__le16 *)(usptr + index));
ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum);
}
/* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
/* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
/* Fw can tell Hw to send these packet derectly. */
void rtl8188e_fill_fake_txdesc(struct adapter *adapt, u8 *desc, u32 BufferLen, u8 ispspoll, u8 is_btqosnull)
{
struct tx_desc *ptxdesc;
/* Clear all status */
ptxdesc = (struct tx_desc *)desc;
memset(desc, 0, TXDESC_SIZE);
/* offset 0 */
ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); /* own, bFirstSeg, bLastSeg; */
ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); /* 32 bytes for TX Desc */
ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff); /* Buffer size + command header */
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00); /* Fixed queue of Mgnt queue */
/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
if (ispspoll) {
ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
} else {
ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */
ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
}
if (is_btqosnull)
ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
/* offset 16 */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
/* USB interface drop packet if the checksum of descriptor isn't correct. */
/* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
rtl8188eu_cal_txdesc_chksum(ptxdesc);
}
static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
{
if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
switch (pattrib->encrypt) {
/* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */
case _WEP40_:
case _WEP104_:
ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
break;
case _TKIP_:
case _TKIP_WTMIC_:
ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
break;
case _AES_:
ptxdesc->txdw1 |= cpu_to_le32((0x03<<SEC_TYPE_SHT)&0x00c00000);
ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
break;
case _NO_PRIVACY_:
default:
break;
}
}
}
static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
{
switch (pattrib->vcs_mode) {
case RTS_CTS:
*pdw |= cpu_to_le32(RTS_EN);
break;
case CTS_TO_SELF:
*pdw |= cpu_to_le32(CTS_2_SELF);
break;
case NONE_VCS:
default:
break;
}
if (pattrib->vcs_mode) {
*pdw |= cpu_to_le32(HW_RTS_EN);
/* Set RTS BW */
if (pattrib->ht_en) {
*pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
*pdw |= cpu_to_le32((0x01 << 28) & 0x30000000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
*pdw |= cpu_to_le32((0x02 << 28) & 0x30000000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
*pdw |= 0;
else
*pdw |= cpu_to_le32((0x03 << 28) & 0x30000000);
}
}
}
static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
{
if (pattrib->ht_en) {
*pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
*pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
*pdw |= cpu_to_le32((0x02 << DATA_SC_SHT) & 0x003f0000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
*pdw |= 0;
else
*pdw |= cpu_to_le32((0x03 << DATA_SC_SHT) & 0x003f0000);
}
}
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
{
int pull = 0;
uint qsel;
u8 data_rate, pwr_status, offset;
struct adapter *adapt = pxmitframe->padapter;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
int bmcst = IS_MCAST(pattrib->ra);
if (adapt->registrypriv.mp_mode == 0) {
if ((!bagg_pkt) && (urb_zero_packet_chk(adapt, sz) == 0)) {
ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
pull = 1;
}
}
memset(ptxdesc, 0, sizeof(struct tx_desc));
/* 4 offset 0 */
ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);/* update TXPKTSIZE */
offset = TXDESC_SIZE + OFFSET_SZ;
ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);/* 32 bytes for TX Desc */
if (bmcst)
ptxdesc->txdw0 |= cpu_to_le32(BMC);
if (adapt->registrypriv.mp_mode == 0) {
if (!bagg_pkt) {
if ((pull) && (pxmitframe->pkt_offset > 0))
pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1;
}
}
/* pkt_offset, unit:8 bytes padding */
if (pxmitframe->pkt_offset > 0)
ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
/* driver uses rate */
ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */
if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F);
qsel = (uint)(pattrib->qsel & 0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000);
fill_txdesc_sectype(pattrib, ptxdesc);
if (pattrib->ampdu_en) {
ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);/* AGG EN */
ptxdesc->txdw6 = cpu_to_le32(0x6666f800);
} else {
ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */
}
/* offset 8 */
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000);
/* offset 16 , offset 20 */
if (pattrib->qos_en)
ptxdesc->txdw4 |= cpu_to_le32(QOS);/* QoS */
/* offset 20 */
if (pxmitframe->agg_num > 1)
ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000);
if ((pattrib->ether_type != 0x888e) &&
(pattrib->ether_type != 0x0806) &&
(pattrib->ether_type != 0x88b4) &&
(pattrib->dhcp_pkt != 1)) {
/* Non EAP & ARP & DHCP type data packet */
fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate=24M */
ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */
if (pattrib->ht_en) {
if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id))
ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */
}
data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id);
ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F);
pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id);
ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT);
} else {
/* EAP data packet and ARP packet and DHCP. */
/* Use the 1M data rate to send the EAP/ARP packet. */
/* This will maybe make the handshake smooth. */
ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */
if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
}
} else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f);
qsel = (uint)(pattrib->qsel&0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000);
/* offset 8 */
/* CCX-TXRPT ack for xmit mgmt frames. */
if (pxmitframe->ack_report)
ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0FFF0000);
/* offset 20 */
ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);/* retry limit enable */
if (pattrib->retry_ctrl)
ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
else
ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
} else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
} else if (((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) &&
(adapt->registrypriv.mp_mode == 1)) {
fill_txdesc_for_mp(adapt, ptxdesc);
} else {
DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */
ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000);/* raid */
/* offset 8 */
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0fff0000);
/* offset 20 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
}
/* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
/* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
/* mgnt frame should be controlled by Hw because Fw will also send null data */
/* which we cannot control when Fw LPS enable. */
/* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
/* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
/* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
/* 2010.06.23. Added by tynli. */
if (!pattrib->qos_en) {
ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ); /* Hw set sequence number */
ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */
}
ODM_SetTxAntByTxInfo_88E(&haldata->odmpriv, pmem, pattrib->mac_id);
rtl8188eu_cal_txdesc_chksum(ptxdesc);
_dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc);
return pull;
}
/* for non-agg data frame or management frame */
static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
s32 ret = _SUCCESS;
s32 inner_ret = _SUCCESS;
int t, sz, w_sz, pull = 0;
u8 *mem_addr;
u32 ff_hwaddr;
struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
struct security_priv *psecuritypriv = &adapt->securitypriv;
if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
(pxmitframe->attrib.ether_type != 0x0806) &&
(pxmitframe->attrib.ether_type != 0x888e) &&
(pxmitframe->attrib.ether_type != 0x88b4) &&
(pxmitframe->attrib.dhcp_pkt != 1))
rtw_issue_addbareq_cmd(adapt, pxmitframe);
mem_addr = pxmitframe->buf_addr;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
for (t = 0; t < pattrib->nr_frags; t++) {
if (inner_ret != _SUCCESS && ret == _SUCCESS)
ret = _FAIL;
if (t != (pattrib->nr_frags - 1)) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("pattrib->nr_frags=%d\n", pattrib->nr_frags));
sz = pxmitpriv->frag_len;
sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);
} else {
/* no frag */
sz = pattrib->last_txcmdsz;
}
pull = update_txdesc(pxmitframe, mem_addr, sz, false);
if (pull) {
mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
pxmitframe->buf_addr = mem_addr;
w_sz = sz + TXDESC_SIZE;
} else {
w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
}
ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
inner_ret = rtw_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);
rtw_count_tx_stats(adapt, pxmitframe, sz);
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_write_port, w_sz=%d\n", w_sz));
mem_addr += w_sz;
mem_addr = (u8 *)RND4(((size_t)(mem_addr)));
}
rtw_free_xmitframe(pxmitpriv, pxmitframe);
if (ret != _SUCCESS)
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
return ret;
}
static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
{
struct pkt_attrib *pattrib = &pxmitframe->attrib;
u32 len = 0;
/* no consider fragement */
len = pattrib->hdrlen + pattrib->iv_len +
SNAP_SIZE + sizeof(u16) +
pattrib->pktlen +
((pattrib->bswenc) ? pattrib->icv_len : 0);
if (pattrib->encrypt == _TKIP_)
len += 8;
return len;
}
s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
{
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct xmit_frame *pxmitframe = NULL;
struct xmit_frame *pfirstframe = NULL;
/* aggregate variable */
struct hw_xmit *phwxmit;
struct sta_info *psta = NULL;
struct tx_servq *ptxservq = NULL;
struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL;
u32 pbuf; /* next pkt address */
u32 pbuf_tail; /* last pkt tail */
u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */
u32 bulksize = haldata->UsbBulkOutSize;
u8 desc_cnt;
u32 bulkptr;
/* dump frame variable */
u32 ff_hwaddr;
RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n"));
/* check xmitbuffer is ok */
if (pxmitbuf == NULL) {
pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
if (pxmitbuf == NULL)
return false;
}
/* 3 1. pick up first frame */
do {
rtw_free_xmitframe(pxmitpriv, pxmitframe);
pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
if (pxmitframe == NULL) {
/* no more xmit frame, release xmit buffer */
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
return false;
}
pxmitframe->pxmitbuf = pxmitbuf;
pxmitframe->buf_addr = pxmitbuf->pbuf;
pxmitbuf->priv_data = pxmitframe;
pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
/* always return ndis_packet after rtw_xmitframe_coalesce */
rtw_os_xmit_complete(adapt, pxmitframe);
break;
} while (1);
/* 3 2. aggregate same priority and same DA(AP or STA) frames */
pfirstframe = pxmitframe;
len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset*PACKET_OFFSET_SZ);
pbuf_tail = len;
pbuf = _RND8(pbuf_tail);
/* check pkt amount in one bulk */
desc_cnt = 0;
bulkptr = bulksize;
if (pbuf < bulkptr) {
desc_cnt++;
} else {
desc_cnt = 0;
bulkptr = ((pbuf / bulksize) + 1) * bulksize; /* round to next bulksize */
}
/* dequeue same priority packet from station tx queue */
psta = pfirstframe->attrib.psta;
switch (pfirstframe->attrib.priority) {
case 1:
case 2:
ptxservq = &(psta->sta_xmitpriv.bk_q);
phwxmit = pxmitpriv->hwxmits + 3;
break;
case 4:
case 5:
ptxservq = &(psta->sta_xmitpriv.vi_q);
phwxmit = pxmitpriv->hwxmits + 1;
break;
case 6:
case 7:
ptxservq = &(psta->sta_xmitpriv.vo_q);
phwxmit = pxmitpriv->hwxmits;
break;
case 0:
case 3:
default:
ptxservq = &(psta->sta_xmitpriv.be_q);
phwxmit = pxmitpriv->hwxmits + 2;
break;
}
spin_lock_bh(&pxmitpriv->lock);
xmitframe_phead = get_list_head(&ptxservq->sta_pending);
xmitframe_plist = xmitframe_phead->next;
while (xmitframe_phead != xmitframe_plist) {
pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
xmitframe_plist = xmitframe_plist->next;
pxmitframe->agg_num = 0; /* not first frame of aggregation */
pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */
len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset*PACKET_OFFSET_SZ);
if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) {
pxmitframe->agg_num = 1;
pxmitframe->pkt_offset = 1;
break;
}
list_del_init(&pxmitframe->list);
ptxservq->qcnt--;
phwxmit->accnt--;
pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf;
rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
/* always return ndis_packet after rtw_xmitframe_coalesce */
rtw_os_xmit_complete(adapt, pxmitframe);
/* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */
update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, true);
/* don't need xmitframe any more */
rtw_free_xmitframe(pxmitpriv, pxmitframe);
/* handle pointer and stop condition */
pbuf_tail = pbuf + len;
pbuf = _RND8(pbuf_tail);
pfirstframe->agg_num++;
if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)
break;
if (pbuf < bulkptr) {
desc_cnt++;
if (desc_cnt == haldata->UsbTxAggDescNum)
break;
} else {
desc_cnt = 0;
bulkptr = ((pbuf / bulksize) + 1) * bulksize;
}
} /* end while (aggregate same priority and same DA(AP or STA) frames) */
if (list_empty(&ptxservq->sta_pending.queue))
list_del_init(&ptxservq->tx_pending);
spin_unlock_bh(&pxmitpriv->lock);
if ((pfirstframe->attrib.ether_type != 0x0806) &&
(pfirstframe->attrib.ether_type != 0x888e) &&
(pfirstframe->attrib.ether_type != 0x88b4) &&
(pfirstframe->attrib.dhcp_pkt != 1))
rtw_issue_addbareq_cmd(adapt, pfirstframe);
/* 3 3. update first frame txdesc */
if ((pbuf_tail % bulksize) == 0) {
/* remove pkt_offset */
pbuf_tail -= PACKET_OFFSET_SZ;
pfirstframe->buf_addr += PACKET_OFFSET_SZ;
pfirstframe->pkt_offset--;
}
update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, true);
/* 3 4. write xmit buffer to USB FIFO */
ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
rtw_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);
/* 3 5. update statisitc */
pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);
rtw_count_tx_stats(adapt, pfirstframe, pbuf_tail);
rtw_free_xmitframe(pxmitpriv, pfirstframe);
return true;
}
static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
s32 res = _SUCCESS;
res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
if (res == _SUCCESS)
rtw_dump_xframe(adapt, pxmitframe);
else
DBG_88E("==> %s xmitframe_coalsece failed\n", __func__);
return res;
}
/*
* Return
* true dump packet directly
* false enqueue packet
*/
static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
s32 res;
struct xmit_buf *pxmitbuf = NULL;
struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
spin_lock_bh(&pxmitpriv->lock);
if (rtw_txframes_sta_ac_pending(adapt, pattrib) > 0)
goto enqueue;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
goto enqueue;
pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
if (pxmitbuf == NULL)
goto enqueue;
spin_unlock_bh(&pxmitpriv->lock);
pxmitframe->pxmitbuf = pxmitbuf;
pxmitframe->buf_addr = pxmitbuf->pbuf;
pxmitbuf->priv_data = pxmitframe;
if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) {
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
rtw_free_xmitframe(pxmitpriv, pxmitframe);
}
return true;
enqueue:
res = rtw_xmitframe_enqueue(adapt, pxmitframe);
spin_unlock_bh(&pxmitpriv->lock);
if (res != _SUCCESS) {
RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n"));
rtw_free_xmitframe(pxmitpriv, pxmitframe);
/* Trick, make the statistics correct */
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
return true;
}
return false;
}
s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
{
return rtw_dump_xframe(adapt, pmgntframe);
}
/*
* Return
* true dump packet directly ok
* false temporary can't transmit packets to hardware
*/
s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
{
return pre_xmitframe(adapt, pxmitframe);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,717 @@
/******************************************************************************
*
* 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 _HCI_OPS_OS_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <osdep_intf.h>
#include <usb_ops.h>
#include <recv_osdep.h>
#include <rtl8188e_hal.h>
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
{
struct adapter *adapt = pintfhdl->padapter;
struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
struct usb_device *udev = dvobjpriv->pusbdev;
unsigned int pipe;
int status = 0;
u8 reqtype;
u8 *pIo_buf;
int vendorreq_times = 0;
if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usbctrl_vendorreq:(adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
status = -EPERM;
goto exit;
}
if (len > MAX_VENDOR_REQ_CMD_SIZE) {
DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__);
status = -EINVAL;
goto exit;
}
_enter_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
/* Acquire IO memory for vendorreq */
pIo_buf = dvobjpriv->usb_vendor_req_buf;
if (pIo_buf == NULL) {
DBG_88E("[%s] pIo_buf == NULL\n", __func__);
status = -ENOMEM;
goto release_mutex;
}
while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
memset(pIo_buf, 0, len);
if (requesttype == 0x01) {
pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
reqtype = REALTEK_USB_VENQT_READ;
} else {
pipe = usb_sndctrlpipe(udev, 0);/* write_out */
reqtype = REALTEK_USB_VENQT_WRITE;
memcpy(pIo_buf, pdata, len);
}
status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
if (status == len) { /* Success this control transfer. */
rtw_reset_continual_urb_error(dvobjpriv);
if (requesttype == 0x01)
memcpy(pdata, pIo_buf, len);
} else { /* error cases */
DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n",
value, (requesttype == 0x01) ? "read" : "write",
len, status, *(u32 *)pdata, vendorreq_times);
if (status < 0) {
if (status == (-ESHUTDOWN) || status == -ENODEV) {
adapt->bSurpriseRemoved = true;
} else {
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
haldata->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
}
} else { /* status != len && status >= 0 */
if (status > 0) {
if (requesttype == 0x01) {
/* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
memcpy(pdata, pIo_buf, len);
}
}
}
if (rtw_inc_and_chk_continual_urb_error(dvobjpriv)) {
adapt->bSurpriseRemoved = true;
break;
}
}
/* firmware download is checksumed, don't retry */
if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
break;
}
release_mutex:
_exit_critical_mutex(&dvobjpriv->usb_vendor_req_mutex, NULL);
exit:
return status;
}
static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u8 data = 0;
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 1;
usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return data;
}
static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
__le32 data;
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 2;
usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return (u16)(le32_to_cpu(data)&0xffff);
}
static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
__le32 data;
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 4;
usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return le32_to_cpu(data);
}
static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u8 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 1;
data = val;
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return ret;
}
static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
__le32 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 2;
data = cpu_to_le32(val & 0x0000ffff);
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return ret;
}
static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
__le32 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 4;
data = cpu_to_le32(val);
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return ret;
}
static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = length;
memcpy(buf, pdata, len);
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
return ret;
}
static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
{
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) {
DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len);
return;
}
/* HISR */
memcpy(&(haldata->IntArray[0]), &(pbuf[USB_INTR_CONTENT_HISR_OFFSET]), 4);
memcpy(&(haldata->IntArray[1]), &(pbuf[USB_INTR_CONTENT_HISRE_OFFSET]), 4);
/* C2H Event */
if (pbuf[0] != 0)
memcpy(&(haldata->C2hArray[0]), &(pbuf[USB_INTR_CONTENT_C2H_OFFSET]), 16);
}
static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
{
u8 *pbuf;
u8 shift_sz = 0;
u16 pkt_cnt;
u32 pkt_offset, skb_len, alloc_sz;
s32 transfer_len;
struct recv_stat *prxstat;
struct phy_stat *pphy_status = NULL;
struct sk_buff *pkt_copy = NULL;
struct recv_frame *precvframe = NULL;
struct rx_pkt_attrib *pattrib = NULL;
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
struct recv_priv *precvpriv = &adapt->recvpriv;
struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
transfer_len = (s32)pskb->len;
pbuf = pskb->data;
prxstat = (struct recv_stat *)pbuf;
pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
do {
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
("recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
prxstat->rxdw0, prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
prxstat = (struct recv_stat *)pbuf;
precvframe = rtw_alloc_recvframe(pfree_recv_queue);
if (precvframe == NULL) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvbuf2recvframe: precvframe==NULL\n"));
DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__);
goto _exit_recvbuf2recvframe;
}
INIT_LIST_HEAD(&precvframe->list);
precvframe->precvbuf = NULL; /* can't access the precvbuf for new arch. */
precvframe->len = 0;
update_recvframe_attrib_88e(precvframe, prxstat);
pattrib = &precvframe->attrib;
if ((pattrib->crc_err) || (pattrib->icv_err)) {
DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
rtw_free_recvframe(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recvbuf2recvframe: pkt_len<=0\n"));
DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfoer_len\n", __func__, __LINE__);
rtw_free_recvframe(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
/* Modified by Albert 20101213 */
/* For 8 bytes IP header alignment. */
if (pattrib->qos) /* Qos data, wireless lan header length is 26 */
shift_sz = 6;
else
shift_sz = 0;
skb_len = pattrib->pkt_len;
/* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
/* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
if (skb_len <= 1650)
alloc_sz = 1664;
else
alloc_sz = skb_len + 14;
} else {
alloc_sz = skb_len;
/* 6 is for IP header 8 bytes alignment in QoS packet case. */
/* 8 is for skb->data 4 bytes alignment. */
alloc_sz += 14;
}
pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
if (pkt_copy) {
pkt_copy->dev = adapt->pnetdev;
precvframe->pkt = pkt_copy;
precvframe->rx_head = pkt_copy->data;
precvframe->rx_end = pkt_copy->data + alloc_sz;
skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
precvframe->rx_tail = pkt_copy->data;
precvframe->rx_data = pkt_copy->data;
} else {
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
DBG_88E("recvbuf2recvframe: alloc_skb fail , drop frag frame\n");
rtw_free_recvframe(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
if (precvframe->pkt) {
precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
precvframe->rx_head = precvframe->rx_tail;
precvframe->rx_data = precvframe->rx_tail;
precvframe->rx_end = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
} else {
DBG_88E("recvbuf2recvframe: skb_clone fail\n");
rtw_free_recvframe(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
}
recvframe_put(precvframe, skb_len);
switch (haldata->UsbRxAggMode) {
case USB_RX_AGG_DMA:
case USB_RX_AGG_MIX:
pkt_offset = (u16)_RND128(pkt_offset);
break;
case USB_RX_AGG_USB:
pkt_offset = (u16)_RND4(pkt_offset);
break;
case USB_RX_AGG_DISABLE:
default:
break;
}
if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
if (pattrib->physt)
update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status);
if (rtw_recv_entry(precvframe) != _SUCCESS) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
}
} else {
/* enqueue recvframe to txrtp queue */
if (pattrib->pkt_rpt_type == TX_REPORT1) {
/* CCX-TXRPT ack for xmit mgmt frames. */
handle_txrpt_ccx_88e(adapt, precvframe->rx_data);
} else if (pattrib->pkt_rpt_type == TX_REPORT2) {
ODM_RA_TxRPT2Handle_8188E(
&haldata->odmpriv,
precvframe->rx_data,
pattrib->pkt_len,
pattrib->MacIDValidEntry[0],
pattrib->MacIDValidEntry[1]
);
} else if (pattrib->pkt_rpt_type == HIS_REPORT) {
interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->rx_data);
}
rtw_free_recvframe(precvframe, pfree_recv_queue);
}
pkt_cnt--;
transfer_len -= pkt_offset;
pbuf += pkt_offset;
precvframe = NULL;
pkt_copy = NULL;
if (transfer_len > 0 && pkt_cnt == 0)
pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
} while ((transfer_len > 0) && (pkt_cnt > 0));
_exit_recvbuf2recvframe:
return _SUCCESS;
}
void rtl8188eu_recv_tasklet(void *priv)
{
struct sk_buff *pskb;
struct adapter *adapt = (struct adapter *)priv;
struct recv_priv *precvpriv = &adapt->recvpriv;
while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
dev_kfree_skb_any(pskb);
break;
}
recvbuf2recvframe(adapt, pskb);
skb_reset_tail_pointer(pskb);
pskb->len = 0;
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
}
}
static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
{
struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
struct adapter *adapt = (struct adapter *)precvbuf->adapter;
struct recv_priv *precvpriv = &adapt->recvpriv;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete!!!\n"));
precvpriv->rx_pending_cnt--;
if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
adapt->bDriverStopped, adapt->bSurpriseRemoved));
precvbuf->reuse = true;
DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
__func__, adapt->bDriverStopped,
adapt->bSurpriseRemoved, adapt->bReadPortCancel);
return;
}
if (purb->status == 0) { /* SUCCESS */
if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n"));
precvbuf->reuse = true;
rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__);
} else {
rtw_reset_continual_urb_error(adapter_to_dvobj(adapt));
precvbuf->transfer_len = purb->actual_length;
skb_put(precvbuf->pskb, purb->actual_length);
skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
tasklet_schedule(&precvpriv->recv_tasklet);
precvbuf->pskb = NULL;
precvbuf->reuse = false;
rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
}
} else {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status));
DBG_88E("###=> usb_read_port_complete => urb status(%d)\n", purb->status);
skb_put(precvbuf->pskb, purb->actual_length);
precvbuf->pskb = NULL;
if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt)))
adapt->bSurpriseRemoved = true;
switch (purb->status) {
case -EINVAL:
case -EPIPE:
case -ENODEV:
case -ESHUTDOWN:
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bSurpriseRemoved=true\n"));
__attribute__((__fallthrough__));
case -ENOENT:
adapt->bDriverStopped = true;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bDriverStopped=true\n"));
break;
case -EPROTO:
case -EOVERFLOW:
{
struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
haldata->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;
}
precvbuf->reuse = true;
rtw_read_port(adapt, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
break;
case -EINPROGRESS:
DBG_88E("ERROR: URB IS IN PROGRESS!/n");
break;
default:
break;
}
}
}
static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
{
struct urb *purb = NULL;
struct recv_buf *precvbuf = (struct recv_buf *)rmem;
struct adapter *adapter = pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
struct recv_priv *precvpriv = &adapter->recvpriv;
struct usb_device *pusbd = pdvobj->pusbdev;
int err;
unsigned int pipe;
size_t tmpaddr = 0;
size_t alignment = 0;
u32 ret = _SUCCESS;
if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
adapter->pwrctrlpriv.pnp_bstop_trx) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port:(adapt->bDriverStopped ||adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
return _FAIL;
}
if (!precvbuf) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port:precvbuf==NULL\n"));
return _FAIL;
}
if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
if (NULL != precvbuf->pskb)
precvbuf->reuse = true;
}
rtl8188eu_init_recvbuf(adapter, precvbuf);
/* re-assign for linux based on skb */
if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
if (precvbuf->pskb == NULL) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
return _FAIL;
}
tmpaddr = (size_t)precvbuf->pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
precvbuf->phead = precvbuf->pskb->head;
precvbuf->pdata = precvbuf->pskb->data;
precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
precvbuf->pend = skb_end_pointer(precvbuf->pskb);
precvbuf->pbuf = precvbuf->pskb->data;
} else { /* reuse skb */
precvbuf->phead = precvbuf->pskb->head;
precvbuf->pdata = precvbuf->pskb->data;
precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
precvbuf->pend = skb_end_pointer(precvbuf->pskb);
precvbuf->pbuf = precvbuf->pskb->data;
precvbuf->reuse = false;
}
precvpriv->rx_pending_cnt++;
purb = precvbuf->purb;
/* translate DMA FIFO addr to pipehandle */
pipe = ffaddr2pipehdl(pdvobj, addr);
usb_fill_bulk_urb(purb, pusbd, pipe,
precvbuf->pbuf,
MAX_RECVBUF_SZ,
usb_read_port_complete,
precvbuf);/* context is precvbuf */
err = usb_submit_urb(purb, GFP_ATOMIC);
if ((err) && (err != (-EPERM))) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
err, purb->status));
DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
err, purb->status);
ret = _FAIL;
}
return ret;
}
void rtl8188eu_xmit_tasklet(void *priv)
{
int ret = false;
struct adapter *adapt = (struct adapter *)priv;
struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
return;
while (1) {
if ((adapt->bDriverStopped) ||
(adapt->bSurpriseRemoved) ||
(adapt->bWritePortCancel)) {
DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
break;
}
ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL);
if (!ret)
break;
}
}
void rtl8188eu_set_intf_ops(struct _io_ops *pops)
{
memset((u8 *)pops, 0, sizeof(struct _io_ops));
pops->_read8 = &usb_read8;
pops->_read16 = &usb_read16;
pops->_read32 = &usb_read32;
pops->_read_mem = &usb_read_mem;
pops->_read_port = &usb_read_port;
pops->_write8 = &usb_write8;
pops->_write16 = &usb_write16;
pops->_write32 = &usb_write32;
pops->_writeN = &usb_writeN;
pops->_write_mem = &usb_write_mem;
pops->_write_port = &usb_write_port;
pops->_read_port_cancel = &usb_read_port_cancel;
pops->_write_port_cancel = &usb_write_port_cancel;
}
void rtl8188eu_set_hw_type(struct adapter *adapt)
{
adapt->chip_type = RTL8188E;
adapt->HardwareType = HARDWARE_TYPE_RTL8188EU;
DBG_88E("CHIP TYPE: RTL8188E\n");
}