staging: r8723au: Add source files for new driver - part 2

The Realtek USB device RTL8723AU is found in Lenovo Yoga 13 tablets.
A driver for it has been available in a GitHub repo for several months.
This commit contains the second part of the source files. The source
is arbitrarily split to avoid E-mail files that are too large.

Jes Sorensen at RedHat has made many improvements to the vendor code,
and he has been doing the testing. I do not have access to this device.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Larry Finger 2014-03-28 21:37:39 -05:00 committed by Greg Kroah-Hartman
parent 5e93f35209
commit f7c92d2cc2
28 changed files with 28277 additions and 0 deletions

View File

@ -0,0 +1,80 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "Hal8723PwrSeq.h"
/*
drivers should parse below arrays and do the corresponding actions
*/
/* 3 Power on Array */
struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_CARDEMU_TO_ACT
RTL8723A_TRANS_END
};
/* 3 Radio off GPIO Array */
struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_END
};
/* 3 Card Disable Array */
struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_CARDDIS
RTL8723A_TRANS_END
};
/* 3 Card Enable Array */
struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_CARDDIS_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_ACT
RTL8723A_TRANS_END
};
/* 3 Suspend Array */
struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_SUS
RTL8723A_TRANS_END
};
/* 3 Resume Array */
struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_SUS_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_ACT
RTL8723A_TRANS_END
};
/* 3 HWPDN Array */
struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_PDN
RTL8723A_TRANS_END
};
/* 3 Enter LPS */
struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS] = {
/* FW behavior */
RTL8723A_TRANS_ACT_TO_LPS
RTL8723A_TRANS_END
};
/* 3 Leave LPS */
struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = {
/* FW behavior */
RTL8723A_TRANS_LPS_TO_ACT
RTL8723A_TRANS_END
};

View File

@ -0,0 +1,136 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/*Created on 2013/01/14, 15:51*/
#include "odm_precomp.h"
u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength] = {
0xe00, 0xffffffff, 0x0a0c0c0c,
0xe04, 0xffffffff, 0x02040608,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x0a0c0d0e,
0xe14, 0xffffffff, 0x02040608,
0xe18, 0xffffffff, 0x0a0c0d0e,
0xe1c, 0xffffffff, 0x02040608,
0x830, 0xffffffff, 0x0a0c0c0c,
0x834, 0xffffffff, 0x02040608,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x0a0c0d0e,
0x848, 0xffffffff, 0x02040608,
0x84c, 0xffffffff, 0x0a0c0d0e,
0x868, 0xffffffff, 0x02040608,
0xe00, 0xffffffff, 0x00000000,
0xe04, 0xffffffff, 0x00000000,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x00000000,
0xe14, 0xffffffff, 0x00000000,
0xe18, 0xffffffff, 0x00000000,
0xe1c, 0xffffffff, 0x00000000,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 0xffffffff, 0x00000000,
0xe00, 0xffffffff, 0x04040404,
0xe04, 0xffffffff, 0x00020204,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x06060606,
0xe14, 0xffffffff, 0x00020406,
0xe18, 0xffffffff, 0x00000000,
0xe1c, 0xffffffff, 0x00000000,
0x830, 0xffffffff, 0x04040404,
0x834, 0xffffffff, 0x00020204,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x06060606,
0x848, 0xffffffff, 0x00020406,
0x84c, 0xffffffff, 0x00000000,
0x868, 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,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 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,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 0xffffffff, 0x00000000,
0xe00, 0xffffffff, 0x04040404,
0xe04, 0xffffffff, 0x00020204,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x00000000,
0xe14, 0xffffffff, 0x00000000,
0xe18, 0xffffffff, 0x00000000,
0xe1c, 0xffffffff, 0x00000000,
0x830, 0xffffffff, 0x04040404,
0x834, 0xffffffff, 0x00020204,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 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,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 0xffffffff, 0x00000000,
};
u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength] = {
0x0,
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,726 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "odm_precomp.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;
}
/******************************************************************************
* AGC_TAB_1T.TXT
******************************************************************************/
static u32 Array_AGC_TAB_1T_8723A[] = {
0xC78, 0x7B000001,
0xC78, 0x7B010001,
0xC78, 0x7B020001,
0xC78, 0x7B030001,
0xC78, 0x7B040001,
0xC78, 0x7B050001,
0xC78, 0x7A060001,
0xC78, 0x79070001,
0xC78, 0x78080001,
0xC78, 0x77090001,
0xC78, 0x760A0001,
0xC78, 0x750B0001,
0xC78, 0x740C0001,
0xC78, 0x730D0001,
0xC78, 0x720E0001,
0xC78, 0x710F0001,
0xC78, 0x70100001,
0xC78, 0x6F110001,
0xC78, 0x6E120001,
0xC78, 0x6D130001,
0xC78, 0x6C140001,
0xC78, 0x6B150001,
0xC78, 0x6A160001,
0xC78, 0x69170001,
0xC78, 0x68180001,
0xC78, 0x67190001,
0xC78, 0x661A0001,
0xC78, 0x651B0001,
0xC78, 0x641C0001,
0xC78, 0x631D0001,
0xC78, 0x621E0001,
0xC78, 0x611F0001,
0xC78, 0x60200001,
0xC78, 0x49210001,
0xC78, 0x48220001,
0xC78, 0x47230001,
0xC78, 0x46240001,
0xC78, 0x45250001,
0xC78, 0x44260001,
0xC78, 0x43270001,
0xC78, 0x42280001,
0xC78, 0x41290001,
0xC78, 0x402A0001,
0xC78, 0x262B0001,
0xC78, 0x252C0001,
0xC78, 0x242D0001,
0xC78, 0x232E0001,
0xC78, 0x222F0001,
0xC78, 0x21300001,
0xC78, 0x20310001,
0xC78, 0x06320001,
0xC78, 0x05330001,
0xC78, 0x04340001,
0xC78, 0x03350001,
0xC78, 0x02360001,
0xC78, 0x01370001,
0xC78, 0x00380001,
0xC78, 0x00390001,
0xC78, 0x003A0001,
0xC78, 0x003B0001,
0xC78, 0x003C0001,
0xC78, 0x003D0001,
0xC78, 0x003E0001,
0xC78, 0x003F0001,
0xC78, 0x7B400001,
0xC78, 0x7B410001,
0xC78, 0x7B420001,
0xC78, 0x7B430001,
0xC78, 0x7B440001,
0xC78, 0x7B450001,
0xC78, 0x7A460001,
0xC78, 0x79470001,
0xC78, 0x78480001,
0xC78, 0x77490001,
0xC78, 0x764A0001,
0xC78, 0x754B0001,
0xC78, 0x744C0001,
0xC78, 0x734D0001,
0xC78, 0x724E0001,
0xC78, 0x714F0001,
0xC78, 0x70500001,
0xC78, 0x6F510001,
0xC78, 0x6E520001,
0xC78, 0x6D530001,
0xC78, 0x6C540001,
0xC78, 0x6B550001,
0xC78, 0x6A560001,
0xC78, 0x69570001,
0xC78, 0x68580001,
0xC78, 0x67590001,
0xC78, 0x665A0001,
0xC78, 0x655B0001,
0xC78, 0x645C0001,
0xC78, 0x635D0001,
0xC78, 0x625E0001,
0xC78, 0x615F0001,
0xC78, 0x60600001,
0xC78, 0x49610001,
0xC78, 0x48620001,
0xC78, 0x47630001,
0xC78, 0x46640001,
0xC78, 0x45650001,
0xC78, 0x44660001,
0xC78, 0x43670001,
0xC78, 0x42680001,
0xC78, 0x41690001,
0xC78, 0x406A0001,
0xC78, 0x266B0001,
0xC78, 0x256C0001,
0xC78, 0x246D0001,
0xC78, 0x236E0001,
0xC78, 0x226F0001,
0xC78, 0x21700001,
0xC78, 0x20710001,
0xC78, 0x06720001,
0xC78, 0x05730001,
0xC78, 0x04740001,
0xC78, 0x03750001,
0xC78, 0x02760001,
0xC78, 0x01770001,
0xC78, 0x00780001,
0xC78, 0x00790001,
0xC78, 0x007A0001,
0xC78, 0x007B0001,
0xC78, 0x007C0001,
0xC78, 0x007D0001,
0xC78, 0x007E0001,
0xC78, 0x007F0001,
0xC78, 0x3800001E,
0xC78, 0x3801001E,
0xC78, 0x3802001E,
0xC78, 0x3803001E,
0xC78, 0x3804001E,
0xC78, 0x3805001E,
0xC78, 0x3806001E,
0xC78, 0x3807001E,
0xC78, 0x3808001E,
0xC78, 0x3C09001E,
0xC78, 0x3E0A001E,
0xC78, 0x400B001E,
0xC78, 0x440C001E,
0xC78, 0x480D001E,
0xC78, 0x4C0E001E,
0xC78, 0x500F001E,
0xC78, 0x5210001E,
0xC78, 0x5611001E,
0xC78, 0x5A12001E,
0xC78, 0x5E13001E,
0xC78, 0x6014001E,
0xC78, 0x6015001E,
0xC78, 0x6016001E,
0xC78, 0x6217001E,
0xC78, 0x6218001E,
0xC78, 0x6219001E,
0xC78, 0x621A001E,
0xC78, 0x621B001E,
0xC78, 0x621C001E,
0xC78, 0x621D001E,
0xC78, 0x621E001E,
0xC78, 0x621F001E,
};
#define READ_NEXT_PAIR(v1, v2, i) \
do { \
i += 2; v1 = Array[i]; v2 = Array[i+1]; \
} while (0)
void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex;
u32 i;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_AGC_TAB_1T_8723A)/sizeof(u32);
u32 *Array = Array_AGC_TAB_1T_8723A;
hex = board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
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) {
odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
continue;
} else {
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) {
odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
* PHY_REG_1T.TXT
******************************************************************************/
static u32 Array_PHY_REG_1T_8723A[] = {
0x800, 0x80040000,
0x804, 0x00000003,
0x808, 0x0000FC00,
0x80C, 0x0000000A,
0x810, 0x10001331,
0x814, 0x020C3D10,
0x818, 0x02200385,
0x81C, 0x00000000,
0x820, 0x01000100,
0x824, 0x00390004,
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, 0x569A569A,
0x85C, 0x001B25A4,
0x860, 0x66F60110,
0x864, 0x061F0130,
0x868, 0x00000000,
0x86C, 0x32323200,
0x870, 0x07000760,
0x874, 0x22004000,
0x878, 0x00000808,
0x87C, 0x00000000,
0x880, 0xC0083070,
0x884, 0x000004D5,
0x888, 0x00000000,
0x88C, 0xCCC000C0,
0x890, 0x00000800,
0x894, 0xFFFFFFFE,
0x898, 0x40302010,
0x89C, 0x00706050,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90C, 0x81121111,
0xA00, 0x00D047C8,
0xA04, 0x80FF000C,
0xA08, 0x8C838300,
0xA0C, 0x2E68120F,
0xA10, 0x9500BB78,
0xA14, 0x11144028,
0xA18, 0x00881117,
0xA1C, 0x89140F00,
0xA20, 0x1A1B0000,
0xA24, 0x090E1317,
0xA28, 0x00000204,
0xA2C, 0x00D30000,
0xA70, 0x101FBF00,
0xA74, 0x00000007,
0xA78, 0x00000900,
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, 0x69E9AC44,
0xFF0F011F, 0xABCD,
0xC34, 0x469652CF,
0xCDCDCDCD, 0xCDCD,
0xC34, 0x469652AF,
0xFF0F011F, 0xDEAD,
0xC38, 0x49795994,
0xC3C, 0x0A97971C,
0xC40, 0x1F7C403F,
0xC44, 0x000100B7,
0xC48, 0xEC020107,
0xC4C, 0x007F037F,
0xC50, 0x69543420,
0xC54, 0x43BC0094,
0xC58, 0x69543420,
0xC5C, 0x433C0094,
0xC60, 0x00000000,
0xFF0F011F, 0xABCD,
0xC64, 0x7116848B,
0xCDCDCDCD, 0xCDCD,
0xC64, 0x7112848B,
0xFF0F011F, 0xDEAD,
0xC68, 0x47C00BFF,
0xC6C, 0x00000036,
0xC70, 0x2C7F000D,
0xC74, 0x018610DB,
0xC78, 0x0000001F,
0xC7C, 0x00B91612,
0xC80, 0x40000100,
0xC84, 0x20F60000,
0xC88, 0x40000100,
0xC8C, 0x20200000,
0xC90, 0x00121820,
0xC94, 0x00000000,
0xC98, 0x00121820,
0xC9C, 0x00007F7F,
0xCA0, 0x00000000,
0xCA4, 0x00000080,
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, 0x00080740,
0xD04, 0x00020401,
0xD08, 0x0000907F,
0xD0C, 0x20010201,
0xD10, 0xA0633333,
0xD14, 0x3333BC43,
0xD18, 0x7A8F5B6B,
0xD2C, 0xCC979975,
0xD30, 0x00000000,
0xD34, 0x80608000,
0xD38, 0x00000000,
0xD3C, 0x00027293,
0xD40, 0x00000000,
0xD44, 0x00000000,
0xD48, 0x00000000,
0xD4C, 0x00000000,
0xD50, 0x6437140A,
0xD54, 0x00000000,
0xD58, 0x00000000,
0xD5C, 0x30032064,
0xD60, 0x4653DE68,
0xD64, 0x04518A3C,
0xD68, 0x00002101,
0xD6C, 0x2A201C16,
0xD70, 0x1812362E,
0xD74, 0x322C2220,
0xD78, 0x000E3C24,
0xE00, 0x2A2A2A2A,
0xE04, 0x2A2A2A2A,
0xE08, 0x03902A2A,
0xE10, 0x2A2A2A2A,
0xE14, 0x2A2A2A2A,
0xE18, 0x2A2A2A2A,
0xE1C, 0x2A2A2A2A,
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, 0x631B25A0,
0xE70, 0x631B25A0,
0xE74, 0x081B25A0,
0xE78, 0x081B25A0,
0xE7C, 0x081B25A0,
0xE80, 0x081B25A0,
0xE84, 0x631B25A0,
0xE88, 0x081B25A0,
0xE8C, 0x631B25A0,
0xED0, 0x631B25A0,
0xED4, 0x631B25A0,
0xED8, 0x631B25A0,
0xEDC, 0x001B25A0,
0xEE0, 0x001B25A0,
0xEEC, 0x6B1B25A0,
0xF14, 0x00000003,
0xF4C, 0x00000000,
0xF00, 0x00000300,
};
void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_PHY_REG_1T_8723A)/sizeof(u32);
u32 *Array = Array_PHY_REG_1T_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
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) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
continue;
} else {
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) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
* PHY_REG_MP.TXT
******************************************************************************/
static u32 Array_PHY_REG_MP_8723A[] = {
0xC30, 0x69E9AC4A,
0xC3C, 0x0A979718,
};
void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_PHY_REG_MP_8723A)/sizeof(u32);
u32 *Array = Array_PHY_REG_MP_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
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) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
continue;
} else {
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) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
* PHY_REG_PG.TXT
******************************************************************************/
static u32 Array_PHY_REG_PG_8723A[] = {
0xE00, 0xFFFFFFFF, 0x0A0C0C0C,
0xE04, 0xFFFFFFFF, 0x02040608,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x0A0C0D0E,
0xE14, 0xFFFFFFFF, 0x02040608,
0xE18, 0xFFFFFFFF, 0x0A0C0D0E,
0xE1C, 0xFFFFFFFF, 0x02040608,
0x830, 0xFFFFFFFF, 0x0A0C0C0C,
0x834, 0xFFFFFFFF, 0x02040608,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x0A0C0D0E,
0x848, 0xFFFFFFFF, 0x02040608,
0x84C, 0xFFFFFFFF, 0x0A0C0D0E,
0x868, 0xFFFFFFFF, 0x02040608,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x04040404,
0xE04, 0xFFFFFFFF, 0x00020204,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x06060606,
0xE14, 0xFFFFFFFF, 0x00020406,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0x830, 0xFFFFFFFF, 0x04040404,
0x834, 0xFFFFFFFF, 0x00020204,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x06060606,
0x848, 0xFFFFFFFF, 0x00020406,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 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,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 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,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x04040404,
0xE04, 0xFFFFFFFF, 0x00020204,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0x830, 0xFFFFFFFF, 0x04040404,
0x834, 0xFFFFFFFF, 0x00020204,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 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,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 0xFFFFFFFF, 0x00000000,
};
void ODM_ReadAndConfig_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_PHY_REG_PG_8723A)/sizeof(u32);
u32 *Array = Array_PHY_REG_PG_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 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_8723A(pDM_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,188 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "odm_precomp.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_8723A[] = {
0x420, 0x00000080,
0x423, 0x00000000,
0x430, 0x00000000,
0x431, 0x00000000,
0x432, 0x00000000,
0x433, 0x00000001,
0x434, 0x00000004,
0x435, 0x00000005,
0x436, 0x00000006,
0x437, 0x00000007,
0x438, 0x00000000,
0x439, 0x00000000,
0x43A, 0x00000000,
0x43B, 0x00000001,
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,
0x462, 0x00000008,
0x463, 0x00000003,
0x4C8, 0x000000FF,
0x4C9, 0x00000008,
0x4CC, 0x000000FF,
0x4CD, 0x000000FF,
0x4CE, 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,
0x515, 0x00000010,
0x516, 0x0000000A,
0x517, 0x00000010,
0x51A, 0x00000016,
0x524, 0x0000000F,
0x525, 0x0000004F,
0x546, 0x00000040,
0x547, 0x00000000,
0x550, 0x00000010,
0x551, 0x00000010,
0x559, 0x00000002,
0x55A, 0x00000002,
0x55D, 0x000000FF,
0x605, 0x00000030,
0x608, 0x0000000E,
0x609, 0x0000002A,
0x652, 0x00000020,
0x63C, 0x0000000A,
0x63D, 0x0000000A,
0x63E, 0x0000000E,
0x63F, 0x0000000E,
0x66E, 0x00000005,
0x700, 0x00000021,
0x701, 0x00000043,
0x702, 0x00000065,
0x703, 0x00000087,
0x708, 0x00000021,
0x709, 0x00000043,
0x70A, 0x00000065,
0x70B, 0x00000087,
};
void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *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 = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_MAC_REG_8723A)/sizeof(u32);
u32 *Array = Array_MAC_REG_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
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) {
odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2);
continue;
} else {
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) {
odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}

View File

@ -0,0 +1,259 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "odm_precomp.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_8723A[] = {
0x000, 0x00030159,
0x001, 0x00031284,
0x002, 0x00098000,
0xFF0F011F, 0xABCD,
0x003, 0x00018C63,
0xCDCDCDCD, 0xCDCD,
0x003, 0x00039C63,
0xFF0F011F, 0xDEAD,
0x004, 0x000210E7,
0x009, 0x0002044F,
0x00A, 0x0001A3F1,
0x00B, 0x00014787,
0x00C, 0x000896FE,
0x00D, 0x0000E02C,
0x00E, 0x00039CE7,
0x00F, 0x00000451,
0x019, 0x00000000,
0x01A, 0x00030355,
0x01B, 0x00060A00,
0x01C, 0x000FC378,
0x01D, 0x000A1250,
0x01E, 0x0000024F,
0x01F, 0x00000000,
0x020, 0x0000B614,
0x021, 0x0006C000,
0x022, 0x00000000,
0x023, 0x00001558,
0x024, 0x00000060,
0x025, 0x00000483,
0x026, 0x0004F000,
0x027, 0x000EC7D9,
0x028, 0x00057730,
0x029, 0x00004783,
0x02A, 0x00000001,
0x02B, 0x00021334,
0x02A, 0x00000000,
0x02B, 0x00000054,
0x02A, 0x00000001,
0x02B, 0x00000808,
0x02B, 0x00053333,
0x02C, 0x0000000C,
0x02A, 0x00000002,
0x02B, 0x00000808,
0x02B, 0x0005B333,
0x02C, 0x0000000D,
0x02A, 0x00000003,
0x02B, 0x00000808,
0x02B, 0x00063333,
0x02C, 0x0000000D,
0x02A, 0x00000004,
0x02B, 0x00000808,
0x02B, 0x0006B333,
0x02C, 0x0000000D,
0x02A, 0x00000005,
0x02B, 0x00000808,
0x02B, 0x00073333,
0x02C, 0x0000000D,
0x02A, 0x00000006,
0x02B, 0x00000709,
0x02B, 0x0005B333,
0x02C, 0x0000000D,
0x02A, 0x00000007,
0x02B, 0x00000709,
0x02B, 0x00063333,
0x02C, 0x0000000D,
0x02A, 0x00000008,
0x02B, 0x0000060A,
0x02B, 0x0004B333,
0x02C, 0x0000000D,
0x02A, 0x00000009,
0x02B, 0x0000060A,
0x02B, 0x00053333,
0x02C, 0x0000000D,
0x02A, 0x0000000A,
0x02B, 0x0000060A,
0x02B, 0x0005B333,
0x02C, 0x0000000D,
0x02A, 0x0000000B,
0x02B, 0x0000060A,
0x02B, 0x00063333,
0x02C, 0x0000000D,
0x02A, 0x0000000C,
0x02B, 0x0000060A,
0x02B, 0x0006B333,
0x02C, 0x0000000D,
0x02A, 0x0000000D,
0x02B, 0x0000060A,
0x02B, 0x00073333,
0x02C, 0x0000000D,
0x02A, 0x0000000E,
0x02B, 0x0000050B,
0x02B, 0x00066666,
0x02C, 0x0000001A,
0x02A, 0x000E0000,
0x010, 0x0004000F,
0x011, 0x000E31FC,
0x010, 0x0006000F,
0x011, 0x000FF9F8,
0x010, 0x0002000F,
0x011, 0x000203F9,
0x010, 0x0003000F,
0x011, 0x000FF500,
0x010, 0x00000000,
0x011, 0x00000000,
0x010, 0x0008000F,
0x011, 0x0003F100,
0x010, 0x0009000F,
0x011, 0x00023100,
0x012, 0x00032000,
0x012, 0x00071000,
0x012, 0x000B0000,
0x012, 0x000FC000,
0x013, 0x000287B3,
0x013, 0x000244B7,
0x013, 0x000204AB,
0x013, 0x0001C49F,
0x013, 0x00018493,
0x013, 0x0001429B,
0x013, 0x00010299,
0x013, 0x0000C29C,
0x013, 0x000081A0,
0x013, 0x000040AC,
0x013, 0x00000020,
0x014, 0x0001944C,
0x014, 0x00059444,
0x014, 0x0009944C,
0x014, 0x000D9444,
0xFF0F011F, 0xABCD,
0x015, 0x0000F424,
0x015, 0x0004F424,
0x015, 0x0008F424,
0x015, 0x000CF424,
0xCDCDCDCD, 0xCDCD,
0x015, 0x0000F474,
0x015, 0x0004F477,
0x015, 0x0008F455,
0x015, 0x000CF455,
0xFF0F011F, 0xDEAD,
0x016, 0x00000339,
0x016, 0x00040339,
0x016, 0x00080339,
0xFF0F011F, 0xABCD,
0x016, 0x000C0356,
0xCDCDCDCD, 0xCDCD,
0x016, 0x000C0366,
0xFF0F011F, 0xDEAD,
0x000, 0x00010159,
0x018, 0x0000F401,
0x0FE, 0x00000000,
0x0FE, 0x00000000,
0x01F, 0x00000003,
0x0FE, 0x00000000,
0x0FE, 0x00000000,
0x01E, 0x00000247,
0x01F, 0x00000000,
0x000, 0x00030159,
};
void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *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 = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_RadioA_1T_8723A)/sizeof(u32);
u32 *Array = Array_RadioA_1T_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
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) {
odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
continue;
} else {
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) {
odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}

View File

@ -0,0 +1,163 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/*++
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 deal with the Power Configuration CMDs parsing
for RTL8723/RTL8188E Series IC. */
/* */
/* Assumption: */
/* We should follow specific format which was released from
HW SD. */
/* */
/* 2011.07.07, added by Roger. */
/* */
u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
u8 FabVersion, u8 InterfaceType,
struct wlan_pwr_cfg PwrSeqCmd[])
{
struct wlan_pwr_cfg PwrCfgCmd = { 0 };
u8 bPollingBit = false;
u32 AryIdx = 0;
u8 value = 0;
u32 offset = 0;
u32 pollingCount = 0; /* polling autoload done. */
u32 maxPollingCnt = 5000;
do {
PwrCfgCmd = PwrSeqCmd[AryIdx];
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: 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) & FabVersion) &&
(GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
(GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) {
switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
case PWR_CMD_READ:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_READ\n"));
break;
case PWR_CMD_WRITE:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"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 sytem register */
rtw_write8(padapter, offset, value);
break;
case PWR_CMD_POLLING:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_POLLING\n"));
bPollingBit = 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)))
bPollingBit = true;
else
udelay(10);
if (pollingCount++ > maxPollingCnt) {
DBG_8723A("Fail to polling "
"Offset[%#x]\n",
offset);
return false;
}
} while (!bPollingBit);
break;
case PWR_CMD_DELAY:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_DELAY\n"));
if (GET_PWR_CFG_VALUE(PwrCfgCmd) ==
PWRSEQ_DELAY_US)
udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
else
udelay(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_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_END\n"));
return true;
break;
default:
RT_TRACE(_module_hal_init_c_, _drv_err_,
("HalPwrSeqCmdParsing23a: "
"Unknown CMD!!\n"));
break;
}
}
AryIdx++; /* Add Array Index */
} while (1);
return true;
}

View File

@ -0,0 +1,881 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include <osdep_service.h>
#include <drv_types.h>
#include <hal_intf.h>
#include <hal_com.h>
#include <rtl8723a_hal.h>
#define _HAL_INIT_C_
void dump_chip_info23a(struct hal_version ChipVersion)
{
int cnt = 0;
u8 buf[128];
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_");
cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ?
"Normal_Chip" : "Test_Chip");
cnt += sprintf((buf + cnt), "%s_",
IS_CHIP_VENDOR_TSMC(ChipVersion) ? "TSMC" : "UMC");
if (IS_A_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "A_CUT_");
else if (IS_B_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "B_CUT_");
else if (IS_C_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "C_CUT_");
else if (IS_D_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "D_CUT_");
else if (IS_E_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "E_CUT_");
else
cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_",
ChipVersion.CUTVersion);
if (IS_1T1R(ChipVersion))
cnt += sprintf((buf + cnt), "1T1R_");
else if (IS_1T2R(ChipVersion))
cnt += sprintf((buf + cnt), "1T2R_");
else if (IS_2T2R(ChipVersion))
cnt += sprintf((buf + cnt), "2T2R_");
else
cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_",
ChipVersion.RFType);
cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer);
DBG_8723A("%s", buf);
}
#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
/* return the final channel plan decision */
/* hw_channel_plan: channel plan from HW (efuse/eeprom) */
/* sw_channel_plan: channel plan from SW (registry/module param) */
/* def_channel_plan: channel plan used when the former two is invalid */
u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan,
u8 sw_channel_plan, u8 def_channel_plan,
bool AutoLoadFail)
{
u8 swConfig;
u8 chnlPlan;
swConfig = true;
if (!AutoLoadFail) {
if (!rtw_is_channel_plan_valid(sw_channel_plan))
swConfig = false;
if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
swConfig = false;
}
if (swConfig == true)
chnlPlan = sw_channel_plan;
else
chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
if (!rtw_is_channel_plan_valid(chnlPlan))
chnlPlan = def_channel_plan;
return chnlPlan;
}
u8 MRateToHwRate23a(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;
/* HT rates since here */
/* case MGN_MCS0: ret = DESC_RATEMCS0; break; */
/* case MGN_MCS1: ret = DESC_RATEMCS1; break; */
/* case MGN_MCS2: ret = DESC_RATEMCS2; break; */
/* case MGN_MCS3: ret = DESC_RATEMCS3; break; */
/* case MGN_MCS4: ret = DESC_RATEMCS4; break; */
/* case MGN_MCS5: ret = DESC_RATEMCS5; break; */
/* case MGN_MCS6: ret = DESC_RATEMCS6; break; */
/* case MGN_MCS7: ret = DESC_RATEMCS7; break; */
default:
break;
}
return ret;
}
void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u8 i, is_brate, brate;
u16 brate_cfg = 0;
u8 rate_index;
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
brate = mBratesOS[i] & 0x7f;
if (is_brate) {
switch (brate) {
case IEEE80211_CCK_RATE_1MB:
brate_cfg |= RATE_1M;
break;
case IEEE80211_CCK_RATE_2MB:
brate_cfg |= RATE_2M;
break;
case IEEE80211_CCK_RATE_5MB:
brate_cfg |= RATE_5_5M;
break;
case IEEE80211_CCK_RATE_11MB:
brate_cfg |= RATE_11M;
break;
case IEEE80211_OFDM_RATE_6MB:
brate_cfg |= RATE_6M;
break;
case IEEE80211_OFDM_RATE_9MB:
brate_cfg |= RATE_9M;
break;
case IEEE80211_OFDM_RATE_12MB:
brate_cfg |= RATE_12M;
break;
case IEEE80211_OFDM_RATE_18MB:
brate_cfg |= RATE_18M;
break;
case IEEE80211_OFDM_RATE_24MB:
brate_cfg |= RATE_24M;
break;
case IEEE80211_OFDM_RATE_36MB:
brate_cfg |= RATE_36M;
break;
case IEEE80211_OFDM_RATE_48MB:
brate_cfg |= RATE_48M;
break;
case IEEE80211_OFDM_RATE_54MB:
brate_cfg |= RATE_54M;
break;
}
}
}
/* 2007.01.16, by Emily */
/* Select RRSR (in Legacy-OFDM and CCK) */
/* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M,
and 1M from the Basic rate. */
/* We do not use other rates. */
/* 2011.03.30 add by Luke Lee */
/* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
/* because CCK 2M has poor TXEVM */
/* CCK 5.5M & 11M ACK should be enabled for better
performance */
brate_cfg = (brate_cfg | 0xd) & 0x15d;
pHalData->BasicRateSet = brate_cfg;
brate_cfg |= 0x01; /* default enable 1M ACK rate */
DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg);
/* Set RRSR rate table. */
rtw_write8(padapter, REG_RRSR, brate_cfg & 0xff);
rtw_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff);
rtw_write8(padapter, REG_RRSR + 2,
rtw_read8(padapter, REG_RRSR + 2) & 0xf0);
rate_index = 0;
/* Set RTS initial rate */
while (brate_cfg > 0x1) {
brate_cfg = (brate_cfg >> 1);
rate_index++;
}
/* Ziv - Check */
rtw_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
return;
}
static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
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 _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
if (bWIFICfg) { /* 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 _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
if (bWIFICfg) { /* 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_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
{
struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
bool result = true;
switch (NumOutPipe) {
case 2:
_TwoOutPipeMapping(pAdapter, bWIFICfg);
break;
case 3:
_ThreeOutPipeMapping(pAdapter, bWIFICfg);
break;
case 1:
_OneOutPipeMapping(pAdapter);
break;
default:
result = false;
break;
}
return result;
}
void hal_init_macaddr23a(struct rtw_adapter *adapter)
{
rtw_hal_set_hwreg23a(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_clear23a(struct rtw_adapter *adapter)
{
rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
}
s32 c2h_evt_read23a(struct rtw_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_read23a(): ",
&c2h_evt, sizeof(c2h_evt));
if (0) {
DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n",
__func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq,
trigger);
}
/* 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_read23a(): 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_clear23a(adapter);
exit:
return ret;
}
void
rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
{
u8 SecMinSpace;
if (MinSpacingToSet <= 7) {
switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
case _NO_PRIVACY_:
case _AES_:
SecMinSpace = 0;
break;
case _WEP40_:
case _WEP104_:
case _TKIP_:
case _TKIP_WTMIC_:
SecMinSpace = 6;
break;
default:
SecMinSpace = 7;
break;
}
if (MinSpacingToSet < SecMinSpace)
MinSpacingToSet = SecMinSpace;
/* RT_TRACE(COMP_MLME, DBG_LOUD,
("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
padapter->MgntInfo.MinSpaceCfg)); */
MinSpacingToSet |=
rtw_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
rtw_write8(padapter, REG_AMPDU_MIN_SPACE,
MinSpacingToSet);
}
}
void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
{
u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
u8 MaxAggNum;
u8 *pRegToSet;
u8 index = 0;
pRegToSet = RegToSet_Normal; /* 0xb972a841; */
#ifdef CONFIG_8723AU_BT_COEXIST
if ((BT_IsBtDisabled(padapter) == false) &&
(BT_1Ant(padapter) == true)) {
MaxAggNum = 0x8;
} else
#endif /* CONFIG_8723AU_BT_COEXIST */
{
MaxAggNum = 0xF;
}
if (FactorToSet <= 3) {
FactorToSet = (1 << (FactorToSet + 2));
if (FactorToSet > MaxAggNum)
FactorToSet = MaxAggNum;
for (index = 0; index < 4; index++) {
if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
pRegToSet[index] = (pRegToSet[index] & 0x0f) |
(FactorToSet << 4);
if ((pRegToSet[index] & 0x0f) > FactorToSet)
pRegToSet[index] = (pRegToSet[index] & 0xf0) |
FactorToSet;
rtw_write8(padapter, REG_AGGLEN_LMT + index,
pRegToSet[index]);
}
/* RT_TRACE(COMP_MLME, DBG_LOUD,
("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); */
}
}
void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl)
{
u8 hwctrl = 0;
if (ctrl != 0) {
hwctrl |= AcmHw_HwEn;
if (ctrl & BIT(1)) /* BE */
hwctrl |= AcmHw_BeqEn;
if (ctrl & BIT(2)) /* VI */
hwctrl |= AcmHw_ViqEn;
if (ctrl & BIT(3)) /* VO */
hwctrl |= AcmHw_VoqEn;
}
DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl);
rtw_write8(padapter, REG_ACMHWCTRL, hwctrl);
}
void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
{
u8 val8;
val8 = rtw_read8(padapter, MSR) & 0x0c;
val8 |= status;
rtw_write8(padapter, MSR, val8);
}
void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
{
u8 val8;
val8 = rtw_read8(padapter, MSR) & 0x03;
val8 |= status << 2;
rtw_write8(padapter, MSR, val8);
}
void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val)
{
if (val)
SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0);
else
SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT);
}
void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
{
u32 val32;
val32 = rtw_read32(padapter, REG_RCR);
if (val)
val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
else
val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtw_write32(padapter, REG_RCR, val32);
}
void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag)
{
if (flag) { /* under sitesurvey */
u32 v32;
/* config RCR to receive different BSSID & not
to receive data frame */
v32 = rtw_read32(padapter, REG_RCR);
v32 &= ~(RCR_CBSSID_BCN);
rtw_write32(padapter, REG_RCR, v32);
/* reject all data frame */
rtw_write16(padapter, REG_RXFLTMAP2, 0);
/* disable update TSF */
SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
} else { /* sitesurvey done */
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo;
u32 v32;
pmlmeinfo = &pmlmeext->mlmext_info;
if ((is_client_associated_to_ap23a(padapter) == true) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
/* enable to rx data frame */
rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
/* enable update TSF */
SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
}
v32 = rtw_read32(padapter, REG_RCR);
v32 |= RCR_CBSSID_BCN;
rtw_write32(padapter, REG_RCR, v32);
}
#ifdef CONFIG_8723AU_BT_COEXIST
BT_WifiScanNotify(padapter, flag ? true : false);
#endif
}
void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
{
rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) | RCR_AM);
DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
rtw_read32(padapter, REG_RCR));
}
void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
{
rtw_write32(padapter, REG_RCR,
rtw_read32(padapter, REG_RCR) & (~RCR_AM));
DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
rtw_read32(padapter, REG_RCR));
}
void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime)
{
u8 u1bAIFS, aSifsTime;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
rtw_write8(padapter, REG_SLOT, slottime);
if (pmlmeinfo->WMM_enable == 0) {
if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
aSifsTime = 10;
else
aSifsTime = 16;
u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
/* <Roger_EXP> Temporary removed, 2008.06.20. */
rtw_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS);
rtw_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS);
rtw_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS);
rtw_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS);
}
}
void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u8 regTmp;
/* Joseph marked out for Netgear 3500 TKIP
channel 7 issue.(Temporarily) */
regTmp = (pHalData->nCur40MhzPrimeSC) << 5;
/* regTmp = 0; */
if (bShortPreamble)
regTmp |= 0x80;
rtw_write8(padapter, REG_RRSR + 2, regTmp);
}
void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
{
rtw_write8(padapter, REG_SECCFG, sec);
}
void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
{
u8 i;
u32 ulCommand = 0;
u32 ulContent = 0;
u32 ulEncAlgo = CAM_AES;
for (i = 0; i < CAM_CONTENT_COUNT; i++) {
/* filled id in CAM config 2 byte */
if (i == 0) {
ulContent |= (ucIndex & 0x03) |
((u16) (ulEncAlgo) << 2);
/* ulContent |= CAM_VALID; */
} else {
ulContent = 0;
}
/* polling bit, and No Write enable, and address */
ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
/* write content 0 is equall to mark invalid */
/* delay_ms(40); */
rtw_write32(padapter, WCAMI, ulContent);
/* RT_TRACE(COMP_SEC, DBG_LOUD,
("CAM_empty_entry23a(): WRITE A4: %lx \n", ulContent));*/
/* delay_ms(40); */
rtw_write32(padapter, RWCAM, ulCommand);
/* RT_TRACE(COMP_SEC, DBG_LOUD,
("CAM_empty_entry23a(): WRITE A0: %lx \n", ulCommand));*/
}
}
void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter)
{
rtw_write32(padapter, RWCAM, BIT(31) | BIT(30));
}
void rtl8723a_cam_write(struct rtw_adapter *padapter, u32 val1, u32 val2)
{
u32 cmd;
rtw_write32(padapter, WCAMI, val1);
cmd = CAM_POLLINIG | CAM_WRITE | val2;
rtw_write32(padapter, RWCAM, cmd);
}
void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
{
#define RW_RELEASE_EN BIT(18)
#define RXDMA_IDLE BIT(17)
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
u8 trycnt = 100;
/* pause tx */
rtw_write8(padapter, REG_TXPAUSE, 0xff);
/* keep sn */
padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ);
if (pwrpriv->bkeepfwalive != true) {
u32 v32;
/* RX DMA stop */
v32 = rtw_read32(padapter, REG_RXPKT_NUM);
v32 |= RW_RELEASE_EN;
rtw_write32(padapter, REG_RXPKT_NUM, v32);
do {
v32 = rtw_read32(padapter, REG_RXPKT_NUM) & RXDMA_IDLE;
if (!v32)
break;
} while (trycnt--);
if (trycnt == 0) {
DBG_8723A("Stop RX DMA failed......\n");
}
/* RQPN Load 0 */
rtw_write16(padapter, REG_RQPN_NPQ, 0);
rtw_write32(padapter, REG_RQPN, 0x80000000);
mdelay(10);
}
}
void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->bMacPwrCtrlOn = val;
DBG_8723A("%s: bMacPwrCtrlOn =%d\n", __func__, pHalData->bMacPwrCtrlOn);
}
void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
{
/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
write 1 to clear, Clear by sw */
rtw_write8(padapter, REG_TDECTRL + 2,
rtw_read8(padapter, REG_TDECTRL + 2) | BIT0);
}
void rtl8723a_set_tx_pause(struct rtw_adapter *padapter, u8 pause)
{
rtw_write8(padapter, REG_TXPAUSE, pause);
}
void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
{
rtw_write16(padapter, REG_BCN_INTERVAL, interval);
}
void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2)
{
/* SIFS_Timer = 0x0a0a0808; */
/* RESP_SIFS for CCK */
/* SIFS_T2T_CCK (0x08) */
rtw_write8(padapter, REG_R2T_SIFS, r2t1);
/* SIFS_R2T_CCK(0x08) */
rtw_write8(padapter, REG_R2T_SIFS + 1, r2t2);
/* RESP_SIFS for OFDM */
/* SIFS_T2T_OFDM (0x0a) */
rtw_write8(padapter, REG_T2T_SIFS, t2t1);
/* SIFS_R2T_OFDM(0x0a) */
rtw_write8(padapter, REG_T2T_SIFS + 1, t2t2);
}
void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
{
rtw_write32(padapter, REG_EDCA_VO_PARAM, vo);
}
void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
{
rtw_write32(padapter, REG_EDCA_VI_PARAM, vi);
}
void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->AcParam_BE = be;
rtw_write32(padapter, REG_EDCA_BE_PARAM, be);
}
void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
{
rtw_write32(padapter, REG_EDCA_BK_PARAM, bk);
}
void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
{
rtw_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
}
void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper)
{
if (usNavUpper > HAL_8723A_NAV_UPPER_UNIT * 0xFF) {
RT_TRACE(_module_hal_init_c_, _drv_notice_,
("The setting value (0x%08X us) of NAV_UPPER "
"is larger than (%d * 0xFF)!!!\n",
usNavUpper, HAL_8723A_NAV_UPPER_UNIT));
return;
}
/* The value of ((usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
HAL_8723A_NAV_UPPER_UNIT) */
/* is getting the upper integer. */
usNavUpper = (usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
HAL_8723A_NAV_UPPER_UNIT;
rtw_write8(padapter, REG_NAV_UPPER, (u8) usNavUpper);
}
void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
if (rx_gain == 0xff) /* restore rx gain */
ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue);
else {
pDigTable->BackupIGValue = pDigTable->CurIGValue;
ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain);
}
}
void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->odmpriv.SupportAbility = val;
}
void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter, u8 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (val) /* save dm flag */
pHalData->odmpriv.BK_SupportAbility =
pHalData->odmpriv.SupportAbility;
else /* restore dm flag */
pHalData->odmpriv.SupportAbility =
pHalData->odmpriv.BK_SupportAbility;
}
void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (val == DYNAMIC_ALL_FUNC_ENABLE) {
pHalData->dmpriv.DMFlag = pHalData->dmpriv.InitDMFlag;
pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
} else {
pHalData->odmpriv.SupportAbility |= val;
}
}
void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->odmpriv.SupportAbility &= val;
}
void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
{
rtw_write8(padapter, REG_USB_HRPWM, val);
}

View File

@ -0,0 +1,418 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _HAL_INTF_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <hal_intf.h>
#include <usb_hal.h>
void rtw_hal_chip_configure23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.intf_chip_configure)
padapter->HalFunc.intf_chip_configure(padapter);
}
void rtw_hal_read_chip_info23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.read_adapter_info)
padapter->HalFunc.read_adapter_info(padapter);
}
void rtw_hal_read_chip_version23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.read_chip_version)
padapter->HalFunc.read_chip_version(padapter);
}
void rtw_hal_def_value_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.init_default_value)
padapter->HalFunc.init_default_value(padapter);
}
void rtw_hal_free_data23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.free_hal_data)
padapter->HalFunc.free_hal_data(padapter);
}
void rtw_hal_dm_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.dm_init)
padapter->HalFunc.dm_init(padapter);
}
void rtw_hal_dm_deinit23a(struct rtw_adapter *padapter)
{
/* cancel dm timer */
if (padapter->HalFunc.dm_deinit)
padapter->HalFunc.dm_deinit(padapter);
}
void rtw_hal_sw_led_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.InitSwLeds)
padapter->HalFunc.InitSwLeds(padapter);
}
void rtw_hal_sw_led_deinit23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.DeInitSwLeds)
padapter->HalFunc.DeInitSwLeds(padapter);
}
u32 rtw_hal_power_on23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.hal_power_on)
return padapter->HalFunc.hal_power_on(padapter);
return _FAIL;
}
uint rtw_hal_init23a(struct rtw_adapter *padapter)
{
uint status = _SUCCESS;
padapter->hw_init_completed = false;
status = padapter->HalFunc.hal_init(padapter);
if (status == _SUCCESS) {
padapter->hw_init_completed = true;
if (padapter->registrypriv.notch_filter == 1)
rtw_hal_notch_filter23a(padapter, 1);
rtw_hal_reset_security_engine23a(padapter);
} else {
padapter->hw_init_completed = false;
DBG_8723A("rtw_hal_init23a: 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_deinit23a(struct rtw_adapter *padapter)
{
uint status = _SUCCESS;
status = padapter->HalFunc.hal_deinit(padapter);
if (status == _SUCCESS)
padapter->hw_init_completed = false;
else
DBG_8723A("\n rtw_hal_deinit23a: hal_init fail\n");
return status;
}
void rtw_hal_set_hwreg23a(struct rtw_adapter *padapter, u8 variable, u8 *val)
{
if (padapter->HalFunc.SetHwRegHandler)
padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
}
void rtw23a_hal_get_hwreg(struct rtw_adapter *padapter, u8 variable, u8 *val)
{
if (padapter->HalFunc.GetHwRegHandler)
padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
}
u8 rtw_hal_set_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
if (padapter->HalFunc.SetHalDefVarHandler)
return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue);
return _FAIL;
}
u8 rtw_hal_get_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
if (padapter->HalFunc.GetHalDefVarHandler)
return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue);
return _FAIL;
}
void rtw_hal_set_odm_var23a(struct rtw_adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
{
if (padapter->HalFunc.SetHalODMVarHandler)
padapter->HalFunc.SetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
}
void rtw_hal_get_odm_var23a(struct rtw_adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
{
if (padapter->HalFunc.GetHalODMVarHandler)
padapter->HalFunc.GetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
}
void rtw_hal_enable_interrupt23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.enable_interrupt)
padapter->HalFunc.enable_interrupt(padapter);
else
DBG_8723A("%s: HalFunc.enable_interrupt is NULL!\n", __FUNCTION__);
}
void rtw_hal_disable_interrupt23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.disable_interrupt)
padapter->HalFunc.disable_interrupt(padapter);
else
DBG_8723A("%s: HalFunc.disable_interrupt is NULL!\n", __FUNCTION__);
}
u32 rtw_hal_inirp_init23a(struct rtw_adapter *padapter)
{
u32 rst = _FAIL;
if (padapter->HalFunc.inirp_init)
rst = padapter->HalFunc.inirp_init(padapter);
else
DBG_8723A(" %s HalFunc.inirp_init is NULL!!!\n", __FUNCTION__);
return rst;
}
u32 rtw_hal_inirp_deinit23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.inirp_deinit)
return padapter->HalFunc.inirp_deinit(padapter);
return _FAIL;
}
u8 rtw_hal_intf_ps_func23a(struct rtw_adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
{
if (padapter->HalFunc.interface_ps_func)
return padapter->HalFunc.interface_ps_func(padapter, efunc_id, val);
return _FAIL;
}
s32 rtw_hal_xmit23aframe_enqueue(struct rtw_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_xmit23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
if (padapter->HalFunc.hal_xmit)
return padapter->HalFunc.hal_xmit(padapter, pxmitframe);
return false;
}
s32 rtw_hal_mgnt_xmit23a(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe)
{
s32 ret = _FAIL;
if (padapter->HalFunc.mgnt_xmit)
ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
return ret;
}
s32 rtw_hal_init23a_xmit_priv(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.init_xmit_priv != NULL)
return padapter->HalFunc.init_xmit_priv(padapter);
return _FAIL;
}
void rtw_hal_free_xmit_priv23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.free_xmit_priv != NULL)
padapter->HalFunc.free_xmit_priv(padapter);
}
s32 rtw_hal_init23a_recv_priv(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.init_recv_priv)
return padapter->HalFunc.init_recv_priv(padapter);
return _FAIL;
}
void rtw_hal_free_recv_priv23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.free_recv_priv)
padapter->HalFunc.free_recv_priv(padapter);
}
void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level)
{
struct rtw_adapter *padapter;
struct mlme_priv *pmlmepriv;
if (!psta)
return;
padapter = psta->padapter;
pmlmepriv = &padapter->mlmepriv;
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
add_RATid23a(padapter, psta, rssi_level);
} else {
if (padapter->HalFunc.UpdateRAMaskHandler)
padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level);
}
}
void rtw_hal_add_ra_tid23a(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level)
{
if (padapter->HalFunc.Add_RateATid)
padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level);
}
/* Start specifical interface thread */
void rtw_hal_start_thread23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.run_thread)
padapter->HalFunc.run_thread(padapter);
}
/* Start specifical interface thread */
void rtw_hal_stop_thread23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.cancel_thread)
padapter->HalFunc.cancel_thread(padapter);
}
u32 rtw_hal_read_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask)
{
u32 data = 0;
if (padapter->HalFunc.read_bbreg)
data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask);
return data;
}
void rtw_hal_write_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data)
{
if (padapter->HalFunc.write_bbreg)
padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data);
}
u32 rtw_hal_read_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask)
{
u32 data = 0;
if (padapter->HalFunc.read_rfreg)
data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask);
return data;
}
void rtw_hal_write_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
{
if (padapter->HalFunc.write_rfreg)
padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
}
s32 rtw_hal_interrupt_handler23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.interrupt_handler)
return padapter->HalFunc.interrupt_handler(padapter);
return _FAIL;
}
void rtw_hal_set_bwmode23a(struct rtw_adapter *padapter,
enum ht_channel_width Bandwidth, u8 offset)
{
if (padapter->HalFunc.set_bwmode_handler)
padapter->HalFunc.set_bwmode_handler(padapter, Bandwidth,
offset);
}
void rtw_hal_set_chan23a(struct rtw_adapter *padapter, u8 channel)
{
if (padapter->HalFunc.set_channel_handler)
padapter->HalFunc.set_channel_handler(padapter, channel);
}
void rtw_hal_dm_watchdog23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.hal_dm_watchdog)
padapter->HalFunc.hal_dm_watchdog(padapter);
}
void rtw_hal_bcn_related_reg_setting23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.SetBeaconRelatedRegistersHandler)
padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter);
}
void rtw_hal_sreset_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_init_value23a)
padapter->HalFunc.sreset_init_value23a(padapter);
}
void rtw_hal_sreset_reset23a(struct rtw_adapter *padapter)
{
padapter = GET_PRIMARY_ADAPTER(padapter);
if (padapter->HalFunc.silentreset)
padapter->HalFunc.silentreset(padapter);
}
void rtw_hal_sreset_reset23a_value23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_reset_value23a)
padapter->HalFunc.sreset_reset_value23a(padapter);
}
void rtw_hal_sreset_xmit_status_check23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_xmit_status_check)
padapter->HalFunc.sreset_xmit_status_check(padapter);
}
void rtw_hal_sreset_linked_status_check23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_linked_status_check)
padapter->HalFunc.sreset_linked_status_check(padapter);
}
u8 rtw_hal_sreset_get_wifi_status23a(struct rtw_adapter *padapter)
{
u8 status = 0;
if (padapter->HalFunc.sreset_get_wifi_status23a)
status = padapter->HalFunc.sreset_get_wifi_status23a(padapter);
return status;
}
bool rtw_hal_sreset_inprogress(struct rtw_adapter *padapter)
{
bool inprogress = false;
padapter = GET_PRIMARY_ADAPTER(padapter);
if (padapter->HalFunc.sreset_inprogress)
inprogress = padapter->HalFunc.sreset_inprogress(padapter);
return inprogress;
}
void rtw_hal_notch_filter23a(struct rtw_adapter *adapter, bool enable)
{
if (adapter->HalFunc.hal_notch_filter)
adapter->HalFunc.hal_notch_filter(adapter, enable);
}
void rtw_hal_reset_security_engine23a(struct rtw_adapter *adapter)
{
if (adapter->HalFunc.hal_reset_security_engine)
adapter->HalFunc.hal_reset_security_engine(adapter);
}
s32 rtw_hal_c2h_handler23a(struct rtw_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_ccx23a(struct rtw_adapter *adapter)
{
return adapter->HalFunc.c2h_id_filter_ccx;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,481 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/* */
/* 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(pDM_Odm))
#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(pDM_Odm))
static u8 odm_QueryRxPwrPercentage(s8 AntPower)
{
if ((AntPower <= -100) || (AntPower >= 20))
return 0;
else if (AntPower >= 0)
return 100;
else
return 100 + AntPower;
}
static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSig)
{
s32 RetSig = 0;
if ((pDM_Odm->SupportInterface == ODM_ITRF_USB) || (pDM_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 dm_odm_t *pDM_Odm, s32 CurrSig)
{
return odm_SignalScaleMapping_92CSeries(pDM_Odm, CurrSig);
}
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 dm_odm_t *pDM_Odm,
struct odm_phy_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_packet_info *pPktinfo)
{
struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
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;
isCCKrate = (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;
pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++;
/* (1)Hardware does not provide RSSI for CCK */
/* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
cck_highpwr = pDM_Odm->bCckHighPower;
cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ;
/* The RSSI formula should be modified according to the gain table */
if (!cck_highpwr) {
report = (cck_agc_rpt & 0xc0)>>6;
switch (report) {
/* 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 (pDM_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;
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 */
pDM_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 (pDM_Odm->RFPathRxEnable & BIT(i))
rf_rx_num++;
rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110;
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 (pDM_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] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
}
/* (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;
/* (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(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */
} else {
if (rf_rx_num != 0)
pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num));
}
}
void odm_Init_RSSIForDM23a(struct dm_odm_t *pDM_Odm)
{
}
static void odm_Process_RSSIForDM(struct dm_odm_t *pDM_Odm,
struct odm_phy_info *pPhyInfo,
struct odm_packet_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 = pDM_Odm->pODM_StaInfo[pPktinfo->StationID];
if (!IS_STA_VALID(pEntry))
return;
if ((!pPktinfo->bPacketMatchBSSID))
return;
isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false;
/* 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_PhyStatusQuery23a_92CSeries(struct dm_odm_t *pDM_Odm,
struct odm_phy_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_packet_info *pPktinfo)
{
odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo,
pPhyStatus, pPktinfo);
if (pDM_Odm->RSSI_test) {
/* Select the packets to do RSSI checking for antenna switching. */
if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon)
ODM_SwAntDivChkPerPktRssi(pDM_Odm, pPktinfo->StationID, pPhyInfo);
} else {
odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo);
}
}
void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct odm_phy_info *pPhyInfo,
u8 *pPhyStatus, struct odm_packet_info *pPktinfo)
{
ODM_PhyStatusQuery23a_92CSeries(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo);
}
/* For future use. */
void ODM_MacStatusQuery23a(struct dm_odm_t *pDM_Odm, u8 *pMacStatus, u8 MacID,
bool bPacketMatchBSSID, bool bPacketToSelf,
bool bPacketBeacon)
{
/* 2011/10/19 Driver team will handle in the future. */
}
enum hal_status
ODM_ConfigRFWithHeaderFile23a(
struct dm_odm_t *pDM_Odm,
enum RF_RADIO_PATH Content,
enum RF_RADIO_PATH eRFPath
)
{
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===>ODM_ConfigRFWithHeaderFile23a\n"));
if (pDM_Odm->SupportICType == ODM_RTL8723A) {
if (eRFPath == RF_PATH_A)
READ_AND_CONFIG_MP(8723A, _RadioA_1T_);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> ODM_ConfigRFWithHeaderFile23a() Radio_A:Rtl8723RadioA_1TArray\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> ODM_ConfigRFWithHeaderFile23a() Radio_B:Rtl8723RadioB_1TArray\n"));
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE,
("ODM_ConfigRFWithHeaderFile23a: Radio No %x\n", eRFPath));
return HAL_STATUS_SUCCESS;
}
enum hal_status
ODM_ConfigBBWithHeaderFile23a(
struct dm_odm_t *pDM_Odm,
enum odm_bb_config_type ConfigType
)
{
if (pDM_Odm->SupportICType == ODM_RTL8723A) {
if (ConfigType == CONFIG_BB_PHY_REG)
READ_AND_CONFIG_MP(8723A, _PHY_REG_1T_);
else if (ConfigType == CONFIG_BB_AGC_TAB)
READ_AND_CONFIG_MP(8723A, _AGC_TAB_1T_);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> phy_ConfigBBWithHeaderFile() phy:Rtl8723AGCTAB_1TArray\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> phy_ConfigBBWithHeaderFile() agc:Rtl8723PHY_REG_1TArray\n"));
}
return HAL_STATUS_SUCCESS;
}
enum hal_status
ODM_ConfigMACWithHeaderFile23a(
struct dm_odm_t *pDM_Odm
)
{
u8 result = HAL_STATUS_SUCCESS;
if (pDM_Odm->SupportICType == ODM_RTL8723A)
READ_AND_CONFIG_MP(8723A, _MAC_REG_);
return result;
}

View File

@ -0,0 +1,162 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "odm_precomp.h"
void
odm_ConfigRFReg_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data,
enum RF_RADIO_PATH RF_PATH,
u32 RegAddr
)
{
if (Addr == 0xfe) {
msleep(50);
} else if (Addr == 0xfd) {
mdelay(5);
} else if (Addr == 0xfc) {
mdelay(1);
} else if (Addr == 0xfb) {
udelay(50);
} else if (Addr == 0xfa) {
udelay(5);
} else if (Addr == 0xf9) {
udelay(1);
} else {
ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
/* Add 1us delay between BB/RF register setting. */
udelay(1);
}
}
void odm_ConfigRF_RadioA_8723A(struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data
)
{
u32 content = 0x1000; /* RF_Content: radioa_txt */
u32 maskforPhySet = (u32)(content&0xE000);
odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_A,
Addr|maskforPhySet);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigRFWithHeaderFile23a: [RadioA] %08X %08X\n",
Addr, Data));
}
void odm_ConfigRF_RadioB_8723A(struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data
)
{
u32 content = 0x1001; /* RF_Content: radiob_txt */
u32 maskforPhySet = (u32)(content&0xE000);
odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_B,
Addr|maskforPhySet);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigRFWithHeaderFile23a: [RadioB] %08X %08X\n",
Addr, Data));
}
void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm,
u32 Addr,
u8 Data
)
{
ODM_Write1Byte(pDM_Odm, Addr, Data);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigMACWithHeaderFile23a: [MAC_REG] %08X %08X\n",
Addr, Data));
}
void
odm_ConfigBB_AGC_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Bitmask,
u32 Data
)
{
ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
/* Add 1us delay between BB/RF register setting. */
udelay(1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigBBWithHeaderFile23a: [AGC_TAB] %08X %08X\n",
Addr, Data));
}
void
odm_ConfigBB_PHY_REG_PG_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Bitmask,
u32 Data
)
{
if (Addr == 0xfe)
msleep(50);
else if (Addr == 0xfd)
mdelay(5);
else if (Addr == 0xfc)
mdelay(1);
else if (Addr == 0xfb)
udelay(50);
else if (Addr == 0xfa)
udelay(5);
else if (Addr == 0xf9)
udelay(1);
/* TODO: ODM_StorePwrIndexDiffRateOffset(...) */
/* storePwrIndexDiffRateOffset(Adapter, Addr, Bitmask, Data); */
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X %08X\n",
Addr, Bitmask, Data));
}
void
odm_ConfigBB_PHY_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Bitmask,
u32 Data
)
{
if (Addr == 0xfe)
msleep(50);
else if (Addr == 0xfd)
mdelay(5);
else if (Addr == 0xfc)
mdelay(1);
else if (Addr == 0xfb)
udelay(50);
else if (Addr == 0xfa)
udelay(5);
else if (Addr == 0xf9)
udelay(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. */
udelay(1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X\n",
Addr, Data));
}

View File

@ -0,0 +1,24 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "odm_precomp.h"
void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm)
{
pDM_Odm->DebugLevel = ODM_DBG_TRACE;
pDM_Odm->DebugComponents = 0;
}
u32 GlobalDebugLevel23A;

View File

@ -0,0 +1,236 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/* */
/* include files */
/* */
#include "odm_precomp.h"
/* */
/* ODM IO Relative API. */
/* */
u8 ODM_Read1Byte(struct dm_odm_t *pDM_Odm,
u32 RegAddr
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return rtw_read8(Adapter, RegAddr);
}
u16 ODM_Read2Byte(struct dm_odm_t *pDM_Odm,
u32 RegAddr
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return rtw_read16(Adapter, RegAddr);
}
u32 ODM_Read4Byte(struct dm_odm_t *pDM_Odm,
u32 RegAddr
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return rtw_read32(Adapter, RegAddr);
}
void ODM_Write1Byte(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u8 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
rtw_write8(Adapter, RegAddr, Data);
}
void ODM_Write2Byte(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u16 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
rtw_write16(Adapter, RegAddr, Data);
}
void ODM_Write4Byte(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
rtw_write32(Adapter, RegAddr, Data);
}
void ODM_SetMACReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
}
u32 ODM_GetMACReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
}
void ODM_SetBBReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
}
u32 ODM_GetBBReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
}
void ODM_SetRFReg(
struct dm_odm_t *pDM_Odm,
enum RF_RADIO_PATH eRFPath,
u32 RegAddr,
u32 BitMask,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
PHY_SetRFReg(Adapter, eRFPath, RegAddr, BitMask, Data);
}
u32 ODM_GetRFReg(
struct dm_odm_t *pDM_Odm,
enum RF_RADIO_PATH eRFPath,
u32 RegAddr,
u32 BitMask
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryRFReg(Adapter, eRFPath, RegAddr, BitMask);
}
/* */
/* ODM Memory relative API. */
/* */
void ODM_AllocateMemory(
struct dm_odm_t *pDM_Odm,
void **pPtr,
u32 length
)
{
*pPtr = rtw_zvmalloc(length);
}
/* length could be ignored, used to detect memory leakage. */
void ODM_FreeMemory(
struct dm_odm_t *pDM_Odm,
void *pPtr,
u32 length
)
{
rtw_vmfree(pPtr, length);
}
/* */
/* ODM MISC relative API. */
/* */
void
ODM_AcquireSpinLock(
struct dm_odm_t *pDM_Odm,
enum rt_spinlock_type type
)
{
}
void ODM_ReleaseSpinLock(
struct dm_odm_t *pDM_Odm,
enum rt_spinlock_type type
)
{
}
/* */
/* Work item relative API. FOr MP driver only~! */
/* */
void ODM_InitializeWorkItem(
struct dm_odm_t *pDM_Odm,
void *pRtWorkItem,
RT_WORKITEM_CALL_BACK RtWorkItemCallback,
void *pContext,
const char *szID
)
{
}
/* */
/* ODM Timer relative API. */
/* */
void ODM_SetTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer, u32 msDelay)
{
mod_timer(pTimer, jiffies + msecs_to_jiffies(msDelay)); /* ms */
}
void ODM_ReleaseTimer(struct dm_odm_t *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;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,845 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _RTL8723A_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 <rtl8723a_hal.h>
#define RTL92C_MAX_H2C_BOX_NUMS 4
#define RTL92C_MAX_CMD_LEN 5
#define MESSAGE_BOX_SIZE 4
#define EX_MESSAGE_BOX_SIZE 2
static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
{
u8 read_down = false;
int retry_cnts = 100;
u8 valid;
do {
valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
if (0 == valid)
read_down = true;
} while ((!read_down) && (retry_cnts--));
return read_down;
}
/*****************************************
* H2C Msg format :
*| 31 - 8 |7 | 6 - 0 |
*| h2c_msg |Ext_bit |CMD_ID |
*
******************************************/
s32 FillH2CCmd(struct rtw_adapter *padapter, 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_8723a *pHalData = GET_HAL_DATA(padapter);
u32 h2c_cmd = 0;
u16 h2c_cmd_ex = 0;
s32 ret = _FAIL;
padapter = GET_PRIMARY_ADAPTER(padapter);
pHalData = GET_HAL_DATA(padapter);
mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
if (!pCmdBuffer)
goto exit;
if (CmdLen > RTL92C_MAX_CMD_LEN)
goto exit;
if (padapter->bSurpriseRemoved == true)
goto exit;
/* pay attention to if race condition happened in H2C cmd setting. */
do {
h2c_box_num = pHalData->LastHMEBoxNum;
if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
DBG_8723A(" fw read cmd failed...\n");
goto exit;
}
if (CmdLen <= 3) {
memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
} else {
memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE));
*(u8 *)(&h2c_cmd) |= BIT(7);
}
*(u8 *)(&h2c_cmd) |= ElementID;
if (h2c_cmd & BIT(7)) {
msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex);
rtw_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
}
msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE);
h2c_cmd = le32_to_cpu(h2c_cmd);
rtw_write32(padapter, msgbox_addr, h2c_cmd);
bcmd_down = true;
pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
} while ((!bcmd_down) && (retry_cnts--));
ret = _SUCCESS;
exit:
mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
return ret;
}
u8 rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
{
u8 res = _SUCCESS;
*((u32 *)param) = cpu_to_le32(*((u32 *)param));
FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
return res;
}
u8 rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
{
u8 buf[5];
u8 res = _SUCCESS;
memset(buf, 0, 5);
mask = cpu_to_le32(mask);
memcpy(buf, &mask, 4);
buf[4] = arg;
FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
return res;
}
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
/* arg[0:4] = macid */
/* arg[5] = Short GI */
void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
u8 macid = arg&0x1f;
u8 raid = (bitmap>>28) & 0x0f;
bitmap &= 0x0fffffff;
if (rssi_level != DM_RATR_STA_INIT)
bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
bitmap |= ((raid<<28)&0xf0000000);
if (pHalData->fw_ractrl == true) {
rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
} else {
u8 init_rate, shortGIrate = false;
init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
shortGIrate = (arg&BIT(5)) ? true:false;
if (shortGIrate == true)
init_rate |= BIT(6);
rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
}
}
void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
{
struct setpwrmode_parm H2CSetPwrMode;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __FUNCTION__,
Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode);
/* Forece leave RF low power mode for 1T1R to
prevent conficting setting in Fw power */
/* saving sequence. 2010.06.07. Added by tynli.
Suggested by SD3 yschang. */
if ((Mode != PS_MODE_ACTIVE) &&
(!IS_92C_SERIAL(pHalData->VersionID))) {
ODM_RF_Saving23a(&pHalData->odmpriv, true);
}
H2CSetPwrMode.Mode = Mode;
H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
H2CSetPwrMode.AwakeInterval = 1;
H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
}
static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
u32 rate_len, pktlen;
struct mlme_ext_priv *pmlmeext = &padapter->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};
/* DBG_8723A("%s\n", __FUNCTION__); */
pwlanhdr = (struct ieee80211_hdr *)pframe;
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
memcpy(pwlanhdr->addr3, get_my_bssid23a(cur_network), ETH_ALEN);
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
/* pmlmeext->mgnt_seq++; */
SetFrameSubType(pframe, WIFI_BEACON);
pframe += sizeof(struct ieee80211_hdr_3addr);
pktlen = sizeof (struct ieee80211_hdr_3addr);
/* timestamp will be inserted by hardware */
pframe += 8;
pktlen += 8;
/* beacon interval: 2 bytes */
memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
/* capability info: 2 bytes */
memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
/* DBG_8723A("ie len =%d\n", cur_network->IELength); */
pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ies);
memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fixed_ies), pktlen);
goto _ConstructBeacon;
}
/* below for ad-hoc mode */
/* SSID */
pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
cur_network->Ssid.ssid, &pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ?
8 : rate_len), cur_network->SupportedRates, &pktlen);
/* DS parameter set */
pframe = rtw_set_ie23a(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 = cur->Configuration.ATIMWindow; */
ATIMWindow = 0;
pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
}
/* todo: ERP IE */
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8)
pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
/* todo:HT for adhoc */
_ConstructBeacon:
if ((pktlen + TXDESC_SIZE) > 512) {
DBG_8723A("beacon frame too large\n");
return;
}
*pLength = pktlen;
/* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
}
static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
pwlanhdr = (struct ieee80211_hdr *)pframe;
/* Frame control. */
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
SetPwrMgt(fctrl);
SetFrameSubType(pframe, WIFI_PSPOLL);
/* AID. */
SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
/* BSSID. */
memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
/* TA. */
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
*pLength = 16;
}
static void ConstructNullFunctionData(
struct rtw_adapter *padapter,
u8 *pframe,
u32 *pLength,
u8 *StaAddr,
u8 bQoS,
u8 AC,
u8 bEosp,
u8 bForcePowerSave)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
u32 pktlen;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *cur_network = &pmlmepriv->cur_network;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
pwlanhdr = (struct ieee80211_hdr *)pframe;
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
if (bForcePowerSave)
SetPwrMgt(fctrl);
switch (cur_network->network.InfrastructureMode) {
case Ndis802_11Infrastructure:
SetToDs(fctrl);
memcpy(pwlanhdr->addr1,
get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&padapter->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_bssid23a(&pmlmeinfo->network), ETH_ALEN);
memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv),
ETH_ALEN);
break;
case Ndis802_11IBSS:
default:
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
memcpy(pwlanhdr->addr3,
get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
break;
}
SetSeqNum(pwlanhdr, 0);
if (bQoS == true) {
struct ieee80211_qos_hdr *pwlanqoshdr;
SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
SetPriority(&pwlanqoshdr->qos_ctrl, AC);
SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
pktlen = sizeof(struct ieee80211_qos_hdr);
} else {
SetFrameSubType(pframe, WIFI_DATA_NULL);
pktlen = sizeof(struct ieee80211_hdr_3addr);
}
*pLength = pktlen;
}
static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
u8 *mac, *bssid;
u32 pktlen;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
/* DBG_8723A("%s\n", __FUNCTION__); */
pwlanhdr = (struct ieee80211_hdr *)pframe;
mac = myid(&padapter->eeprompriv);
bssid = cur_network->MacAddress;
fctrl = &pwlanhdr->frame_control;
*(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 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 beacuse beacon is too large. */
void CheckFwRsvdPageContent23a(struct rtw_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 lengh. */
/* true: At the second time, we should send the first packet (default:beacon) */
/* to Hw again and set the lengh in descriptor to the real beacon lengh. */
/* 2009.10.15 by tynli. */
static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished)
{
struct hal_data_8723a *pHalData;
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, BTQosNullLength;
u8 *ReservedPagePacket;
u8 PageNum, PageNeed, TxDescLen;
u16 BufIndex;
u32 TotalPacketLen;
struct rsvdpage_loc RsvdPageLoc;
DBG_8723A("%s\n", __FUNCTION__);
ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
if (ReservedPagePacket == NULL) {
DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
return;
}
pHalData = GET_HAL_DATA(padapter);
pxmitpriv = &padapter->xmitpriv;
pmlmeext = &padapter->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
/* 3 (1) beacon */
BufIndex = TXDESC_OFFSET;
ConstructBeacon(padapter, &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;
pHalData->FwRsvdPageStartOffset = PageNum;
BufIndex += PageNeed*128;
/* 3 (2) ps-poll */
RsvdPageLoc.LocPsPoll = PageNum;
ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (3) null data */
RsvdPageLoc.LocNullData = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&NullDataLength,
get_my_bssid23a(&pmlmeinfo->network),
false, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (4) probe response */
RsvdPageLoc.LocProbeRsp = PageNum;
ConstructProbeRsp(
padapter,
&ReservedPagePacket[BufIndex],
&ProbeRspLength,
get_my_bssid23a(&pmlmeinfo->network),
false);
rtl8723a_fill_fake_txdesc(padapter, &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(
padapter,
&ReservedPagePacket[BufIndex],
&QosNullLength,
get_my_bssid23a(&pmlmeinfo->network),
true, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (6) BT Qos null data */
RsvdPageLoc.LocBTQosNull = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&BTQosNullLength,
get_my_bssid23a(&pmlmeinfo->network),
true, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
TotalPacketLen = BufIndex + BTQosNullLength;
pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
if (pmgntframe == NULL)
goto exit;
/* update attribute */
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib23a(padapter, pattrib);
pattrib->qsel = 0x10;
pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
exit:
kfree(ReservedPagePacket);
}
void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
{
struct joinbssrpt_parm JoinBssRptParm;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
if (mstatus == 1) {
bool bRecover = false;
u8 v8;
/* 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(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
/* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
/* correct_TSF23a(padapter, pmlmeext); */
/* Hw sequende enable by dedault. 2010.06.23. by tynli. */
/* rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */
/* rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */
/* set REG_CR bit 8 */
v8 = rtw_read8(padapter, REG_CR+1);
v8 |= BIT(0); /* ENSWBCN */
rtw_write8(padapter, REG_CR+1, v8);
/* 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. */
/* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */
/* SetBcnCtrlReg23a(padapter, BIT(4), 0); */
SetBcnCtrlReg23a(padapter, BIT(4), BIT(3));
/* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
if (pHalData->RegFwHwTxQCtrl & BIT(6))
bRecover = true;
/* To tell Hw the packet is not a real beacon frame. */
/* U1bTmp = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2); */
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
pHalData->RegFwHwTxQCtrl &= ~BIT(6);
SetFwRsvdPagePkt(padapter, 0);
/* 2010.05.11. Added by tynli. */
SetBcnCtrlReg23a(padapter, BIT(3), 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 (bRecover) {
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
pHalData->RegFwHwTxQCtrl |= BIT(6);
}
/* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
v8 = rtw_read8(padapter, REG_CR+1);
v8 &= ~BIT(0); /* ~ENSWBCN */
rtw_write8(padapter, REG_CR+1, v8);
}
JoinBssRptParm.OpMode = mstatus;
FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
}
#ifdef CONFIG_8723AU_BT_COEXIST
static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
struct xmit_frame *pmgntframe;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
struct mlme_ext_priv *pmlmeext;
struct mlme_ext_info *pmlmeinfo;
u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00};
u32 NullDataLength, BTQosNullLength;
u8 *ReservedPagePacket;
u8 PageNum, PageNeed, TxDescLen;
u16 BufIndex;
u32 TotalPacketLen;
struct rsvdpage_loc RsvdPageLoc;
DBG_8723A("+%s\n", __FUNCTION__);
ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
if (ReservedPagePacket == NULL) {
DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
return;
}
pHalData = GET_HAL_DATA(padapter);
pxmitpriv = &padapter->xmitpriv;
pmlmeext = &padapter->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
/* 3 (1) beacon */
BufIndex = TXDESC_OFFSET;
/* skip Beacon Packet */
PageNeed = 3;
PageNum += PageNeed;
pHalData->FwRsvdPageStartOffset = PageNum;
BufIndex += PageNeed*128;
/* 3 (3) null data */
RsvdPageLoc.LocNullData = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&NullDataLength,
fakemac,
false, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (6) BT Qos null data */
RsvdPageLoc.LocBTQosNull = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&BTQosNullLength,
fakemac,
true, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
TotalPacketLen = BufIndex + BTQosNullLength;
pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
if (pmgntframe == NULL)
goto exit;
/* update attribute */
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib23a(padapter, pattrib);
pattrib->qsel = 0x10;
pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
exit:
kfree(ReservedPagePacket);
}
void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
u8 bRecover = false;
DBG_8723A("+%s\n", __FUNCTION__);
pHalData = GET_HAL_DATA(padapter);
/* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
if (pHalData->RegFwHwTxQCtrl & BIT(6))
bRecover = true;
/* To tell Hw the packet is not a real beacon frame. */
pHalData->RegFwHwTxQCtrl &= ~BIT(6);
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
SetFwRsvdPagePkt_BTCoex(padapter);
/* 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 (bRecover) {
pHalData->RegFwHwTxQCtrl |= BIT(6);
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
}
}
#endif
#ifdef CONFIG_8723AU_P2P
void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter *padapter, u8 p2p_ps_state)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
u8 i;
switch (p2p_ps_state) {
case P2P_PS_DISABLE:
DBG_8723A("P2P_PS_DISABLE \n");
memset(p2p_ps_offload, 0, 1);
break;
case P2P_PS_ENABLE:
DBG_8723A("P2P_PS_ENABLE \n");
/* update CTWindow value. */
if (pwdinfo->ctwindow > 0) {
p2p_ps_offload->CTWindow_En = 1;
rtw_write8(padapter, 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(padapter, 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(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
}
if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
/* rst p2p circuit */
rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
p2p_ps_offload->Offload_En = 1;
if (rtw_p2p_chk_role(pwdinfo, 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_8723A("P2P_PS_SCAN \n");
p2p_ps_offload->discovery = 1;
break;
case P2P_PS_SCAN_DONE:
DBG_8723A("P2P_PS_SCAN_DONE \n");
p2p_ps_offload->discovery = 0;
pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
break;
default:
break;
}
FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
}
#endif /* CONFIG_8723AU_P2P */

View File

@ -0,0 +1,273 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/* */
/* Description: */
/* */
/* This file is for 92CE/92CU dynamic mechanism only */
/* */
/* */
/* */
#define _RTL8723A_DM_C_
/* */
/* include files */
/* */
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
/* */
/* Global var */
/* */
static void dm_CheckStatistics(struct rtw_adapter *Adapter)
{
}
static void dm_CheckPbcGPIO(struct rtw_adapter *padapter)
{
u8 tmp1byte;
u8 bPbcPressed = false;
if (!padapter->registrypriv.hw_wps_pbc)
return;
tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */
tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */
tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */
tmp1byte = rtw_read8(padapter, GPIO_IN);
if (tmp1byte == 0xff)
return;
if (tmp1byte&HAL_8192C_HW_GPIO_WPS_BIT)
bPbcPressed = true;
if (bPbcPressed) {
/* Here we only set bPbcPressed to true */
/* After trigger PBC, the variable will be set to false */
DBG_8723A("CheckPbcGPIO - PBC is pressed\n");
if (padapter->pid[0] == 0) {
/* 0 is the default value and it means the application
* monitors the HW PBC doesn't privde its pid to driver.
*/
return;
}
rtw_signal_process(padapter->pid[0], SIGUSR1);
}
}
/* Initialize GPIO setting registers */
/* functions */
static void Init_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
u8 cut_ver, fab_ver;
/* */
/* Init Value */
/* */
memset(pDM_Odm, 0, sizeof(*pDM_Odm));
pDM_Odm->Adapter = Adapter;
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PLATFORM, 0x04);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_INTERFACE, RTW_USB);/* RTL871X_HCI_TYPE */
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723A);
if (IS_8723A_A_CUT(pHalData->VersionID)) {
fab_ver = ODM_UMC;
cut_ver = ODM_CUT_A;
} else if (IS_8723A_B_CUT(pHalData->VersionID)) {
fab_ver = ODM_UMC;
cut_ver = ODM_CUT_B;
} else {
fab_ver = ODM_TSMC;
cut_ver = ODM_CUT_A;
}
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID));
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, pHalData->BoardType);
if (pHalData->BoardType == BOARD_USB_High_PA) {
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_LNA, true);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_PA, true);
}
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
if (pHalData->rf_type == RF_1T1R)
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
else if (pHalData->rf_type == RF_2T2R)
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
else if (pHalData->rf_type == RF_1T2R)
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
}
static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
{
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
struct dm_priv *pdmpriv = &pHalData->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_TX_PWR_TRACK |
ODM_RF_CALIBRATION;
/* Pointer reference */
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_TX_UNI,
&Adapter->xmitpriv.tx_bytes);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_RX_UNI,
&Adapter->recvpriv.rx_bytes);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_WM_MODE,
&pmlmeext->cur_wireless_mode);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET,
&pHalData->nCur40MhzPrimeSC);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_MODE,
&Adapter->securitypriv.dot11PrivacyAlgrthm);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BW,
&pHalData->CurrentChannelBW);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL,
&pHalData->CurrentChannel);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &Adapter->net_closed);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SCAN, &pmlmepriv->bScanInProcess);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_POWER_SAVING,
&pwrctrlpriv->bpower_saving);
for (i = 0; i < NUM_STA; i++)
ODM_CmnInfoPtrArrayHook23a(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL);
}
void rtl8723a_InitHalDm(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
u8 i;
pdmpriv->DM_Type = DM_Type_ByDriver;
pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
#ifdef CONFIG_8723AU_BT_COEXIST
pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
#endif
pdmpriv->InitDMFlag = pdmpriv->DMFlag;
Update_ODM_ComInfo_8723a(Adapter);
ODM23a_DMInit(pDM_Odm);
/* Save REG_INIDATA_RATE_SEL value for TXDESC. */
for (i = 0; i < 32; i++)
pdmpriv->INIDATA_RATE[i] = rtw_read8(Adapter, REG_INIDATA_RATE_SEL+i) & 0x3f;
}
void
rtl8723a_HalDmWatchDog(
struct rtw_adapter *Adapter
)
{
bool bFwCurrentInPSMode = false;
bool bFwPSAwake = true;
u8 hw_init_completed = false;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
hw_init_completed = Adapter->hw_init_completed;
if (hw_init_completed == false)
goto skip_dm;
bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
rtw23a_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
#ifdef CONFIG_8723AU_P2P
/* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
/* modifed by thomas. 2011.06.11. */
if (Adapter->wdinfo.p2p_ps_mode)
bFwPSAwake = false;
#endif /* CONFIG_8723AU_P2P */
if ((hw_init_completed) && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
/* Calculate Tx/Rx statistics. */
dm_CheckStatistics(Adapter);
/* Read REG_INIDATA_RATE_SEL value for TXDESC. */
if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE)) {
pdmpriv->INIDATA_RATE[0] = rtw_read8(Adapter, REG_INIDATA_RATE_SEL) & 0x3f;
} else {
u8 i;
for (i = 1 ; i < (Adapter->stapriv.asoc_sta_count + 1); i++)
pdmpriv->INIDATA_RATE[i] = rtw_read8(Adapter, (REG_INIDATA_RATE_SEL+i)) & 0x3f;
}
}
/* ODM */
if (hw_init_completed == true) {
u8 bLinked = false;
if (rtw_linked_check(Adapter))
bLinked = true;
ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK,
bLinked);
ODM_DMWatchdog23a(&pHalData->odmpriv);
}
skip_dm:
/* Check GPIO to determine current RF on/off and Pbc status. */
/* Check Hardware Radio ON/OFF or not */
dm_CheckPbcGPIO(Adapter);
}
void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
memset(pdmpriv, 0, sizeof(struct dm_priv));
Init_ODM_ComInfo_8723a(Adapter);
}
void rtl8723a_deinit_dm_priv(struct rtw_adapter *Adapter)
{
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,515 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
/******************************************************************************
*
*
* 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 _RTL8723A_RF6052_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
/*---------------------------Define Local Constant---------------------------*/
/* Define local structure for debug!!!!! */
struct rf_shadow_compare_map {
/* 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;
};
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetBandwidth()
*
* Overview: This function is called by SetBWMode23aCallback8190Pci() only
*
* Input: struct rtw_adapter * Adapter
* WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
*
* Output: NONE
*
* Return: NONE
*
* Note: For RF type 0222D
*---------------------------------------------------------------------------*/
void rtl8723a_phy_rf6052set_bw(
struct rtw_adapter *Adapter,
enum ht_channel_width Bandwidth) /* 20M or 40M */
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
switch (Bandwidth) {
case HT_CHANNEL_WIDTH_20:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400);
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));
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 rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, u8 *pPowerlevel)
{
struct hal_data_8723a *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;
bool TurboScanOff = false;
u8 idx1, idx2;
u8 *ptr;
/* According to SD3 eechou's suggestion, we need to disable turbo scan for RU. */
/* Otherwise, external PA will be broken if power index > 0x20. */
if (pHalData->EEPROMRegulatory != 0 || pHalData->ExternalPA)
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 {
/* 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 independantly. Thanks for Lanhsin's reminder. */
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++;
}
}
/* 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 getPowerBase(
struct rtw_adapter *Adapter,
u8 *pPowerLevel,
u8 Channel,
u32 *OfdmBase,
u32 *MCSBase
)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u32 powerBase0, powerBase1;
u8 Legacy_pwrdiff = 0;
s8 HT20_pwrdiff = 0;
u8 i, powerlevel[2];
for (i = 0; i < 2; i++) {
powerlevel[i] = pPowerLevel[i];
Legacy_pwrdiff = pHalData->TxPwrLegacyHtDiff[i][Channel-1];
powerBase0 = powerlevel[i] + Legacy_pwrdiff;
powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0;
*(OfdmBase+i) = powerBase0;
}
for (i = 0; i < 2; i++) {
/* Check HT20 to HT40 diff */
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) {
HT20_pwrdiff = pHalData->TxPwrHt20Diff[i][Channel-1];
powerlevel[i] += HT20_pwrdiff;
}
powerBase1 = powerlevel[i];
powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1;
*(MCSBase+i) = powerBase1;
}
}
static void getTxPowerWriteValByRegulatory(
struct rtw_adapter *Adapter,
u8 Channel,
u8 index,
u32 *powerBase0,
u32 *powerBase1,
u32 *pOutWriteVal
)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
u8 i, chnlGroup = 0, pwr_diff_limit[4];
u32 writeVal, customer_limit, rf;
/* Index 0 & 1 = legacy OFDM, 2-5 = HT_MCS rate */
for (rf = 0; rf < 2; rf++) {
switch (pHalData->EEPROMRegulatory) {
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 >= 3) {
if (Channel <= 3)
chnlGroup = 0;
else if (Channel >= 4 && Channel <= 9)
chnlGroup = 1;
else if (Channel > 9)
chnlGroup = 2;
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
chnlGroup++;
else
chnlGroup += 4;
}
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. */
chnlGroup = 0;
for (i = 0; i < 4; i++) {
pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index +
(rf ? 8 : 0)]&(0x7f << (i*8))) >> (i*8));
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) {
if (pwr_diff_limit[i] > pHalData->PwrGroupHT40[rf][Channel-1])
pwr_diff_limit[i] = pHalData->PwrGroupHT40[rf][Channel-1];
} else {
if (pwr_diff_limit[i] > pHalData->PwrGroupHT20[rf][Channel-1])
pwr_diff_limit[i] = pHalData->PwrGroupHT20[rf][Channel-1];
}
}
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 independantly. Thanks for Lanhsin's reminder. */
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 writeOFDMPowerReg(struct rtw_adapter *Adapter, u8 index, u32 *pValue)
{
struct hal_data_8723a *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 rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, u8 *pPowerLevel, u8 Channel)
{
u32 writeVal[2], powerBase0[2], powerBase1[2];
u8 index = 0;
getPowerBase(Adapter, pPowerLevel, Channel, &powerBase0[0], &powerBase1[0]);
for (index = 0; index < 6; index++) {
getTxPowerWriteValByRegulatory(Adapter, Channel, index,
&powerBase0[0], &powerBase1[0], &writeVal[0]);
writeOFDMPowerReg(Adapter, index, &writeVal[0]);
}
}
static int phy_RF6052_Config_ParaFile(struct rtw_adapter *Adapter)
{
u32 u4RegValue = 0;
u8 eRFPath;
struct bb_reg_define *pPhyReg;
int rtStatus = _SUCCESS;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
static char sz8723RadioAFile[] = RTL8723_PHY_RADIO_A;
static char sz8723RadioBFile[] = RTL8723_PHY_RADIO_B;
char *pszRadioAFile, *pszRadioBFile;
pszRadioAFile = sz8723RadioAFile;
pszRadioBFile = sz8723RadioBFile;
/* 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);
udelay(1);/* PlatformStallExecution(1); */
/*----Set RF_ENV output high----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
udelay(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 */
udelay(1);/* PlatformStallExecution(1); */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
udelay(1);/* PlatformStallExecution(1); */
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF_PATH_A:
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv, (enum RF_RADIO_PATH)eRFPath, (enum RF_RADIO_PATH)eRFPath))
rtStatus = _FAIL;
break;
case RF_PATH_B:
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile23a(&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) {
/* RT_TRACE(COMP_FPGA, DBG_LOUD, ("phy_RF6052_Config_ParaFile():Radio[%d] Fail!!", eRFPath)); */
goto phy_RF6052_Config_ParaFile_Fail;
}
}
phy_RF6052_Config_ParaFile_Fail:
return rtStatus;
}
int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *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;
}
/* End of HalRf6052.c */

View File

@ -0,0 +1,69 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _RTL8723A_REDESC_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
static void process_rssi(struct rtw_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;
}
static void process_link_qual(struct rtw_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 rtl8723a_process_phy_info(struct rtw_adapter *padapter, union recv_frame *prframe) */
void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe)
{
struct recv_frame *precvframe = prframe;
/* Check RSSI */
process_rssi(padapter, precvframe);
/* Check EVM */
process_link_qual(padapter, precvframe);
}

View File

@ -0,0 +1,73 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _RTL8723A_SRESET_C_
#include <rtl8723a_sreset.h>
#include <rtl8723a_hal.h>
void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter)
{
struct hal_data_8723a *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 != 0) {
DBG_8723A("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
rtw_hal_sreset_reset23a(padapter);
}
current_time = jiffies;
if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) {
diff_time = jiffies_to_msecs(jiffies - 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(jiffies - psrtpriv->last_tx_complete_time);
if (diff_time > 4000) {
/* padapter->Wifi_Error_Status = WIFI_TX_HANG; */
DBG_8723A("%s tx hang\n", __func__);
rtw_hal_sreset_reset23a(padapter);
}
}
}
}
if (psrtpriv->dbg_trigger_point == SRESET_TGP_XMIT_STATUS) {
psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
rtw_hal_sreset_reset23a(padapter);
return;
}
}
void rtl8723a_sreset_linked_status_check(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
if (psrtpriv->dbg_trigger_point == SRESET_TGP_LINK_STATUS) {
psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
rtw_hal_sreset_reset23a(padapter);
return;
}
}

View File

@ -0,0 +1,52 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _RTL8723A_XMIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
void dump_txrpt_ccx_8723a(void *buf)
{
struct txrpt_ccx_8723a *txrpt_ccx = buf;
DBG_8723A("%s:\n"
"tag1:%u, rsvd:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n"
"mac_id:%u, pkt_drop:%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->rsvd, txrpt_ccx->int_bt, txrpt_ccx->int_tri, txrpt_ccx->int_ccx
, txrpt_ccx->mac_id, txrpt_ccx->pkt_drop, txrpt_ccx->pkt_ok, txrpt_ccx->bmc
, txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over, txrpt_ccx->retry_over
, txrpt_ccx_qtime_8723a(txrpt_ccx)
, txrpt_ccx->final_data_rate
, txrpt_ccx->qsel, txrpt_ccx_sw_8723a(txrpt_ccx)
);
}
void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf)
{
struct txrpt_ccx_8723a *txrpt_ccx = buf;
if (txrpt_ccx->int_ccx) {
if (txrpt_ccx->pkt_ok)
rtw_ack_tx_done23a(&adapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
else
rtw_ack_tx_done23a(&adapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
}
}

View File

@ -0,0 +1,113 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#include "drv_types.h"
#include "rtl8723a_hal.h"
#include "rtl8723a_led.h"
/* */
/* LED object. */
/* */
/* */
/* Prototype of protected function. */
/* */
/* */
/* LED_819xUsb routines. */
/* */
/* Description: */
/* Turn on LED according to LedPin specified. */
void SwLedOn23a(struct rtw_adapter *padapter, struct led_8723a *pLed)
{
u8 LedCfg = 0;
if ((padapter->bSurpriseRemoved == true) || (padapter->bDriverStopped == true))
return;
switch (pLed->LedPin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
rtw_write8(padapter, REG_LEDCFG0, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
break;
case LED_PIN_LED1:
rtw_write8(padapter, REG_LEDCFG1, (LedCfg&0x00)|BIT6); /* SW control led1 on. */
break;
case LED_PIN_LED2:
LedCfg = rtw_read8(padapter, REG_LEDCFG2);
rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x80)|BIT5); /* SW control led1 on. */
break;
default:
break;
}
pLed->bLedOn = true;
}
/* Description: */
/* Turn off LED according to LedPin specified. */
void SwLedOff23a(struct rtw_adapter *padapter, struct led_8723a *pLed)
{
u8 LedCfg = 0;
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
goto exit;
switch (pLed->LedPin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
rtw_write8(padapter, REG_LEDCFG0, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
break;
case LED_PIN_LED1:
rtw_write8(padapter, REG_LEDCFG1, (LedCfg&0x00)|BIT5|BIT6); /* SW control led1 on. */
break;
case LED_PIN_LED2:
LedCfg = rtw_read8(padapter, REG_LEDCFG2);
rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x80)|BIT3|BIT5); /* SW control led1 on. */
break;
default:
break;
}
exit:
pLed->bLedOn = false;
}
/* Interface to manipulate LED objects. */
/* Description: */
/* Initialize all LED_871x objects. */
void
rtl8723au_InitSwLeds(struct rtw_adapter *padapter)
{
struct led_priv *pledpriv = &padapter->ledpriv;
pledpriv->LedControlHandler = LedControl871x23a;
/* 8723as-vau wifi used led2 */
InitLed871x23a(padapter, &pledpriv->SwLed0, LED_PIN_LED2);
/* InitLed871x23a(padapter,&pledpriv->SwLed1, LED_PIN_LED2); */
}
/* Description: */
/* DeInitialize all LED_819xUsb objects. */
void
rtl8723au_DeInitSwLeds(struct rtw_adapter *padapter)
{
struct led_priv *ledpriv = &padapter->ledpriv;
DeInitLed871x23a(&ledpriv->SwLed0);
}

View File

@ -0,0 +1,247 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _RTL8192CU_RECV_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <mlme_osdep.h>
#include <linux/ip.h>
#include <linux/if_ether.h>
#include <ethernet.h>
#include <usb_ops.h>
#include <wifi.h>
#include <rtl8723a_hal.h>
void rtl8723au_init_recvbuf(struct rtw_adapter *padapter,
struct recv_buf *precvbuf)
{
}
int rtl8723au_init_recv_priv(struct rtw_adapter *padapter)
{
struct recv_priv *precvpriv = &padapter->recvpriv;
int i, size, res = _SUCCESS;
struct recv_buf *precvbuf;
unsigned long tmpaddr;
unsigned long alignment;
struct sk_buff *pskb;
tasklet_init(&precvpriv->recv_tasklet,
(void(*)(unsigned long))rtl8723au_recv_tasklet,
(unsigned long)padapter);
precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!precvpriv->int_in_urb)
DBG_8723A("alloc_urb for interrupt in endpoint fail !!!!\n");
precvpriv->int_in_buf = kzalloc(USB_INTR_CONTENT_LENGTH, GFP_KERNEL);
if (!precvpriv->int_in_buf)
DBG_8723A("alloc_mem for interrupt in endpoint fail !!!!\n");
/* init recv_buf */
_rtw_init_queue23a(&precvpriv->free_recv_buf_queue);
size = NR_RECVBUFF * sizeof(struct recv_buf);
precvpriv->precv_buf = kzalloc(size, GFP_KERNEL);
if (!precvpriv->precv_buf) {
res = _FAIL;
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("alloc recv_buf fail!\n"));
goto exit;
}
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
INIT_LIST_HEAD(&precvbuf->list);
res = rtw_os_recvbuf_resource_alloc23a(padapter, precvbuf);
if (res == _FAIL)
break;
precvbuf->adapter = padapter;
precvbuf++;
}
precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
skb_queue_head_init(&precvpriv->rx_skb_queue);
skb_queue_head_init(&precvpriv->free_recv_skb_queue);
for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
size = MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ;
pskb = __netdev_alloc_skb(padapter->pnetdev, size, GFP_KERNEL);
if (pskb) {
pskb->dev = padapter->pnetdev;
tmpaddr = (unsigned long)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 rtl8723au_free_recv_priv(struct rtw_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_free23a(padapter, precvbuf);
precvbuf++;
}
kfree(precvpriv->precv_buf);
usb_free_urb(precvpriv->int_in_urb);
kfree(precvpriv->int_in_buf);
if (skb_queue_len(&precvpriv->rx_skb_queue))
DBG_8723A(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_8723A(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);
}
void update_recvframe_attrib(struct recv_frame *precvframe,
struct recv_stat *prxstat)
{
struct rx_pkt_attrib *pattrib;
struct recv_stat report;
struct rxreport_8723a *prxreport;
report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
prxreport = (struct rxreport_8723a *)&report;
pattrib = &precvframe->attrib;
memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
/* update rx report to recv_frame attribute */
pattrib->pkt_len = (u16)prxreport->pktlen;
pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
pattrib->physt = (u8)prxreport->physt;
pattrib->crc_err = (u8)prxreport->crc32;
pattrib->icv_err = (u8)prxreport->icverr;
pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
pattrib->encrypt = (u8)prxreport->security;
pattrib->qos = (u8)prxreport->qos;
pattrib->priority = (u8)prxreport->tid;
pattrib->amsdu = (u8)prxreport->amsdu;
pattrib->seq_num = (u16)prxreport->seq;
pattrib->frag_num = (u8)prxreport->frag;
pattrib->mfrag = (u8)prxreport->mf;
pattrib->mdata = (u8)prxreport->md;
pattrib->mcs_rate = (u8)prxreport->rxmcs;
pattrib->rxht = (u8)prxreport->rxht;
}
void update_recvframe_phyinfo(struct recv_frame *precvframe,
struct phy_stat *pphy_status)
{
struct rtw_adapter *padapter = precvframe->adapter;
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct odm_phy_info *pPHYInfo = (struct odm_phy_info *)(&pattrib->phy_info);
struct odm_packet_info pkt_info;
u8 *sa = NULL, *da;
struct sta_priv *pstapriv;
struct sta_info *psta;
struct sk_buff *skb = precvframe->pkt;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u8 *wlanhdr = skb->data;
pkt_info.bPacketMatchBSSID = false;
pkt_info.bPacketToSelf = false;
pkt_info.bPacketBeacon = false;
pkt_info.bPacketMatchBSSID =
(!ieee80211_is_ctl(hdr->frame_control) &&
!pattrib->icv_err &&
!pattrib->crc_err &&
!memcmp(get_hdr_bssid(wlanhdr),
get_bssid(&padapter->mlmepriv), ETH_ALEN));
da = ieee80211_get_DA(hdr);
pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
(!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN));
pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
ieee80211_is_beacon(hdr->frame_control);
pkt_info.StationID = 0xFF;
if (pkt_info.bPacketBeacon) {
if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true)
sa = padapter->mlmepriv.cur_network.network.MacAddress;
/* to do Ad-hoc */
} else {
sa = ieee80211_get_SA(hdr);
}
pstapriv = &padapter->stapriv;
psta = rtw_get_stainfo23a(pstapriv, sa);
if (psta) {
pkt_info.StationID = psta->mac_id;
/* printk("%s ==> StationID(%d)\n", __FUNCTION__, pkt_info.StationID); */
}
pkt_info.Rate = pattrib->mcs_rate;
ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo,
(u8 *)pphy_status, &pkt_info);
precvframe->psta = NULL;
if (pkt_info.bPacketMatchBSSID &&
(check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
if (psta) {
precvframe->psta = psta;
rtl8723a_process_phy_info(padapter, precvframe);
}
} else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
if (check_fwstate(&padapter->mlmepriv,
WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) ==
true) {
if (psta)
precvframe->psta = psta;
}
rtl8723a_process_phy_info(padapter, precvframe);
}
}

View File

@ -0,0 +1,548 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#define _RTL8192C_XMIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <wifi.h>
#include <osdep_intf.h>
#include <usb_ops.h>
/* include <rtl8192c_hal.h> */
#include <rtl8723a_hal.h>
s32 rtl8723au_init_xmit_priv(struct rtw_adapter *padapter)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
tasklet_init(&pxmitpriv->xmit_tasklet,
(void(*)(unsigned long))rtl8723au_xmit_tasklet,
(unsigned long)padapter);
return _SUCCESS;
}
void rtl8723au_free_xmit_priv(struct rtw_adapter *padapter)
{
}
static void do_queue_select(struct rtw_adapter *padapter, struct pkt_attrib *pattrib)
{
u8 qsel;
qsel = pattrib->priority;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
("### do_queue_select priority =%d , qsel = %d\n",
pattrib->priority, qsel));
pattrib->qsel = qsel;
}
static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz)
{
int blnSetTxDescOffset;
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
if (pdvobj->ishighspeed) {
if (((sz + TXDESC_SIZE) % 512) == 0)
blnSetTxDescOffset = 1;
else
blnSetTxDescOffset = 0;
} else {
if (((sz + TXDESC_SIZE) % 64) == 0)
blnSetTxDescOffset = 1;
else
blnSetTxDescOffset = 0;
}
return blnSetTxDescOffset;
}
static void rtl8192cu_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(*(usPtr + index));
ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum);
}
static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
{
if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
switch (pattrib->encrypt) {
/* SEC_TYPE */
case _WEP40_:
case _WEP104_:
ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
break;
case _TKIP_:
case _TKIP_WTMIC_:
/* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */
ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
break;
case _AES_:
ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000);
break;
case _NO_PRIVACY_:
default:
break;
}
}
}
static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw)
{
/* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
switch (pattrib->vcs_mode) {
case RTS_CTS:
*pdw |= cpu_to_le32(BIT(12));
break;
case CTS_TO_SELF:
*pdw |= cpu_to_le32(BIT(11));
break;
case NONE_VCS:
default:
break;
}
if (pattrib->vcs_mode) {
*pdw |= cpu_to_le32(BIT(13));
/* 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, u32 *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<<20)&0x003f0000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
*pdw |= cpu_to_le32((0x02<<20)&0x003f0000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
*pdw |= 0;
else
*pdw |= cpu_to_le32((0x03<<20)&0x003f0000);
}
}
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
{
int pull = 0;
uint qsel;
struct rtw_adapter *padapter = pxmitframe->padapter;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
int bmcst = is_multicast_ether_addr(pattrib->ra);
if ((!bagg_pkt) && (urb_zero_packet_chk(padapter, sz) == 0)) {
ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
pull = 1;
pxmitframe->pkt_offset--;
}
memset(ptxdesc, 0, sizeof(struct tx_desc));
if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
qsel = (uint)(pattrib->qsel & 0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
fill_txdesc_sectype(pattrib, ptxdesc);
if (pattrib->ampdu_en)
ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */
else
ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
/* offset 8 */
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
/* offset 16 , offset 20 */
if (pattrib->qos_en)
ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */
if ((pattrib->ether_type != 0x888e) &&
(pattrib->ether_type != 0x0806) &&
(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);/* */
/* use REG_INIDATA_RATE_SEL value */
ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]);
} else {
/* EAP data packet and ARP packet. */
/* Use the 1M data rate to send the EAP/ARP packet. */
/* This will maybe make the handshake smooth. */
ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
}
} else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
qsel = (uint)(pattrib->qsel&0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00);
ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 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<<16)&0xffff0000);
/* offset 16 */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
/* offset 20 */
ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */
ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
} else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
} else {
DBG_8723A("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */
ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */
/* offset 8 */
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
/* offset 16 */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
/* offset 20 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
}
/* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
/* mgnt frame should be controled 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. */
if (!pattrib->qos_en) {
/* Hw set sequence number */
ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
/* set bit3 to 1. */
ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
}
/* offset 0 */
ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff);
ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);/* 32 bytes for TX Desc */
if (bmcst)
ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("offset0-txdesc = 0x%x\n", ptxdesc->txdw0));
/* offset 4 */
/* pkt_offset, unit:8 bytes padding */
if (pxmitframe->pkt_offset > 0)
ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
rtl8192cu_cal_txdesc_chksum(ptxdesc);
return pull;
}
static s32 rtw_dump_xframe(struct rtw_adapter *padapter, 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 = &padapter->xmitpriv;
if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
(pxmitframe->attrib.ether_type != 0x0806) &&
(pxmitframe->attrib.ether_type != 0x888e) &&
(pxmitframe->attrib.dhcp_pkt != 1))
rtw_issue_addbareq_cmd23a(padapter, 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 - 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_hwaddr23a(pxmitframe);
inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, pxmitbuf);
rtw_count_tx_stats23a(padapter, 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(((unsigned long)(mem_addr)));
}
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
if (ret != _SUCCESS)
rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
return ret;
}
s32 rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
{
struct hw_xmit *phwxmits;
struct xmit_frame *pxmitframe;
int hwentry;
int res = _SUCCESS, xcnt = 0;
phwxmits = pxmitpriv->hwxmits;
hwentry = pxmitpriv->hwxmit_entry;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete()\n"));
if (pxmitbuf == NULL) {
pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
if (!pxmitbuf)
return false;
}
pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry);
if (pxmitframe) {
pxmitframe->pxmitbuf = pxmitbuf;
pxmitframe->buf_addr = pxmitbuf->pbuf;
pxmitbuf->priv_data = pxmitframe;
if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
if (pxmitframe->attrib.priority <= 15)/* TID0~15 */
res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */
}
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete(): rtw_dump_xframe\n"));
if (res == _SUCCESS) {
rtw_dump_xframe(padapter, pxmitframe);
} else {
rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
}
xcnt++;
} else {
rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
return false;
}
return true;
}
static s32 xmitframe_direct(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
s32 res = _SUCCESS;
res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
if (res == _SUCCESS)
rtw_dump_xframe(padapter, pxmitframe);
return res;
}
/*
* Return
* true dump packet directly
* false enqueue packet
*/
static s32 pre_xmitframe(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
s32 res;
struct xmit_buf *pxmitbuf = NULL;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
do_queue_select(padapter, pattrib);
spin_lock_bh(&pxmitpriv->lock);
#ifdef CONFIG_8723AU_AP_MODE
if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
struct sta_info *psta;
struct sta_priv *pstapriv = &padapter->stapriv;
spin_unlock_bh(&pxmitpriv->lock);
if (pattrib->psta)
psta = pattrib->psta;
else
psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
if (psta) {
if (psta->sleepq_len > (NR_XMITFRAME>>3))
wakeup_sta_to_xmit23a(padapter, psta);
}
return false;
}
#endif
if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0)
goto enqueue;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
goto enqueue;
pxmitbuf = rtw_alloc_xmitbuf23a(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(padapter, pxmitframe) != _SUCCESS) {
rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
}
return true;
enqueue:
res = rtw_xmitframe_enqueue23a(padapter, 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_xmitframe23a(pxmitpriv, pxmitframe);
/* Trick, make the statistics correct */
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
return true;
}
return false;
}
s32 rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe)
{
return rtw_dump_xframe(padapter, pmgntframe);
}
/*
* Return
* true dump packet directly ok
* false temporary can't transmit packets to hardware
*/
s32 rtl8723au_hal_xmit(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
return pre_xmitframe(padapter, pxmitframe);
}
s32 rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter,
struct xmit_frame *pxmitframe)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
s32 err;
err = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
if (err != _SUCCESS) {
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
/* Trick, make the statistics correct */
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
} else {
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
}
return err;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,848 @@
/******************************************************************************
*
* 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.
*
******************************************************************************/
#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 <rtl8723a_hal.h>
#include <rtl8723a_recv.h>
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
{
struct rtw_adapter *padapter = pintfhdl->padapter ;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct usb_device *udev = pdvobjpriv->pusbdev;
unsigned int pipe;
int status = 0;
u8 reqtype;
u8 *pIo_buf;
int vendorreq_times = 0;
if ((padapter->bSurpriseRemoved) || (padapter->pwrctrlpriv.pnp_bstop_trx)) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usbctrl_vendorreq:(padapter->bSurpriseRemoved||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
status = -EPERM;
goto exit;
}
if (len > MAX_VENDOR_REQ_CMD_SIZE) {
DBG_8723A("[%s] Buffer len error , vendor request failed\n", __FUNCTION__);
status = -EINVAL;
goto exit;
}
mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
/* Acquire IO memory for vendorreq */
pIo_buf = pdvobjpriv->usb_vendor_req_buf;
if (pIo_buf == NULL) {
DBG_8723A("[%s] pIo_buf == NULL \n", __FUNCTION__);
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(pdvobjpriv);
if (requesttype == 0x01) {
/* For Control read transfer, we have to copy
* the read data from pIo_buf to pdata.
*/
memcpy(pdata, pIo_buf, len);
}
} else { /* error cases */
DBG_8723A("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) {
padapter->bSurpriseRemoved = true;
} else {
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->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(pdvobjpriv)) {
padapter->bSurpriseRemoved = true;
break;
}
}
/* firmware download is checksumed, don't retry */
if ((value >= FW_8723A_START_ADDRESS && value <= FW_8723A_END_ADDRESS) || status == len)
break;
}
release_mutex:
mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
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;
u16 data = 0;
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 data;
}
static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u32 data = 0;
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 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;
u16 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 2;
data = val;
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;
u32 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 4;
data = 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;
}
/*
* Description:
* Recognize the interrupt content by reading the interrupt
* register or content and masking interrupt mask (IMR)
* if it is our NIC's interrupt. After recognizing, we may clear
* the all interrupts (ISR).
* Arguments:
* [in] Adapter -
* The adapter context.
* [in] pContent -
* Under PCI interface, this field is ignord.
* Under USB interface, the content is the interrupt
* content pointer.
* Under SDIO interface, this is the interrupt type which
* is Local interrupt or system interrupt.
* [in] ContentLen -
* The length in byte of pContent.
* Return:
* If any interrupt matches the mask (IMR), return true, and
* return false otherwise.
*/
static bool
InterruptRecognized8723AU(struct rtw_adapter *Adapter, void *pContent,
u32 ContentLen)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 *buffer = (u8 *)pContent;
struct reportpwrstate_parm report;
memcpy(&pHalData->IntArray[0], &buffer[USB_INTR_CONTENT_HISR_OFFSET],
4);
pHalData->IntArray[0] &= pHalData->IntrMask[0];
/* For HISR extension. Added by tynli. 2009.10.07. */
memcpy(&pHalData->IntArray[1],
&buffer[USB_INTR_CONTENT_HISRE_OFFSET], 4);
pHalData->IntArray[1] &= pHalData->IntrMask[1];
/* We sholud remove this function later because DDK suggest
* not to executing too many operations in MPISR */
memcpy(&report.state, &buffer[USB_INTR_CPWM_OFFSET], 1);
return ((pHalData->IntArray[0])&pHalData->IntrMask[0]) != 0 ||
((pHalData->IntArray[1])&pHalData->IntrMask[1]) != 0;
}
static void usb_read_interrupt_complete(struct urb *purb, struct pt_regs *regs)
{
int err;
struct rtw_adapter *padapter = (struct rtw_adapter *)purb->context;
if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
padapter->bReadPortCancel) {
DBG_8723A("%s() RX Warning! bDriverStopped(%d) OR "
"bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
__FUNCTION__, padapter->bDriverStopped,
padapter->bSurpriseRemoved,
padapter->bReadPortCancel);
return;
}
if (purb->status == 0) {
struct c2h_evt_hdr *c2h_evt;
c2h_evt = (struct c2h_evt_hdr *)purb->transfer_buffer;
if (purb->actual_length > USB_INTR_CONTENT_LENGTH) {
DBG_8723A("usb_read_interrupt_complete: purb->actual_"
"length > USB_INTR_CONTENT_LENGTH\n");
goto urb_submit;
}
InterruptRecognized8723AU(padapter, purb->transfer_buffer,
purb->actual_length);
if (c2h_evt_exist(c2h_evt)) {
if (c2h_id_filter_ccx_8723a(c2h_evt->id)) {
/* Handle CCX report here */
handle_txrpt_ccx_8723a(padapter, (void *)(c2h_evt->payload));
/* Replace with special pointer to
trigger c2h_evt_clear23a */
if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
(void *)&padapter->evtpriv) !=
_SUCCESS)
DBG_8723A("%s rtw_cbuf_push23a fail\n",
__func__);
schedule_work(&padapter->evtpriv.c2h_wk);
} else if ((c2h_evt = (struct c2h_evt_hdr *)
kmalloc(16, GFP_ATOMIC))) {
memcpy(c2h_evt, purb->transfer_buffer, 16);
if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
(void *)c2h_evt) != _SUCCESS)
DBG_8723A("%s rtw_cbuf_push23a fail\n",
__func__);
schedule_work(&padapter->evtpriv.c2h_wk);
} else {
/* Error handling for malloc fail */
if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
(void *)NULL) != _SUCCESS)
DBG_8723A("%s rtw_cbuf_push23a fail\n",
__func__);
schedule_work(&padapter->evtpriv.c2h_wk);
}
}
urb_submit:
err = usb_submit_urb(purb, GFP_ATOMIC);
if (err && (err != -EPERM)) {
DBG_8723A("cannot submit interrupt in-token(err = "
"0x%08x), urb_status = %d\n",
err, purb->status);
}
} else {
DBG_8723A("###=> usb_read_interrupt_complete => urb "
"status(%d)\n", purb->status);
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"));
/* Fall Through here */
case -ENOENT:
padapter->bDriverStopped = true;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bDriverStopped ="
"true\n"));
break;
case -EPROTO:
break;
case -EINPROGRESS:
DBG_8723A("ERROR: URB IS IN PROGRESS!/n");
break;
default:
break;
}
}
}
static u32 usb_read_interrupt(struct intf_hdl *pintfhdl, u32 addr)
{
int err;
unsigned int pipe;
u32 ret = _SUCCESS;
struct rtw_adapter *adapter = pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
struct recv_priv *precvpriv = &adapter->recvpriv;
struct usb_device *pusbd = pdvobj->pusbdev;
/* translate DMA FIFO addr to pipehandle */
pipe = ffaddr2pipehdl23a(pdvobj, addr);
usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe,
precvpriv->int_in_buf, USB_INTR_CONTENT_LENGTH,
usb_read_interrupt_complete, adapter, 1);
err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC);
if (err && (err != -EPERM)) {
DBG_8723A("cannot submit interrupt in-token(err = 0x%08x),"
"urb_status = %d\n", err,
precvpriv->int_in_urb->status);
ret = _FAIL;
}
return ret;
}
static int recvbuf2recvframe(struct rtw_adapter *padapter, 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_info = NULL;
struct sk_buff *pkt_copy = NULL;
struct recv_frame *precvframe = NULL;
struct rx_pkt_attrib *pattrib = NULL;
struct recv_priv *precvpriv = &padapter->recvpriv;
struct rtw_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_recvframe23a(pfree_recv_queue);
if (!precvframe) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("recvbuf2recvframe: precvframe == NULL\n"));
DBG_8723A("%s()-%d: rtw_alloc_recvframe23a() failed! RX "
"Drop!\n", __FUNCTION__, __LINE__);
goto _exit_recvbuf2recvframe;
}
INIT_LIST_HEAD(&precvframe->list);
update_recvframe_attrib(precvframe, prxstat);
pattrib = &precvframe->attrib;
if (pattrib->crc_err) {
DBG_8723A("%s()-%d: RX Warning! rx CRC ERROR !!\n",
__FUNCTION__, __LINE__);
rtw_free_recvframe23a(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
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_8723A("%s()-%d: RX Warning!\n",
__FUNCTION__, __LINE__);
rtw_free_recvframe23a(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
/* Modified by Albert 20101213 */
/* For 8 bytes IP header alignment. */
/* Qos data, wireless lan header length is 26 */
if (pattrib->qos) {
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)) {
/* alloc_sz = 1664; 1664 is 128 alignment. */
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(padapter->pnetdev, alloc_sz);
if (pkt_copy) {
pkt_copy->dev = padapter->pnetdev;
precvframe->pkt = pkt_copy;
skb_reserve(pkt_copy, 8 - ((unsigned long)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
/*force ip_hdr at 8-byte alignment address according to shift_sz. */
skb_reserve(pkt_copy, shift_sz);
memcpy(pkt_copy->data, (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
skb_put(pkt_copy, skb_len);
} else {
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
DBG_8723A("recvbuf2recvframe: alloc_skb fail, "
"drop frag frame \n");
rtw_free_recvframe23a(precvframe,
pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
if (!precvframe->pkt) {
DBG_8723A("recvbuf2recvframe: skb_clone "
"fail\n");
rtw_free_recvframe23a(precvframe,
pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
}
if (pattrib->physt) {
pphy_info = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
update_recvframe_phyinfo(precvframe, pphy_info);
}
if (rtw_recv_entry23a(precvframe) != _SUCCESS)
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("recvbuf2recvframe: rtw_recv_entry23a"
"(precvframe) != _SUCCESS\n"));
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 rtl8723au_recv_tasklet(void *priv)
{
struct sk_buff *pskb;
struct rtw_adapter *padapter = (struct rtw_adapter *)priv;
struct recv_priv *precvpriv = &padapter->recvpriv;
while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
if ((padapter->bDriverStopped) ||
(padapter->bSurpriseRemoved)) {
DBG_8723A("recv_tasklet => bDriverStopped or "
"bSurpriseRemoved \n");
dev_kfree_skb_any(pskb);
break;
}
recvbuf2recvframe(padapter, 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 rtw_adapter *padapter = (struct rtw_adapter *)precvbuf->adapter;
struct recv_priv *precvpriv = &padapter->recvpriv;
struct hal_data_8723a *pHalData;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete!!!\n"));
precvpriv->rx_pending_cnt--;
if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
padapter->bReadPortCancel) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bDriverStopped(%d) OR "
"bSurpriseRemoved(%d)\n", padapter->bDriverStopped,
padapter->bSurpriseRemoved));
DBG_8723A("%s()-%d: RX Warning! bDriverStopped(%d) OR "
"bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
__FUNCTION__, __LINE__, padapter->bDriverStopped,
padapter->bSurpriseRemoved, padapter->bReadPortCancel);
return;
}
if (purb->status == 0) {
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"));
rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
precvbuf);
DBG_8723A("%s()-%d: RX Warning!\n",
__FUNCTION__, __LINE__);
} else {
rtw_reset_continual_urb_error(
adapter_to_dvobj(padapter));
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;
rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
precvbuf);
}
} else {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete : purb->status(%d) != 0 \n",
purb->status));
skb_put(precvbuf->pskb, purb->actual_length);
precvbuf->pskb = NULL;
DBG_8723A("###=> usb_read_port_complete => urb status(%d)\n",
purb->status);
if (rtw_inc_and_chk_continual_urb_error(
adapter_to_dvobj(padapter))) {
padapter->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:bSurprise"
"Removed = true\n"));
/* Intentional fall through here */
case -ENOENT:
padapter->bDriverStopped = true;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:"
"bDriverStopped = true\n"));
break;
case -EPROTO:
case -EOVERFLOW:
pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.Wifi_Error_Status =
USB_READ_PORT_FAIL;
rtw_read_port(padapter, precvpriv->ff_hwaddr,
0, precvbuf);
break;
case -EINPROGRESS:
DBG_8723A("ERROR: URB IS IN PROGRESS!/n");
break;
default:
break;
}
}
}
static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
struct recv_buf *precvbuf)
{
int err;
unsigned int pipe;
unsigned long tmpaddr = 0;
unsigned long alignment = 0;
u32 ret = _SUCCESS;
struct urb *purb = NULL;
struct rtw_adapter *adapter = pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
struct recv_priv *precvpriv = &adapter->recvpriv;
struct usb_device *pusbd = pdvobj->pusbdev;
if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
adapter->pwrctrlpriv.pnp_bstop_trx) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port:(padapter->bDriverStopped ||"
"padapter->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->pskb)
precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
rtl8723au_init_recvbuf(adapter, precvbuf);
/* re-assign for linux based on skb */
if (!precvbuf->pskb) {
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"));
return _FAIL;
}
tmpaddr = (unsigned long)precvbuf->pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
}
precvpriv->rx_pending_cnt++;
purb = precvbuf->purb;
/* translate DMA FIFO addr to pipehandle */
pipe = ffaddr2pipehdl23a(pdvobj, addr);
usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pskb->data,
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_8723A("cannot submit rx in-token(err = 0x%08x), urb_status "
"= %d\n", err, purb->status);
ret = _FAIL;
}
return ret;
}
void rtl8723au_xmit_tasklet(void *priv)
{
int ret = false;
struct rtw_adapter *padapter = (struct rtw_adapter *)priv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY))
return;
while (1) {
if ((padapter->bDriverStopped) ||
(padapter->bSurpriseRemoved) ||
(padapter->bWritePortCancel)) {
DBG_8723A("xmit_tasklet => bDriverStopped or "
"bSurpriseRemoved or bWritePortCancel\n");
break;
}
ret = rtl8723au_xmitframe_complete(padapter, pxmitpriv, NULL);
if (!ret)
break;
}
}
void rtl8723au_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_mem23a;
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_mem23a;
pops->_write_port = &usb_write_port23a;
pops->_read_port_cancel = &usb_read_port_cancel23a;
pops->_write_port_cancel = &usb_write_port23a_cancel;
pops->_read_interrupt = &usb_read_interrupt;
}
void rtl8723au_set_hw_type(struct rtw_adapter *padapter)
{
padapter->chip_type = RTL8723A;
padapter->HardwareType = HARDWARE_TYPE_RTL8723AU;
DBG_8723A("CHIP TYPE: RTL8723A\n");
}