Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,15 @@
rtl8192se-objs := \
dm.o \
fw.o \
hw.o \
led.o \
phy.o \
rf.o \
sw.o \
table.o \
trx.o
obj-$(CONFIG_RTL8192SE) += rtl8192se.o
ccflags-y += -D__CHECK_ENDIAN__

View file

@ -0,0 +1,556 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __REALTEK_92S_DEF_H__
#define __REALTEK_92S_DEF_H__
#define RX_MPDU_QUEUE 0
#define RX_CMD_QUEUE 1
#define RX_MAX_QUEUE 2
#define SHORT_SLOT_TIME 9
#define NON_SHORT_SLOT_TIME 20
/* Queue Select Value in TxDesc */
#define QSLT_BK 0x2
#define QSLT_BE 0x0
#define QSLT_VI 0x5
#define QSLT_VO 0x6
#define QSLT_BEACON 0x10
#define QSLT_HIGH 0x11
#define QSLT_MGNT 0x12
#define QSLT_CMD 0x13
/* Tx Desc */
#define TX_DESC_SIZE_RTL8192S (16 * 4)
#define TX_CMDDESC_SIZE_RTL8192S (16 * 4)
/* Define a macro that takes a le32 word, converts it to host ordering,
* right shifts by a specified count, creates a mask of the specified
* bit count, and extracts that number of bits.
*/
#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \
((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \
BIT_LEN_MASK_32(__mask))
/* Define a macro that clears a bit field in an le32 word and
* sets the specified value into that bit field. The resulting
* value remains in le32 ordering; however, it is properly converted
* to host ordering for the clear and set operations before conversion
* back to le32.
*/
#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \
(*(__le32 *)(__pdesc) = \
(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \
(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \
(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
/* macros to read/write various fields in RX or TX descriptors */
/* Dword 0 */
#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val)
#define SET_TX_DESC_OFFSET(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val)
#define SET_TX_DESC_TYPE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val)
#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
#define SET_TX_DESC_LINIP(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
#define SET_TX_DESC_AMSDU(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
#define SET_TX_DESC_GREEN_FIELD(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
#define SET_TX_DESC_OWN(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
#define GET_TX_DESC_OWN(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 31, 1)
/* Dword 1 */
#define SET_TX_DESC_MACID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val)
#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 5, 1, __val)
#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 6, 1, __val)
#define SET_TX_DESC_PIFS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 7, 1, __val)
#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 8, 5, __val)
#define SET_TX_DESC_ACK_POLICY(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 13, 2, __val)
#define SET_TX_DESC_NO_ACM(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val)
#define SET_TX_DESC_NON_QOS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 16, 1, __val)
#define SET_TX_DESC_KEY_ID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 17, 2, __val)
#define SET_TX_DESC_OUI(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 19, 1, __val)
#define SET_TX_DESC_PKT_TYPE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 20, 1, __val)
#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 21, 1, __val)
#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 22, 2, __val)
#define SET_TX_DESC_WDS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val)
#define SET_TX_DESC_HTC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val)
#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 26, 5, __val)
#define SET_TX_DESC_HWPC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val)
/* Dword 2 */
#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 0, 6, __val)
#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 6, 1, __val)
#define SET_TX_DESC_TSFL(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 7, 5, __val)
#define SET_TX_DESC_RTS_RETRY_COUNT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 12, 6, __val)
#define SET_TX_DESC_DATA_RETRY_COUNT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 18, 6, __val)
#define SET_TX_DESC_RSVD_MACID(__pdesc, __val) \
SET_BITS_OFFSET_LE(((__pdesc) + 8), 24, 5, __val)
#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 29, 1, __val)
#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val)
#define SET_TX_DESC_OWN_MAC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 31, 1, __val)
/* Dword 3 */
#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 0, 8, __val)
#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 8, 8, __val)
#define SET_TX_DESC_SEQ(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 16, 12, __val)
#define SET_TX_DESC_FRAG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 28, 4, __val)
/* Dword 4 */
#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 0, 6, __val)
#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 6, 1, __val)
#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 7, 4, __val)
#define SET_TX_DESC_CTS_ENABLE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 11, 1, __val)
#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 12, 1, __val)
#define SET_TX_DESC_RA_BRSR_ID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 13, 3, __val)
#define SET_TX_DESC_TXHT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 16, 1, __val)
#define SET_TX_DESC_TX_SHORT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 17, 1, __val)
#define SET_TX_DESC_TX_BANDWIDTH(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 18, 1, __val)
#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 19, 2, __val)
#define SET_TX_DESC_TX_STBC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 21, 2, __val)
#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 23, 1, __val)
#define SET_TX_DESC_RTS_HT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 24, 1, __val)
#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 25, 1, __val)
#define SET_TX_DESC_RTS_BANDWIDTH(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 26, 1, __val)
#define SET_TX_DESC_RTS_SUB_CARRIER(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 27, 2, __val)
#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 29, 2, __val)
#define SET_TX_DESC_USER_RATE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 31, 1, __val)
/* Dword 5 */
#define SET_TX_DESC_PACKET_ID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 20, 0, 9, __val)
#define SET_TX_DESC_TX_RATE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 20, 9, 6, __val)
#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 20, 15, 1, __val)
#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 20, 16, 5, __val)
#define SET_TX_DESC_TX_AGC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 20, 21, 11, __val)
/* Dword 6 */
#define SET_TX_DESC_IP_CHECK_SUM(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 16, __val)
#define SET_TX_DESC_TCP_CHECK_SUM(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 16, 16, __val)
/* Dword 7 */
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 28, 0, 16, __val)
#define SET_TX_DESC_IP_HEADER_OFFSET(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 28, 16, 8, __val)
#define SET_TX_DESC_TCP_ENABLE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 28, 31, 1, __val)
/* Dword 8 */
#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 32, 0, 32, __val)
#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 32, 0, 32)
/* Dword 9 */
#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 36, 0, 32, __val)
/* Because the PCI Tx descriptors are chaied at the
* initialization and all the NextDescAddresses in
* these descriptors cannot not be cleared (,or
* driver/HW cannot find the next descriptor), the
* offset 36 (NextDescAddresses) is reserved when
* the desc is cleared. */
#define TX_DESC_NEXT_DESC_OFFSET 36
#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \
memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET))
/* Rx Desc */
#define RX_STATUS_DESC_SIZE 24
#define RX_DRV_INFO_SIZE_UNIT 8
/* DWORD 0 */
#define SET_RX_STATUS_DESC_PKT_LEN(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val)
#define SET_RX_STATUS_DESC_CRC32(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 14, 1, __val)
#define SET_RX_STATUS_DESC_ICV(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 15, 1, __val)
#define SET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 16, 4, __val)
#define SET_RX_STATUS_DESC_SECURITY(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 20, 3, __val)
#define SET_RX_STATUS_DESC_QOS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 23, 1, __val)
#define SET_RX_STATUS_DESC_SHIFT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val)
#define SET_RX_STATUS_DESC_PHY_STATUS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
#define SET_RX_STATUS_DESC_SWDEC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
#define SET_RX_STATUS_DESC_LAST_SEG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
#define SET_RX_STATUS_DESC_FIRST_SEG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
#define SET_RX_STATUS_DESC_EOR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
#define SET_RX_STATUS_DESC_OWN(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
#define GET_RX_STATUS_DESC_PKT_LEN(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 0, 14)
#define GET_RX_STATUS_DESC_CRC32(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 14, 1)
#define GET_RX_STATUS_DESC_ICV(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 15, 1)
#define GET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 16, 4)
#define GET_RX_STATUS_DESC_SECURITY(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 20, 3)
#define GET_RX_STATUS_DESC_QOS(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 23, 1)
#define GET_RX_STATUS_DESC_SHIFT(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 24, 2)
#define GET_RX_STATUS_DESC_PHY_STATUS(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 26, 1)
#define GET_RX_STATUS_DESC_SWDEC(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 27, 1)
#define GET_RX_STATUS_DESC_LAST_SEG(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 28, 1)
#define GET_RX_STATUS_DESC_FIRST_SEG(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 29, 1)
#define GET_RX_STATUS_DESC_EOR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 30, 1)
#define GET_RX_STATUS_DESC_OWN(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc, 31, 1)
/* DWORD 1 */
#define SET_RX_STATUS_DESC_MACID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val)
#define SET_RX_STATUS_DESC_TID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 5, 4, __val)
#define SET_RX_STATUS_DESC_PAGGR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 14, 1, __val)
#define SET_RX_STATUS_DESC_FAGGR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val)
#define SET_RX_STATUS_DESC_A1_FIT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 16, 4, __val)
#define SET_RX_STATUS_DESC_A2_FIT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 20, 4, __val)
#define SET_RX_STATUS_DESC_PAM(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val)
#define SET_RX_STATUS_DESC_PWR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val)
#define SET_RX_STATUS_DESC_MOREDATA(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 26, 1, __val)
#define SET_RX_STATUS_DESC_MOREFRAG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val)
#define SET_RX_STATUS_DESC_TYPE(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 28, 2, __val)
#define SET_RX_STATUS_DESC_MC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 30, 1, __val)
#define SET_RX_STATUS_DESC_BC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 4, 31, 1, __val)
#define GET_RX_STATUS_DEC_MACID(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 0, 5)
#define GET_RX_STATUS_DESC_TID(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 5, 4)
#define GET_RX_STATUS_DESC_PAGGR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 14, 1)
#define GET_RX_STATUS_DESC_FAGGR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 15, 1)
#define GET_RX_STATUS_DESC_A1_FIT(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 16, 4)
#define GET_RX_STATUS_DESC_A2_FIT(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 20, 4)
#define GET_RX_STATUS_DESC_PAM(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 24, 1)
#define GET_RX_STATUS_DESC_PWR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 25, 1)
#define GET_RX_STATUS_DESC_MORE_DATA(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 26, 1)
#define GET_RX_STATUS_DESC_MORE_FRAG(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 27, 1)
#define GET_RX_STATUS_DESC_TYPE(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 28, 2)
#define GET_RX_STATUS_DESC_MC(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 30, 1)
#define GET_RX_STATUS_DESC_BC(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 4, 31, 1)
/* DWORD 2 */
#define SET_RX_STATUS_DESC_SEQ(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 0, 12, __val)
#define SET_RX_STATUS_DESC_FRAG(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 12, 4, __val)
#define SET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 16, 8, __val)
#define SET_RX_STATUS_DESC_NEXT_IND(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val)
#define GET_RX_STATUS_DESC_SEQ(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 8, 0, 12)
#define GET_RX_STATUS_DESC_FRAG(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 8, 12, 4)
#define GET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 8, 16, 8)
#define GET_RX_STATUS_DESC_NEXT_IND(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 8, 30, 1)
/* DWORD 3 */
#define SET_RX_STATUS_DESC_RX_MCS(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 0, 6, __val)
#define SET_RX_STATUS_DESC_RX_HT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 6, 1, __val)
#define SET_RX_STATUS_DESC_AMSDU(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 7, 1, __val)
#define SET_RX_STATUS_DESC_SPLCP(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 8, 1, __val)
#define SET_RX_STATUS_DESC_BW(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 9, 1, __val)
#define SET_RX_STATUS_DESC_HTC(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 10, 1, __val)
#define SET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 11, 1, __val)
#define SET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 12, 1, __val)
#define SET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 13, 1, __val)
#define SET_RX_STATUS_DESC_HWPC_ERR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 14, 1, __val)
#define SET_RX_STATUS_DESC_HWPC_IND(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 15, 1, __val)
#define SET_RX_STATUS_DESC_IV0(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 12, 16, 16, __val)
#define GET_RX_STATUS_DESC_RX_MCS(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 0, 6)
#define GET_RX_STATUS_DESC_RX_HT(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 6, 1)
#define GET_RX_STATUS_DESC_AMSDU(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 7, 1)
#define GET_RX_STATUS_DESC_SPLCP(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 8, 1)
#define GET_RX_STATUS_DESC_BW(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 9, 1)
#define GET_RX_STATUS_DESC_HTC(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 10, 1)
#define GET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 11, 1)
#define GET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 12, 1)
#define GET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 13, 1)
#define GET_RX_STATUS_DESC_HWPC_ERR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 14, 1)
#define GET_RX_STATUS_DESC_HWPC_IND(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 15, 1)
#define GET_RX_STATUS_DESC_IV0(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 12, 16, 16)
/* DWORD 4 */
#define SET_RX_STATUS_DESC_IV1(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 16, 0, 32, __val)
#define GET_RX_STATUS_DESC_IV1(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 16, 0, 32)
/* DWORD 5 */
#define SET_RX_STATUS_DESC_TSFL(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 20, 0, 32, __val)
#define GET_RX_STATUS_DESC_TSFL(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 20, 0, 32)
/* DWORD 6 */
#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \
SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \
GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \
GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)
enum rf_optype {
RF_OP_BY_SW_3WIRE = 0,
RF_OP_BY_FW,
RF_OP_MAX
};
enum ic_inferiority {
IC_INFERIORITY_A = 0,
IC_INFERIORITY_B = 1,
};
enum fwcmd_iotype {
/* For DIG DM */
FW_CMD_DIG_ENABLE = 0,
FW_CMD_DIG_DISABLE = 1,
FW_CMD_DIG_HALT = 2,
FW_CMD_DIG_RESUME = 3,
/* For High Power DM */
FW_CMD_HIGH_PWR_ENABLE = 4,
FW_CMD_HIGH_PWR_DISABLE = 5,
/* For Rate adaptive DM */
FW_CMD_RA_RESET = 6,
FW_CMD_RA_ACTIVE = 7,
FW_CMD_RA_REFRESH_N = 8,
FW_CMD_RA_REFRESH_BG = 9,
FW_CMD_RA_INIT = 10,
/* For FW supported IQK */
FW_CMD_IQK_INIT = 11,
/* Tx power tracking switch,
* MP driver only */
FW_CMD_TXPWR_TRACK_ENABLE = 12,
/* Tx power tracking switch,
* MP driver only */
FW_CMD_TXPWR_TRACK_DISABLE = 13,
/* Tx power tracking with thermal
* indication, for Normal driver */
FW_CMD_TXPWR_TRACK_THERMAL = 14,
FW_CMD_PAUSE_DM_BY_SCAN = 15,
FW_CMD_RESUME_DM_BY_SCAN = 16,
FW_CMD_RA_REFRESH_N_COMB = 17,
FW_CMD_RA_REFRESH_BG_COMB = 18,
FW_CMD_ANTENNA_SW_ENABLE = 19,
FW_CMD_ANTENNA_SW_DISABLE = 20,
/* Tx Status report for CCX from FW */
FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21,
/* Indifate firmware that driver
* enters LPS, For PS-Poll issue */
FW_CMD_LPS_ENTER = 22,
/* Indicate firmware that driver
* leave LPS*/
FW_CMD_LPS_LEAVE = 23,
/* Set DIG mode to signal strength */
FW_CMD_DIG_MODE_SS = 24,
/* Set DIG mode to false alarm. */
FW_CMD_DIG_MODE_FA = 25,
FW_CMD_ADD_A2_ENTRY = 26,
FW_CMD_CTRL_DM_BY_DRIVER = 27,
FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28,
FW_CMD_PAPE_CONTROL = 29,
FW_CMD_IQK_ENABLE = 30,
};
/* Driver info contain PHY status
* and other variabel size info
* PHY Status content as below
*/
struct rx_fwinfo {
/* DWORD 0 */
u8 gain_trsw[4];
/* DWORD 1 */
u8 pwdb_all;
u8 cfosho[4];
/* DWORD 2 */
u8 cfotail[4];
/* DWORD 3 */
s8 rxevm[2];
s8 rxsnr[4];
/* DWORD 4 */
u8 pdsnr[2];
/* DWORD 5 */
u8 csi_current[2];
u8 csi_target[2];
/* DWORD 6 */
u8 sigevm;
u8 max_ex_pwr;
u8 ex_intf_flag:1;
u8 sgi_en:1;
u8 rxsc:2;
u8 reserve:4;
};
struct phy_sts_cck_8192s_t {
u8 adc_pwdb_x[4];
u8 sq_rpt;
u8 cck_agc_rpt;
};
#endif

View file

@ -0,0 +1,742 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../wifi.h"
#include "../base.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "dm.h"
#include "fw.h"
static const u32 edca_setting_dl[PEER_MAX] = {
0xa44f, /* 0 UNKNOWN */
0x5ea44f, /* 1 REALTEK_90 */
0x5ea44f, /* 2 REALTEK_92SE */
0xa630, /* 3 BROAD */
0xa44f, /* 4 RAL */
0xa630, /* 5 ATH */
0xa630, /* 6 CISCO */
0xa42b, /* 7 MARV */
};
static const u32 edca_setting_dl_gmode[PEER_MAX] = {
0x4322, /* 0 UNKNOWN */
0xa44f, /* 1 REALTEK_90 */
0x5ea44f, /* 2 REALTEK_92SE */
0xa42b, /* 3 BROAD */
0x5e4322, /* 4 RAL */
0x4322, /* 5 ATH */
0xa430, /* 6 CISCO */
0x5ea44f, /* 7 MARV */
};
static const u32 edca_setting_ul[PEER_MAX] = {
0x5e4322, /* 0 UNKNOWN */
0xa44f, /* 1 REALTEK_90 */
0x5ea44f, /* 2 REALTEK_92SE */
0x5ea322, /* 3 BROAD */
0x5ea422, /* 4 RAL */
0x5ea322, /* 5 ATH */
0x3ea44f, /* 6 CISCO */
0x5ea44f, /* 7 MARV */
};
static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
static u64 last_txok_cnt;
static u64 last_rxok_cnt;
u64 cur_txok_cnt = 0;
u64 cur_rxok_cnt = 0;
u32 edca_be_ul = edca_setting_ul[mac->vendor];
u32 edca_be_dl = edca_setting_dl[mac->vendor];
u32 edca_gmode = edca_setting_dl_gmode[mac->vendor];
if (mac->link_state != MAC80211_LINKED) {
rtlpriv->dm.current_turbo_edca = false;
goto dm_checkedcaturbo_exit;
}
if ((!rtlpriv->dm.is_any_nonbepkts) &&
(!rtlpriv->dm.disable_framebursting)) {
cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
if (rtlpriv->phy.rf_type == RF_1T2R) {
if (cur_txok_cnt > 4 * cur_rxok_cnt) {
/* Uplink TP is present. */
if (rtlpriv->dm.is_cur_rdlstate ||
!rtlpriv->dm.current_turbo_edca) {
rtl_write_dword(rtlpriv, EDCAPARA_BE,
edca_be_ul);
rtlpriv->dm.is_cur_rdlstate = false;
}
} else {/* Balance TP is present. */
if (!rtlpriv->dm.is_cur_rdlstate ||
!rtlpriv->dm.current_turbo_edca) {
if (mac->mode == WIRELESS_MODE_G ||
mac->mode == WIRELESS_MODE_B)
rtl_write_dword(rtlpriv,
EDCAPARA_BE,
edca_gmode);
else
rtl_write_dword(rtlpriv,
EDCAPARA_BE,
edca_be_dl);
rtlpriv->dm.is_cur_rdlstate = true;
}
}
rtlpriv->dm.current_turbo_edca = true;
} else {
if (cur_rxok_cnt > 4 * cur_txok_cnt) {
if (!rtlpriv->dm.is_cur_rdlstate ||
!rtlpriv->dm.current_turbo_edca) {
if (mac->mode == WIRELESS_MODE_G ||
mac->mode == WIRELESS_MODE_B)
rtl_write_dword(rtlpriv,
EDCAPARA_BE,
edca_gmode);
else
rtl_write_dword(rtlpriv,
EDCAPARA_BE,
edca_be_dl);
rtlpriv->dm.is_cur_rdlstate = true;
}
} else {
if (rtlpriv->dm.is_cur_rdlstate ||
!rtlpriv->dm.current_turbo_edca) {
rtl_write_dword(rtlpriv, EDCAPARA_BE,
edca_be_ul);
rtlpriv->dm.is_cur_rdlstate = false;
}
}
rtlpriv->dm.current_turbo_edca = true;
}
} else {
if (rtlpriv->dm.current_turbo_edca) {
u8 tmp = AC0_BE;
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
&tmp);
rtlpriv->dm.current_turbo_edca = false;
}
}
dm_checkedcaturbo_exit:
rtlpriv->dm.is_any_nonbepkts = false;
last_txok_cnt = rtlpriv->stats.txbytesunicast;
last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
}
static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 thermalvalue = 0;
u32 fw_cmd = 0;
rtlpriv->dm.txpower_trackinginit = true;
thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n",
thermalvalue,
rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter);
if (thermalvalue) {
rtlpriv->dm.thermalvalue = thermalvalue;
if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
} else {
fw_cmd = (FW_TXPWR_TRACK_THERMAL |
(rtlpriv->efuse.thermalmeter[0] << 8) |
(thermalvalue << 16));
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Write to FW Thermal Val = 0x%x\n", fw_cmd);
rtl_write_dword(rtlpriv, WFM5, fw_cmd);
rtl92s_phy_chk_fwcmd_iodone(hw);
}
}
rtlpriv->dm.txpowercount = 0;
}
static void _rtl92s_dm_check_txpowertracking_thermalmeter(
struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
static u8 tm_trigger;
u8 tx_power_checkcnt = 5;
/* 2T2R TP issue */
if (rtlphy->rf_type == RF_2T2R)
return;
if (!rtlpriv->dm.txpower_tracking)
return;
if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) {
rtlpriv->dm.txpowercount++;
return;
}
if (!tm_trigger) {
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER,
RFREG_OFFSET_MASK, 0x60);
tm_trigger = 1;
} else {
_rtl92s_dm_txpowertracking_callback_thermalmeter(hw);
tm_trigger = 0;
}
}
static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rate_adaptive *ra = &(rtlpriv->ra);
struct ieee80211_sta *sta = NULL;
u32 low_rssi_thresh = 0;
u32 middle_rssi_thresh = 0;
u32 high_rssi_thresh = 0;
if (is_hal_stop(rtlhal))
return;
if (!rtlpriv->dm.useramask)
return;
if (hal_get_firmwareversion(rtlpriv) >= 61 &&
!rtlpriv->dm.inform_fw_driverctrldm) {
rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
rtlpriv->dm.inform_fw_driverctrldm = true;
}
if ((mac->link_state == MAC80211_LINKED) &&
(mac->opmode == NL80211_IFTYPE_STATION)) {
switch (ra->pre_ratr_state) {
case DM_RATR_STA_HIGH:
high_rssi_thresh = 40;
middle_rssi_thresh = 30;
low_rssi_thresh = 20;
break;
case DM_RATR_STA_MIDDLE:
high_rssi_thresh = 44;
middle_rssi_thresh = 30;
low_rssi_thresh = 20;
break;
case DM_RATR_STA_LOW:
high_rssi_thresh = 44;
middle_rssi_thresh = 34;
low_rssi_thresh = 20;
break;
case DM_RATR_STA_ULTRALOW:
high_rssi_thresh = 44;
middle_rssi_thresh = 34;
low_rssi_thresh = 24;
break;
default:
high_rssi_thresh = 44;
middle_rssi_thresh = 34;
low_rssi_thresh = 24;
break;
}
if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_HIGH;
} else if (rtlpriv->dm.undec_sm_pwdb >
(long)middle_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
} else if (rtlpriv->dm.undec_sm_pwdb >
(long)low_rssi_thresh) {
ra->ratr_state = DM_RATR_STA_LOW;
} else {
ra->ratr_state = DM_RATR_STA_ULTRALOW;
}
if (ra->pre_ratr_state != ra->ratr_state) {
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
ra->pre_ratr_state, ra->ratr_state);
rcu_read_lock();
sta = rtl_find_sta(hw, mac->bssid);
if (sta)
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
ra->ratr_state);
rcu_read_unlock();
ra->pre_ratr_state = ra->ratr_state;
}
}
}
static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
bool current_mrc;
bool enable_mrc = true;
long tmpentry_maxpwdb = 0;
u8 rssi_a = 0;
u8 rssi_b = 0;
if (is_hal_stop(rtlhal))
return;
if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R))
return;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
if (mac->link_state >= MAC80211_LINKED) {
if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) {
rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
}
}
/* MRC settings would NOT affect TP on Wireless B mode. */
if (mac->mode != WIRELESS_MODE_B) {
if ((rssi_a == 0) && (rssi_b == 0)) {
enable_mrc = true;
} else if (rssi_b > 30) {
/* Turn on B-Path */
enable_mrc = true;
} else if (rssi_b < 5) {
/* Turn off B-path */
enable_mrc = false;
/* Take care of RSSI differentiation. */
} else if (rssi_a > 15 && (rssi_a >= rssi_b)) {
if ((rssi_a - rssi_b) > 15)
/* Turn off B-path */
enable_mrc = false;
else if ((rssi_a - rssi_b) < 10)
/* Turn on B-Path */
enable_mrc = true;
else
enable_mrc = current_mrc;
} else {
/* Turn on B-Path */
enable_mrc = true;
}
}
/* Update MRC settings if needed. */
if (enable_mrc != current_mrc)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC,
(u8 *)&enable_mrc);
}
void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.current_turbo_edca = false;
rtlpriv->dm.is_any_nonbepkts = false;
rtlpriv->dm.is_cur_rdlstate = false;
}
static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rate_adaptive *ra = &(rtlpriv->ra);
ra->ratr_state = DM_RATR_STA_MAX;
ra->pre_ratr_state = DM_RATR_STA_MAX;
if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER &&
hal_get_firmwareversion(rtlpriv) >= 60)
rtlpriv->dm.useramask = true;
else
rtlpriv->dm.useramask = false;
rtlpriv->dm.useramask = false;
rtlpriv->dm.inform_fw_driverctrldm = false;
}
static void _rtl92s_dm_init_txpowertracking_thermalmeter(
struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.txpower_tracking = true;
rtlpriv->dm.txpowercount = 0;
rtlpriv->dm.txpower_trackinginit = false;
}
static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
u32 ret_value;
ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail +
falsealm_cnt->cnt_mcs_fail;
/* read CCK false alarm */
ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD);
falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff);
falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
falsealm_cnt->cnt_cck_fail;
}
static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *digtable = &rtlpriv->dm_digtable;
struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
if (falsealm_cnt->cnt_all > digtable->fa_highthresh) {
if ((digtable->back_val - 6) <
digtable->backoffval_range_min)
digtable->back_val = digtable->backoffval_range_min;
else
digtable->back_val -= 6;
} else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) {
if ((digtable->back_val + 6) >
digtable->backoffval_range_max)
digtable->back_val =
digtable->backoffval_range_max;
else
digtable->back_val += 6;
}
}
static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *digtable = &rtlpriv->dm_digtable;
struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
static u8 initialized, force_write;
u8 initial_gain = 0;
if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) ||
(digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) {
if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) {
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
if (digtable->backoff_enable_flag)
rtl92s_backoff_enable_flag(hw);
else
digtable->back_val = DM_DIG_BACKOFF;
if ((digtable->rssi_val + 10 - digtable->back_val) >
digtable->rx_gain_max)
digtable->cur_igvalue =
digtable->rx_gain_max;
else if ((digtable->rssi_val + 10 - digtable->back_val)
< digtable->rx_gain_min)
digtable->cur_igvalue =
digtable->rx_gain_min;
else
digtable->cur_igvalue = digtable->rssi_val + 10
- digtable->back_val;
if (falsealm_cnt->cnt_all > 10000)
digtable->cur_igvalue =
(digtable->cur_igvalue > 0x33) ?
digtable->cur_igvalue : 0x33;
if (falsealm_cnt->cnt_all > 16000)
digtable->cur_igvalue =
digtable->rx_gain_max;
/* connected -> connected or disconnected -> disconnected */
} else {
/* Firmware control DIG, do nothing in driver dm */
return;
}
/* disconnected -> connected or connected ->
* disconnected or beforeconnect->(dis)connected */
} else {
/* Enable FW DIG */
digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
digtable->back_val = DM_DIG_BACKOFF;
digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0];
digtable->pre_igvalue = 0;
return;
}
/* Forced writing to prevent from fw-dig overwriting. */
if (digtable->pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
MASKBYTE0))
force_write = 1;
if ((digtable->pre_igvalue != digtable->cur_igvalue) ||
!initialized || force_write) {
/* Disable FW DIG */
rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE);
initial_gain = (u8)digtable->cur_igvalue;
/* Set initial gain. */
rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain);
rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain);
digtable->pre_igvalue = digtable->cur_igvalue;
initialized = 1;
force_write = 0;
}
}
static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dig = &rtlpriv->dm_digtable;
if (rtlpriv->mac80211.act_scanning)
return;
/* Decide the current status and if modify initial gain or not */
if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
dig->cur_sta_cstate = DIG_STA_CONNECT;
else
dig->cur_sta_cstate = DIG_STA_DISCONNECT;
dig->rssi_val = rtlpriv->dm.undec_sm_pwdb;
/* Change dig mode to rssi */
if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) {
if (dig->dig_twoport_algorithm ==
DIG_TWO_PORT_ALGO_FALSE_ALARM) {
dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS);
}
}
_rtl92s_dm_false_alarm_counter_statistics(hw);
_rtl92s_dm_initial_gain_sta_beforeconnect(hw);
dig->pre_sta_cstate = dig->cur_sta_cstate;
}
static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct dig_t *digtable = &rtlpriv->dm_digtable;
/* 2T2R TP issue */
if (rtlphy->rf_type == RF_2T2R)
return;
if (!rtlpriv->dm.dm_initialgain_enable)
return;
if (digtable->dig_enable_flag == false)
return;
_rtl92s_dm_ctrl_initgain_bytwoport(hw);
}
static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
long undec_sm_pwdb;
long txpwr_threshold_lv1, txpwr_threshold_lv2;
/* 2T2R TP issue */
if (rtlphy->rf_type == RF_2T2R)
return;
if (!rtlpriv->dm.dynamic_txpower_enable ||
rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
return;
}
if ((mac->link_state < MAC80211_LINKED) &&
(rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
"Not connected to any\n");
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
return;
}
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
undec_sm_pwdb);
} else {
undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
undec_sm_pwdb);
}
} else {
undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n",
undec_sm_pwdb);
}
txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1;
if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
else if (undec_sm_pwdb >= txpwr_threshold_lv2)
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) &&
(undec_sm_pwdb >= txpwr_threshold_lv1))
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3))
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
rtl92s_phy_set_txpower(hw, rtlphy->current_channel);
rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
}
static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *digtable = &rtlpriv->dm_digtable;
/* Disable DIG scheme now.*/
digtable->dig_enable_flag = true;
digtable->backoff_enable_flag = true;
if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) &&
(hal_get_firmwareversion(rtlpriv) >= 0x3c))
digtable->dig_algorithm = DIG_ALGO_BY_TOW_PORT;
else
digtable->dig_algorithm =
DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM;
digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
/* off=by real rssi value, on=by digtable->rssi_val for new dig */
digtable->dig_dbgmode = DM_DBG_OFF;
digtable->dig_slgorithm_switch = 0;
/* 2007/10/04 MH Define init gain threshol. */
digtable->dig_state = DM_STA_DIG_MAX;
digtable->dig_highpwrstate = DM_STA_DIG_MAX;
digtable->cur_sta_cstate = DIG_STA_DISCONNECT;
digtable->pre_sta_cstate = DIG_STA_DISCONNECT;
digtable->cur_ap_cstate = DIG_AP_DISCONNECT;
digtable->pre_ap_cstate = DIG_AP_DISCONNECT;
digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
digtable->rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
digtable->rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
/* for dig debug rssi value */
digtable->rssi_val = 50;
digtable->back_val = DM_DIG_BACKOFF;
digtable->rx_gain_max = DM_DIG_MAX;
digtable->rx_gain_min = DM_DIG_MIN;
digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX;
digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN;
}
static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
if ((hal_get_firmwareversion(rtlpriv) >= 60) &&
(rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER))
rtlpriv->dm.dynamic_txpower_enable = true;
else
rtlpriv->dm.dynamic_txpower_enable = false;
rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
}
void rtl92s_dm_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
rtlpriv->dm.undec_sm_pwdb = -1;
_rtl92s_dm_init_dynamic_txpower(hw);
rtl92s_dm_init_edca_turbo(hw);
_rtl92s_dm_init_rate_adaptive_mask(hw);
_rtl92s_dm_init_txpowertracking_thermalmeter(hw);
_rtl92s_dm_init_dig(hw);
rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE);
}
void rtl92s_dm_watchdog(struct ieee80211_hw *hw)
{
_rtl92s_dm_check_edca_turbo(hw);
_rtl92s_dm_check_txpowertracking_thermalmeter(hw);
_rtl92s_dm_ctrl_initgain_byrssi(hw);
_rtl92s_dm_dynamic_txpower(hw);
_rtl92s_dm_refresh_rateadaptive_mask(hw);
_rtl92s_dm_switch_baseband_mrc(hw);
}

View file

@ -0,0 +1,120 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL_92S_DM_H__
#define __RTL_92S_DM_H__
enum dm_dig_alg {
DIG_ALGO_BY_FALSE_ALARM = 0,
DIG_ALGO_BY_RSSI = 1,
DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2,
DIG_ALGO_BY_TOW_PORT = 3,
DIG_ALGO_MAX
};
enum dm_dig_two_port_alg {
DIG_TWO_PORT_ALGO_RSSI = 0,
DIG_TWO_PORT_ALGO_FALSE_ALARM = 1,
};
enum dm_dig_dbg {
DM_DBG_OFF = 0,
DM_DBG_ON = 1,
DM_DBG_MAX
};
enum dm_dig_sta {
DM_STA_DIG_OFF = 0,
DM_STA_DIG_ON,
DM_STA_DIG_MAX
};
enum dm_dig_connect {
DIG_STA_DISCONNECT = 0,
DIG_STA_CONNECT = 1,
DIG_STA_BEFORE_CONNECT = 2,
DIG_AP_DISCONNECT = 3,
DIG_AP_CONNECT = 4,
DIG_AP_ADD_STATION = 5,
DIG_CONNECT_MAX
};
enum dm_dig_ext_port_alg {
DIG_EXT_PORT_STAGE_0 = 0,
DIG_EXT_PORT_STAGE_1 = 1,
DIG_EXT_PORT_STAGE_2 = 2,
DIG_EXT_PORT_STAGE_3 = 3,
DIG_EXT_PORT_STAGE_MAX = 4,
};
enum dm_ratr_sta {
DM_RATR_STA_HIGH = 0,
DM_RATR_STA_MIDDLEHIGH = 1,
DM_RATR_STA_MIDDLE = 2,
DM_RATR_STA_MIDDLELOW = 3,
DM_RATR_STA_LOW = 4,
DM_RATR_STA_ULTRALOW = 5,
DM_RATR_STA_MAX
};
#define DM_TYPE_BYFW 0
#define DM_TYPE_BYDRIVER 1
#define TX_HIGH_PWR_LEVEL_NORMAL 0
#define TX_HIGH_PWR_LEVEL_LEVEL1 1
#define TX_HIGH_PWR_LEVEL_LEVEL2 2
#define HAL_DM_DIG_DISABLE BIT(0) /* Disable Dig */
#define HAL_DM_HIPWR_DISABLE BIT(1) /* Disable High Power */
#define TX_HIGHPWR_LEVEL_NORMAL 0
#define TX_HIGHPWR_LEVEL_NORMAL1 1
#define TX_HIGHPWR_LEVEL_NORMAL2 2
#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
#define DM_DIG_THRESH_HIGH 40
#define DM_DIG_THRESH_LOW 35
#define DM_FALSEALARM_THRESH_LOW 40
#define DM_FALSEALARM_THRESH_HIGH 1000
#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
#define DM_DIG_HIGH_PWR_THRESH_LOW 70
#define DM_DIG_BACKOFF 12
#define DM_DIG_MAX 0x3e
#define DM_DIG_MIN 0x1c
#define DM_DIG_MIN_Netcore 0x12
#define DM_DIG_BACKOFF_MAX 12
#define DM_DIG_BACKOFF_MIN -4
void rtl92s_dm_watchdog(struct ieee80211_hw *hw);
void rtl92s_dm_init(struct ieee80211_hw *hw);
void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw);
#endif

View file

@ -0,0 +1,652 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../wifi.h"
#include "../pci.h"
#include "../base.h"
#include "reg.h"
#include "def.h"
#include "fw.h"
static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_write_dword(rtlpriv, RQPN, 0xffffffff);
rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff);
rtl_write_byte(rtlpriv, RQPN + 8, 0xff);
rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80);
}
static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 ichecktime = 200;
u16 tmpu2b;
u8 tmpu1b, cpustatus = 0;
_rtl92s_fw_set_rqpn(hw);
/* Enable CPU. */
tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR);
/* AFE source */
rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL));
tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN));
/* Polling IMEM Ready after CPU has refilled. */
do {
cpustatus = rtl_read_byte(rtlpriv, TCR);
if (cpustatus & IMEM_RDY) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"IMEM Ready after CPU has refilled\n");
break;
}
udelay(100);
} while (ichecktime--);
if (!(cpustatus & IMEM_RDY))
return false;
return true;
}
static enum fw_status _rtl92s_firmware_get_nextstatus(
enum fw_status fw_currentstatus)
{
enum fw_status next_fwstatus = 0;
switch (fw_currentstatus) {
case FW_STATUS_INIT:
next_fwstatus = FW_STATUS_LOAD_IMEM;
break;
case FW_STATUS_LOAD_IMEM:
next_fwstatus = FW_STATUS_LOAD_EMEM;
break;
case FW_STATUS_LOAD_EMEM:
next_fwstatus = FW_STATUS_LOAD_DMEM;
break;
case FW_STATUS_LOAD_DMEM:
next_fwstatus = FW_STATUS_READY;
break;
default:
break;
}
return next_fwstatus;
}
static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
switch (rtlphy->rf_type) {
case RF_1T1R:
return 0x11;
case RF_1T2R:
return 0x12;
case RF_2T2R:
return 0x22;
default:
RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown RF type(%x)\n",
rtlphy->rf_type);
break;
}
return 0x22;
}
static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw,
struct fw_priv *pfw_priv)
{
/* Update RF types for RATR settings. */
pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw);
}
static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw,
struct sk_buff *skb, u8 last)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring;
struct rtl_tx_desc *pdesc;
unsigned long flags;
u8 idx = 0;
ring = &rtlpci->tx_ring[TXCMD_QUEUE];
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
pdesc = &ring->desc[idx];
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
__skb_queue_tail(&ring->queue, skb);
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
return true;
}
static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
u8 *code_virtual_address, u32 buffer_len)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct sk_buff *skb;
struct rtl_tcb_desc *tcb_desc;
unsigned char *seg_ptr;
u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE;
u16 frag_length, frag_offset = 0;
u16 extra_descoffset = 0;
u8 last_inipkt = 0;
_rtl92s_fw_set_rqpn(hw);
if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Size over FIRMWARE_CODE_SIZE!\n");
return false;
}
extra_descoffset = 0;
do {
if ((buffer_len - frag_offset) > frag_threshold) {
frag_length = frag_threshold + extra_descoffset;
} else {
frag_length = (u16)(buffer_len - frag_offset +
extra_descoffset);
last_inipkt = 1;
}
/* Allocate skb buffer to contain firmware */
/* info and tx descriptor info. */
skb = dev_alloc_skb(frag_length);
if (!skb)
return false;
skb_reserve(skb, extra_descoffset);
seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length -
extra_descoffset));
memcpy(seg_ptr, code_virtual_address + frag_offset,
(u32)(frag_length - extra_descoffset));
tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT;
tcb_desc->last_inipkt = last_inipkt;
_rtl92s_cmd_send_packet(hw, skb, last_inipkt);
frag_offset += (frag_length - extra_descoffset);
} while (frag_offset < buffer_len);
rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ);
return true ;
}
static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw,
u8 loadfw_status)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware;
u32 tmpu4b;
u8 cpustatus = 0;
short pollingcnt = 1000;
bool rtstatus = true;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"LoadStaus(%d)\n", loadfw_status);
firmware->fwstatus = (enum fw_status)loadfw_status;
switch (loadfw_status) {
case FW_STATUS_LOAD_IMEM:
/* Polling IMEM code done. */
do {
cpustatus = rtl_read_byte(rtlpriv, TCR);
if (cpustatus & IMEM_CODE_DONE)
break;
udelay(5);
} while (pollingcnt--);
if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n",
cpustatus);
goto status_check_fail;
}
break;
case FW_STATUS_LOAD_EMEM:
/* Check Put Code OK and Turn On CPU */
/* Polling EMEM code done. */
do {
cpustatus = rtl_read_byte(rtlpriv, TCR);
if (cpustatus & EMEM_CODE_DONE)
break;
udelay(5);
} while (pollingcnt--);
if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n",
cpustatus);
goto status_check_fail;
}
/* Turn On CPU */
rtstatus = _rtl92s_firmware_enable_cpu(hw);
if (!rtstatus) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Enable CPU fail!\n");
goto status_check_fail;
}
break;
case FW_STATUS_LOAD_DMEM:
/* Polling DMEM code done */
do {
cpustatus = rtl_read_byte(rtlpriv, TCR);
if (cpustatus & DMEM_CODE_DONE)
break;
udelay(5);
} while (pollingcnt--);
if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Polling DMEM code done fail ! cpustatus(%#x)\n",
cpustatus);
goto status_check_fail;
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"DMEM code download success, cpustatus(%#x)\n",
cpustatus);
/* Prevent Delay too much and being scheduled out */
/* Polling Load Firmware ready */
pollingcnt = 2000;
do {
cpustatus = rtl_read_byte(rtlpriv, TCR);
if (cpustatus & FWRDY)
break;
udelay(40);
} while (pollingcnt--);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Polling Load Firmware ready, cpustatus(%x)\n",
cpustatus);
if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) ||
(pollingcnt <= 0)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Polling Load Firmware ready fail ! cpustatus(%x)\n",
cpustatus);
goto status_check_fail;
}
/* If right here, we can set TCR/RCR to desired value */
/* and config MAC lookback mode to normal mode */
tmpu4b = rtl_read_dword(rtlpriv, TCR);
rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV)));
tmpu4b = rtl_read_dword(rtlpriv, RCR);
rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS |
RCR_APP_ICV | RCR_APP_MIC));
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Current RCR settings(%#x)\n", tmpu4b);
/* Set to normal mode. */
rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL);
break;
default:
RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
"Unknown status check!\n");
rtstatus = false;
break;
}
status_check_fail:
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"loadfw_status(%d), rtstatus(%x)\n",
loadfw_status, rtstatus);
return rtstatus;
}
int rtl92s_download_fw(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rt_firmware *firmware = NULL;
struct fw_hdr *pfwheader;
struct fw_priv *pfw_priv = NULL;
u8 *puc_mappedfile = NULL;
u32 ul_filelength = 0;
u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;
u8 fwstatus = FW_STATUS_INIT;
bool rtstatus = true;
if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
return 1;
firmware = (struct rt_firmware *)rtlhal->pfirmware;
firmware->fwstatus = FW_STATUS_INIT;
puc_mappedfile = firmware->sz_fw_tmpbuffer;
/* 1. Retrieve FW header. */
firmware->pfwheader = (struct fw_hdr *) puc_mappedfile;
pfwheader = firmware->pfwheader;
firmware->firmwareversion = byte(pfwheader->version, 0);
firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
pfwheader->signature,
pfwheader->version, pfwheader->dmem_size,
pfwheader->img_imem_size, pfwheader->img_sram_size);
/* 2. Retrieve IMEM image. */
if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size >
sizeof(firmware->fw_imem))) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"memory for data image is less than IMEM required\n");
goto fail;
} else {
puc_mappedfile += fwhdr_size;
memcpy(firmware->fw_imem, puc_mappedfile,
pfwheader->img_imem_size);
firmware->fw_imem_len = pfwheader->img_imem_size;
}
/* 3. Retriecve EMEM image. */
if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"memory for data image is less than EMEM required\n");
goto fail;
} else {
puc_mappedfile += firmware->fw_imem_len;
memcpy(firmware->fw_emem, puc_mappedfile,
pfwheader->img_sram_size);
firmware->fw_emem_len = pfwheader->img_sram_size;
}
/* 4. download fw now */
fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus);
while (fwstatus != FW_STATUS_READY) {
/* Image buffer redirection. */
switch (fwstatus) {
case FW_STATUS_LOAD_IMEM:
puc_mappedfile = firmware->fw_imem;
ul_filelength = firmware->fw_imem_len;
break;
case FW_STATUS_LOAD_EMEM:
puc_mappedfile = firmware->fw_emem;
ul_filelength = firmware->fw_emem_len;
break;
case FW_STATUS_LOAD_DMEM:
/* Partial update the content of header private. */
pfwheader = firmware->pfwheader;
pfw_priv = &pfwheader->fwpriv;
_rtl92s_firmwareheader_priveupdate(hw, pfw_priv);
puc_mappedfile = (u8 *)(firmware->pfwheader) +
RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
ul_filelength = fwhdr_size -
RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Unexpected Download step!!\n");
goto fail;
}
/* <2> Download image file */
rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile,
ul_filelength);
if (!rtstatus) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "fail!\n");
goto fail;
}
/* <3> Check whether load FW process is ready */
rtstatus = _rtl92s_firmware_checkready(hw, fwstatus);
if (!rtstatus) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "fail!\n");
goto fail;
}
fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus);
}
return rtstatus;
fail:
return 0;
}
static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen,
u32 cmd_num, u32 *pelement_id, u32 *pcmd_len,
u8 **pcmb_buffer, u8 *cmd_start_seq)
{
u32 totallen = 0, len = 0, tx_desclen = 0;
u32 pre_continueoffset = 0;
u8 *ph2c_buffer;
u8 i = 0;
do {
/* 8 - Byte aligment */
len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8);
/* Buffer length is not enough */
if (h2cbufferlen < totallen + len + tx_desclen)
break;
/* Clear content */
ph2c_buffer = (u8 *)skb_put(skb, (u32)len);
memset((ph2c_buffer + totallen + tx_desclen), 0, len);
/* CMD len */
SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
0, 16, pcmd_len[i]);
/* CMD ID */
SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
16, 8, pelement_id[i]);
/* CMD Sequence */
*cmd_start_seq = *cmd_start_seq % 0x80;
SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen),
24, 7, *cmd_start_seq);
++*cmd_start_seq;
/* Copy memory */
memcpy((ph2c_buffer + totallen + tx_desclen +
H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]);
/* CMD continue */
/* set the continue in prevoius cmd. */
if (i < cmd_num - 1)
SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset),
31, 1, 1);
pre_continueoffset = totallen;
totallen += len;
} while (++i < cmd_num);
return totallen;
}
static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len)
{
u32 totallen = 0, len = 0, tx_desclen = 0;
u8 i = 0;
do {
/* 8 - Byte aligment */
len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8);
/* Buffer length is not enough */
if (h2cbufferlen < totallen + len + tx_desclen)
break;
totallen += len;
} while (++i < cmd_num);
return totallen + tx_desclen;
}
static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
u8 *pcmd_buffer)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_tcb_desc *cb_desc;
struct sk_buff *skb;
u32 element_id = 0;
u32 cmd_len = 0;
u32 len;
switch (h2c_cmd) {
case FW_H2C_SETPWRMODE:
element_id = H2C_SETPWRMODE_CMD ;
cmd_len = sizeof(struct h2c_set_pwrmode_parm);
break;
case FW_H2C_JOINBSSRPT:
element_id = H2C_JOINBSSRPT_CMD;
cmd_len = sizeof(struct h2c_joinbss_rpt_parm);
break;
case FW_H2C_WOWLAN_UPDATE_GTK:
element_id = H2C_WOWLAN_UPDATE_GTK_CMD;
cmd_len = sizeof(struct h2c_wpa_two_way_parm);
break;
case FW_H2C_WOWLAN_UPDATE_IV:
element_id = H2C_WOWLAN_UPDATE_IV_CMD;
cmd_len = sizeof(unsigned long long);
break;
case FW_H2C_WOWLAN_OFFLOAD:
element_id = H2C_WOWLAN_FW_OFFLOAD;
cmd_len = sizeof(u8);
break;
default:
break;
}
len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
skb = dev_alloc_skb(len);
if (!skb)
return false;
cb_desc = (struct rtl_tcb_desc *)(skb->cb);
cb_desc->queue_index = TXCMD_QUEUE;
cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
cb_desc->last_inipkt = false;
_rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id,
&cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq);
_rtl92s_cmd_send_packet(hw, skb, false);
rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE);
return true;
}
void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct h2c_set_pwrmode_parm pwrmode;
u16 max_wakeup_period = 0;
pwrmode.mode = Mode;
pwrmode.flag_low_traffic_en = 0;
pwrmode.flag_lpnav_en = 0;
pwrmode.flag_rf_low_snr_en = 0;
pwrmode.flag_dps_en = 0;
pwrmode.bcn_rx_en = 0;
pwrmode.bcn_to = 0;
SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16,
mac->vif->bss_conf.beacon_int);
pwrmode.app_itv = 0;
pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl;
pwrmode.smart_ps = 1;
pwrmode.bcn_pass_period = 10;
/* Set beacon pass count */
if (pwrmode.mode == FW_PS_MIN_MODE)
max_wakeup_period = mac->vif->bss_conf.beacon_int;
else if (pwrmode.mode == FW_PS_MAX_MODE)
max_wakeup_period = mac->vif->bss_conf.beacon_int *
mac->vif->bss_conf.dtim_period;
if (max_wakeup_period >= 500)
pwrmode.bcn_pass_cnt = 1;
else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500))
pwrmode.bcn_pass_cnt = 2;
else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300))
pwrmode.bcn_pass_cnt = 3;
else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200))
pwrmode.bcn_pass_cnt = 5;
else
pwrmode.bcn_pass_cnt = 1;
_rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode);
}
void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw,
u8 mstatus, u8 ps_qosinfo)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct h2c_joinbss_rpt_parm joinbss_rpt;
joinbss_rpt.opmode = mstatus;
joinbss_rpt.ps_qos_info = ps_qosinfo;
joinbss_rpt.bssid[0] = mac->bssid[0];
joinbss_rpt.bssid[1] = mac->bssid[1];
joinbss_rpt.bssid[2] = mac->bssid[2];
joinbss_rpt.bssid[3] = mac->bssid[3];
joinbss_rpt.bssid[4] = mac->bssid[4];
joinbss_rpt.bssid[5] = mac->bssid[5];
SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16,
mac->vif->bss_conf.beacon_int);
SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id);
_rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt);
}

View file

@ -0,0 +1,375 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __REALTEK_FIRMWARE92S_H__
#define __REALTEK_FIRMWARE92S_H__
#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000
#define RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE 90000
#define RTL8190_CPU_START_OFFSET 0x80
/* Firmware Local buffer size. 64k */
#define MAX_FIRMWARE_CODE_SIZE 0xFF00
#define RT_8192S_FIRMWARE_HDR_SIZE 80
#define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32
/* support till 64 bit bus width OS */
#define MAX_DEV_ADDR_SIZE 8
#define MAX_FIRMWARE_INFORMATION_SIZE 32
#define MAX_802_11_HEADER_LENGTH (40 + \
MAX_FIRMWARE_INFORMATION_SIZE)
#define ENCRYPTION_MAX_OVERHEAD 128
#define MAX_FRAGMENT_COUNT 8
#define MAX_TRANSMIT_BUFFER_SIZE (1600 + \
(MAX_802_11_HEADER_LENGTH + \
ENCRYPTION_MAX_OVERHEAD) *\
MAX_FRAGMENT_COUNT)
#define H2C_TX_CMD_HDR_LEN 8
/* The following DM control code are for Reg0x364, */
#define FW_DIG_ENABLE_CTL BIT(0)
#define FW_HIGH_PWR_ENABLE_CTL BIT(1)
#define FW_SS_CTL BIT(2)
#define FW_RA_INIT_CTL BIT(3)
#define FW_RA_BG_CTL BIT(4)
#define FW_RA_N_CTL BIT(5)
#define FW_PWR_TRK_CTL BIT(6)
#define FW_IQK_CTL BIT(7)
#define FW_FA_CTL BIT(8)
#define FW_DRIVER_CTRL_DM_CTL BIT(9)
#define FW_PAPE_CTL_BY_SW_HW BIT(10)
#define FW_DISABLE_ALL_DM 0
#define FW_PWR_TRK_PARAM_CLR 0x0000ffff
#define FW_RA_PARAM_CLR 0xffff0000
enum desc_packet_type {
DESC_PACKET_TYPE_INIT = 0,
DESC_PACKET_TYPE_NORMAL = 1,
};
/* 8-bytes alignment required */
struct fw_priv {
/* --- long word 0 ---- */
/* 0x12: CE product, 0x92: IT product */
u8 signature_0;
/* 0x87: CE product, 0x81: IT product */
u8 signature_1;
/* 0x81: PCI-AP, 01:PCIe, 02: 92S-U,
* 0x82: USB-AP, 0x12: 72S-U, 03:SDIO */
u8 hci_sel;
/* the same value as reigster value */
u8 chip_version;
/* customer ID low byte */
u8 customer_id_0;
/* customer ID high byte */
u8 customer_id_1;
/* 0x11: 1T1R, 0x12: 1T2R,
* 0x92: 1T2R turbo, 0x22: 2T2R */
u8 rf_config;
/* 4: 4EP, 6: 6EP, 11: 11EP */
u8 usb_ep_num;
/* --- long word 1 ---- */
/* regulatory class bit map 0 */
u8 regulatory_class_0;
/* regulatory class bit map 1 */
u8 regulatory_class_1;
/* regulatory class bit map 2 */
u8 regulatory_class_2;
/* regulatory class bit map 3 */
u8 regulatory_class_3;
/* 0:SWSI, 1:HWSI, 2:HWPI */
u8 rfintfs;
u8 def_nettype;
u8 rsvd010;
u8 rsvd011;
/* --- long word 2 ---- */
/* 0x00: normal, 0x03: MACLBK, 0x01: PHYLBK */
u8 lbk_mode;
/* 1: for MP use, 0: for normal
* driver (to be discussed) */
u8 mp_mode;
u8 rsvd020;
u8 rsvd021;
u8 rsvd022;
u8 rsvd023;
u8 rsvd024;
u8 rsvd025;
/* --- long word 3 ---- */
/* QoS enable */
u8 qos_en;
/* 40MHz BW enable */
/* 4181 convert AMSDU to AMPDU, 0: disable */
u8 bw_40mhz_en;
u8 amsdu2ampdu_en;
/* 11n AMPDU enable */
u8 ampdu_en;
/* FW offloads, 0: driver handles */
u8 rate_control_offload;
/* FW offloads, 0: driver handles */
u8 aggregation_offload;
u8 rsvd030;
u8 rsvd031;
/* --- long word 4 ---- */
/* 1. FW offloads, 0: driver handles */
u8 beacon_offload;
/* 2. FW offloads, 0: driver handles */
u8 mlme_offload;
/* 3. FW offloads, 0: driver handles */
u8 hwpc_offload;
/* 4. FW offloads, 0: driver handles */
u8 tcp_checksum_offload;
/* 5. FW offloads, 0: driver handles */
u8 tcp_offload;
/* 6. FW offloads, 0: driver handles */
u8 ps_control_offload;
/* 7. FW offloads, 0: driver handles */
u8 wwlan_offload;
u8 rsvd040;
/* --- long word 5 ---- */
/* tcp tx packet length low byte */
u8 tcp_tx_frame_len_L;
/* tcp tx packet length high byte */
u8 tcp_tx_frame_len_H;
/* tcp rx packet length low byte */
u8 tcp_rx_frame_len_L;
/* tcp rx packet length high byte */
u8 tcp_rx_frame_len_H;
u8 rsvd050;
u8 rsvd051;
u8 rsvd052;
u8 rsvd053;
};
/* 8-byte alinment required */
struct fw_hdr {
/* --- LONG WORD 0 ---- */
u16 signature;
/* 0x8000 ~ 0x8FFF for FPGA version,
* 0x0000 ~ 0x7FFF for ASIC version, */
u16 version;
/* define the size of boot loader */
u32 dmem_size;
/* --- LONG WORD 1 ---- */
/* define the size of FW in IMEM */
u32 img_imem_size;
/* define the size of FW in SRAM */
u32 img_sram_size;
/* --- LONG WORD 2 ---- */
/* define the size of DMEM variable */
u32 fw_priv_size;
u32 rsvd0;
/* --- LONG WORD 3 ---- */
u32 rsvd1;
u32 rsvd2;
struct fw_priv fwpriv;
} ;
enum fw_status {
FW_STATUS_INIT = 0,
FW_STATUS_LOAD_IMEM = 1,
FW_STATUS_LOAD_EMEM = 2,
FW_STATUS_LOAD_DMEM = 3,
FW_STATUS_READY = 4,
};
struct rt_firmware {
struct fw_hdr *pfwheader;
enum fw_status fwstatus;
u16 firmwareversion;
u8 fw_imem[RTL8190_MAX_FIRMWARE_CODE_SIZE];
u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE];
u32 fw_imem_len;
u32 fw_emem_len;
u8 sz_fw_tmpbuffer[RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE];
u32 sz_fw_tmpbufferlen;
u16 cmdpacket_fragthresold;
};
struct h2c_set_pwrmode_parm {
u8 mode;
u8 flag_low_traffic_en;
u8 flag_lpnav_en;
u8 flag_rf_low_snr_en;
/* 1: dps, 0: 32k */
u8 flag_dps_en;
u8 bcn_rx_en;
u8 bcn_pass_cnt;
/* beacon TO (ms). ¡§=0¡¨ no limit. */
u8 bcn_to;
u16 bcn_itv;
/* only for VOIP mode. */
u8 app_itv;
u8 awake_bcn_itvl;
u8 smart_ps;
/* unit: 100 ms */
u8 bcn_pass_period;
};
struct h2c_joinbss_rpt_parm {
u8 opmode;
u8 ps_qos_info;
u8 bssid[6];
u16 bcnitv;
u16 aid;
} ;
struct h2c_wpa_ptk {
/* EAPOL-Key Key Confirmation Key (KCK) */
u8 kck[16];
/* EAPOL-Key Key Encryption Key (KEK) */
u8 kek[16];
/* Temporal Key 1 (TK1) */
u8 tk1[16];
union {
/* Temporal Key 2 (TK2) */
u8 tk2[16];
struct {
u8 tx_mic_key[8];
u8 rx_mic_key[8];
} athu;
} u;
};
struct h2c_wpa_two_way_parm {
/* algorithm TKIP or AES */
u8 pairwise_en_alg;
u8 group_en_alg;
struct h2c_wpa_ptk wpa_ptk_value;
} ;
enum h2c_cmd {
FW_H2C_SETPWRMODE = 0,
FW_H2C_JOINBSSRPT = 1,
FW_H2C_WOWLAN_UPDATE_GTK = 2,
FW_H2C_WOWLAN_UPDATE_IV = 3,
FW_H2C_WOWLAN_OFFLOAD = 4,
};
enum fw_h2c_cmd {
H2C_READ_MACREG_CMD, /*0*/
H2C_WRITE_MACREG_CMD,
H2C_READBB_CMD,
H2C_WRITEBB_CMD,
H2C_READRF_CMD,
H2C_WRITERF_CMD, /*5*/
H2C_READ_EEPROM_CMD,
H2C_WRITE_EEPROM_CMD,
H2C_READ_EFUSE_CMD,
H2C_WRITE_EFUSE_CMD,
H2C_READ_CAM_CMD, /*10*/
H2C_WRITE_CAM_CMD,
H2C_SETBCNITV_CMD,
H2C_SETMBIDCFG_CMD,
H2C_JOINBSS_CMD,
H2C_DISCONNECT_CMD, /*15*/
H2C_CREATEBSS_CMD,
H2C_SETOPMode_CMD,
H2C_SITESURVEY_CMD,
H2C_SETAUTH_CMD,
H2C_SETKEY_CMD, /*20*/
H2C_SETSTAKEY_CMD,
H2C_SETASSOCSTA_CMD,
H2C_DELASSOCSTA_CMD,
H2C_SETSTAPWRSTATE_CMD,
H2C_SETBASICRATE_CMD, /*25*/
H2C_GETBASICRATE_CMD,
H2C_SETDATARATE_CMD,
H2C_GETDATARATE_CMD,
H2C_SETPHYINFO_CMD,
H2C_GETPHYINFO_CMD, /*30*/
H2C_SETPHY_CMD,
H2C_GETPHY_CMD,
H2C_READRSSI_CMD,
H2C_READGAIN_CMD,
H2C_SETATIM_CMD, /*35*/
H2C_SETPWRMODE_CMD,
H2C_JOINBSSRPT_CMD,
H2C_SETRATABLE_CMD,
H2C_GETRATABLE_CMD,
H2C_GETCCXREPORT_CMD, /*40*/
H2C_GETDTMREPORT_CMD,
H2C_GETTXRATESTATICS_CMD,
H2C_SETUSBSUSPEND_CMD,
H2C_SETH2CLBK_CMD,
H2C_TMP1, /*45*/
H2C_WOWLAN_UPDATE_GTK_CMD,
H2C_WOWLAN_FW_OFFLOAD,
H2C_TMP2,
H2C_TMP3,
H2C_WOWLAN_UPDATE_IV_CMD, /*50*/
H2C_TMP4,
};
/* The following macros are used for FW
* CMD map and parameter updated. */
#define FW_CMD_IO_CLR(rtlpriv, _Bit) \
do { \
udelay(1000); \
rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \
} while (0)
#define FW_CMD_IO_UPDATE(rtlpriv, _val) \
rtlpriv->rtlhal.fwcmd_iomap = _val;
#define FW_CMD_IO_SET(rtlpriv, _val) \
do { \
rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \
FW_CMD_IO_UPDATE(rtlpriv, _val); \
} while (0)
#define FW_CMD_PARA_SET(rtlpriv, _val) \
do { \
rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \
rtlpriv->rtlhal.fwcmd_ioparam = _val; \
} while (0)
#define FW_CMD_IO_QUERY(rtlpriv) \
(u16)(rtlpriv->rtlhal.fwcmd_iomap)
#define FW_CMD_IO_PARA_QUERY(rtlpriv) \
((u32)(rtlpriv->rtlhal.fwcmd_ioparam))
int rtl92s_download_fw(struct ieee80211_hw *hw);
void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw,
u8 mstatus, u8 ps_qosinfo);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,78 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __REALTEK_PCI92SE_HW_H__
#define __REALTEK_PCI92SE_HW_H__
#define MSR_LINK_MANAGED 2
#define MSR_LINK_NONE 0
#define MSR_LINK_SHIFT 0
#define MSR_LINK_ADHOC 1
#define MSR_LINK_MASTER 3
enum WIRELESS_NETWORK_TYPE {
WIRELESS_11B = 1,
WIRELESS_11G = 2,
WIRELESS_11A = 4,
WIRELESS_11N = 8
};
void rtl92se_get_hw_reg(struct ieee80211_hw *hw,
u8 variable, u8 *val);
void rtl92se_read_eeprom_info(struct ieee80211_hw *hw);
void rtl92se_interrupt_recognized(struct ieee80211_hw *hw,
u32 *inta, u32 *intb);
int rtl92se_hw_init(struct ieee80211_hw *hw);
void rtl92se_card_disable(struct ieee80211_hw *hw);
void rtl92se_enable_interrupt(struct ieee80211_hw *hw);
void rtl92se_disable_interrupt(struct ieee80211_hw *hw);
int rtl92se_set_network_type(struct ieee80211_hw *hw,
enum nl80211_iftype type);
void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr);
void rtl92se_set_qos(struct ieee80211_hw *hw, int aci);
void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw);
void rtl92se_set_beacon_interval(struct ieee80211_hw *hw);
void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw,
u32 add_msr, u32 rm_msr);
void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable,
u8 *val);
void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u8 rssi_level);
void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw);
bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw,
u8 *valid);
void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw);
void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw);
void rtl92se_set_key(struct ieee80211_hw *hw,
u32 key_index, u8 *macaddr, bool is_group,
u8 enc_algo, bool is_wepkey, bool clear_all);
void rtl92se_suspend(struct ieee80211_hw *hw);
void rtl92se_resume(struct ieee80211_hw *hw);
#endif

View file

@ -0,0 +1,151 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../wifi.h"
#include "../pci.h"
#include "reg.h"
#include "led.h"
static void _rtl92se_init_led(struct ieee80211_hw *hw,
struct rtl_led *pled, enum rtl_led_pin ledpin)
{
pled->hw = hw;
pled->ledpin = ledpin;
pled->ledon = false;
}
void rtl92se_init_sw_leds(struct ieee80211_hw *hw)
{
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
_rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
_rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
}
void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
LEDCFG, pled->ledpin);
ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
switch (pled->ledpin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0xf0);
break;
case LED_PIN_LED1:
rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
pled->ledon = true;
}
void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
{
struct rtl_priv *rtlpriv;
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
u8 ledcfg;
rtlpriv = rtl_priv(hw);
if (!rtlpriv || rtlpriv->max_fw_size)
return;
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
LEDCFG, pled->ledpin);
ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
switch (pled->ledpin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
ledcfg &= 0xf0;
if (pcipriv->ledctl.led_opendrain)
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));
else
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
break;
case LED_PIN_LED1:
ledcfg &= 0x0f;
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
pled->ledon = false;
}
static void _rtl92se_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
rtl92se_sw_led_on(hw, pLed0);
break;
case LED_CTL_POWER_OFF:
rtl92se_sw_led_off(hw, pLed0);
break;
default:
break;
}
}
void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
(ledaction == LED_CTL_TX ||
ledaction == LED_CTL_RX ||
ledaction == LED_CTL_SITE_SURVEY ||
ledaction == LED_CTL_LINK ||
ledaction == LED_CTL_NO_LINK ||
ledaction == LED_CTL_START_TO_LINK ||
ledaction == LED_CTL_POWER_ON)) {
return;
}
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction);
_rtl92se_sw_led_control(hw, ledaction);
}

View file

@ -0,0 +1,37 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __REALTEK_PCI92SE_LED_H__
#define __REALTEK_PCI92SE_LED_H__
void rtl92se_init_sw_leds(struct ieee80211_hw *hw);
void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,102 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92S_PHY_H__
#define __RTL92S_PHY_H__
#define MAX_TXPWR_IDX_NMODE_92S 63
#define MAX_DOZE_WAITING_TIMES_9x 64
/* Channel switch:The size of
* command tables for switch channel */
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
#define MAX_POSTCMD_CNT 16
#define RF90_PATH_MAX 4
#define RF6052_MAX_PATH 2
enum version_8192s {
VERSION_8192S_ACUT,
VERSION_8192S_BCUT,
VERSION_8192S_CCUT
};
enum swchnlcmd_id {
CMDID_END,
CMDID_SET_TXPOWEROWER_LEVEL,
CMDID_BBREGWRITE10,
CMDID_WRITEPORT_ULONG,
CMDID_WRITEPORT_USHORT,
CMDID_WRITEPORT_UCHAR,
CMDID_RF_WRITEREG,
};
struct swchnlcmd {
enum swchnlcmd_id cmdid;
u32 para1;
u32 para2;
u32 msdelay;
};
enum baseband_config_type {
/* Radio Path A */
BASEBAND_CONFIG_PHY_REG = 0,
/* Radio Path B */
BASEBAND_CONFIG_AGC_TAB = 1,
};
#define hal_get_firmwareversion(rtlpriv) \
(((struct rt_firmware *)(rtlpriv->rtlhal.pfirmware))->firmwareversion)
u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
u32 data);
void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
u32 regaddr, u32 bitmask);
void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
u32 regaddr, u32 bitmask, u32 data);
void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,
enum nl80211_channel_type ch_type);
u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw);
bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,
enum rf_pwrstate rfpower_state);
bool rtl92s_phy_mac_config(struct ieee80211_hw *hw);
void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw);
bool rtl92s_phy_bb_config(struct ieee80211_hw *hw);
bool rtl92s_phy_rf_config(struct ieee80211_hw *hw);
void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel);
bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fwcmd_io);
void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw);
void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval);
u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) ;
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,535 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../wifi.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "rf.h"
#include "dm.h"
static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel,
u8 chnl, u32 *ofdmbase, u32 *mcsbase,
u8 *p_final_pwridx)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u32 pwrbase0, pwrbase1;
u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
u8 i, pwrlevel[4];
for (i = 0; i < 2; i++)
pwrlevel[i] = p_pwrlevel[i];
/* We only care about the path A for legacy. */
if (rtlefuse->eeprom_version < 2) {
pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf);
} else {
legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff
[RF90_PATH_A][chnl - 1];
/* For legacy OFDM, tx pwr always > HT OFDM pwr.
* We do not care Path B
* legacy OFDM pwr diff. NO BB register
* to notify HW. */
pwrbase0 = pwrlevel[0] + legacy_pwrdiff;
}
pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) |
pwrbase0;
*ofdmbase = pwrbase0;
/* MCS rates */
if (rtlefuse->eeprom_version >= 2) {
/* Check HT20 to HT40 diff */
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
for (i = 0; i < 2; i++) {
/* rf-A, rf-B */
/* HT 20<->40 pwr diff */
ht20_pwrdiff = rtlefuse->txpwr_ht20diff
[i][chnl - 1];
if (ht20_pwrdiff < 8) /* 0~+7 */
pwrlevel[i] += ht20_pwrdiff;
else /* index8-15=-8~-1 */
pwrlevel[i] -= (16 - ht20_pwrdiff);
}
}
}
/* use index of rf-A */
pwrbase1 = pwrlevel[0];
pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) |
pwrbase1;
*mcsbase = pwrbase1;
/* The following is for Antenna
* diff from Ant-B to Ant-A */
p_final_pwridx[0] = pwrlevel[0];
p_final_pwridx[1] = pwrlevel[1];
switch (rtlefuse->eeprom_regulatory) {
case 3:
/* The following is for calculation
* of the power diff for Ant-B to Ant-A. */
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
p_final_pwridx[0] += rtlefuse->pwrgroup_ht40
[RF90_PATH_A][
chnl - 1];
p_final_pwridx[1] += rtlefuse->pwrgroup_ht40
[RF90_PATH_B][
chnl - 1];
} else {
p_final_pwridx[0] += rtlefuse->pwrgroup_ht20
[RF90_PATH_A][
chnl - 1];
p_final_pwridx[1] += rtlefuse->pwrgroup_ht20
[RF90_PATH_B][
chnl - 1];
}
break;
default:
break;
}
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
p_final_pwridx[0], p_final_pwridx[1]);
} else {
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
p_final_pwridx[0], p_final_pwridx[1]);
}
}
static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw,
u8 *p_final_pwridx)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_phy *rtlphy = &(rtlpriv->phy);
char ant_pwr_diff = 0;
u32 u4reg_val = 0;
if (rtlphy->rf_type == RF_2T2R) {
ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0];
/* range is from 7~-8,
* index = 0x0~0xf */
if (ant_pwr_diff > 7)
ant_pwr_diff = 7;
if (ant_pwr_diff < -8)
ant_pwr_diff = -8;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Antenna Diff from RF-B to RF-A = %d (0x%x)\n",
ant_pwr_diff, ant_pwr_diff & 0xf);
ant_pwr_diff &= 0xf;
}
/* Antenna TX power difference */
rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */
rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */
rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff); /* RF-B */
u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 |
rtlefuse->antenna_txpwdiff[1] << 4 |
rtlefuse->antenna_txpwdiff[0];
rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC),
u4reg_val);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n",
RFPGA0_TXGAINSTAGE, u4reg_val);
}
static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
u8 chnl, u8 index,
u32 pwrbase0,
u32 pwrbase1,
u32 *p_outwrite_val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 i, chnlgroup, pwrdiff_limit[4];
u32 writeval, customer_limit;
/* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
switch (rtlefuse->eeprom_regulatory) {
case 0:
/* Realtek better performance increase power diff
* defined by Realtek for large power */
chnlgroup = 0;
writeval = rtlphy->mcs_offset[chnlgroup][index] +
((index < 2) ? pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"RTK better performance, writeval = 0x%x\n", writeval);
break;
case 1:
/* Realtek regulatory increase power diff defined
* by Realtek for regulatory */
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
writeval = ((index < 2) ? pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Realtek regulatory, 40MHz, writeval = 0x%x\n",
writeval);
} else {
if (rtlphy->pwrgroup_cnt == 1)
chnlgroup = 0;
if (rtlphy->pwrgroup_cnt >= 3) {
if (chnl <= 3)
chnlgroup = 0;
else if (chnl >= 4 && chnl <= 8)
chnlgroup = 1;
else if (chnl > 8)
chnlgroup = 2;
if (rtlphy->pwrgroup_cnt == 4)
chnlgroup++;
}
writeval = rtlphy->mcs_offset[chnlgroup][index]
+ ((index < 2) ?
pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Realtek regulatory, 20MHz, writeval = 0x%x\n",
writeval);
}
break;
case 2:
/* Better regulatory don't increase any power diff */
writeval = ((index < 2) ? pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Better regulatory, writeval = 0x%x\n", writeval);
break;
case 3:
/* Customer defined power diff. increase power diff
defined by customer. */
chnlgroup = 0;
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"customer's limit, 40MHz = 0x%x\n",
rtlefuse->pwrgroup_ht40
[RF90_PATH_A][chnl - 1]);
} else {
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"customer's limit, 20MHz = 0x%x\n",
rtlefuse->pwrgroup_ht20
[RF90_PATH_A][chnl - 1]);
}
for (i = 0; i < 4; i++) {
pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset
[chnlgroup][index] & (0x7f << (i * 8)))
>> (i * 8));
if (rtlphy->current_chan_bw ==
HT_CHANNEL_WIDTH_20_40) {
if (pwrdiff_limit[i] >
rtlefuse->pwrgroup_ht40
[RF90_PATH_A][chnl - 1]) {
pwrdiff_limit[i] =
rtlefuse->pwrgroup_ht40
[RF90_PATH_A][chnl - 1];
}
} else {
if (pwrdiff_limit[i] >
rtlefuse->pwrgroup_ht20
[RF90_PATH_A][chnl - 1]) {
pwrdiff_limit[i] =
rtlefuse->pwrgroup_ht20
[RF90_PATH_A][chnl - 1];
}
}
}
customer_limit = (pwrdiff_limit[3] << 24) |
(pwrdiff_limit[2] << 16) |
(pwrdiff_limit[1] << 8) |
(pwrdiff_limit[0]);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Customer's limit = 0x%x\n", customer_limit);
writeval = customer_limit + ((index < 2) ?
pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Customer, writeval = 0x%x\n", writeval);
break;
default:
chnlgroup = 0;
writeval = rtlphy->mcs_offset[chnlgroup][index] +
((index < 2) ? pwrbase0 : pwrbase1);
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"RTK better performance, writeval = 0x%x\n", writeval);
break;
}
if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1)
writeval = 0x10101010;
else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TX_HIGH_PWR_LEVEL_LEVEL2)
writeval = 0x0;
*p_outwrite_val = writeval;
}
static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw,
u8 index, u32 val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
u8 i, rfa_pwr[4];
u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0;
u32 writeval = val;
/* If path A and Path B coexist, we must limit Path A tx power.
* Protect Path B pwr over or under flow. We need to calculate
* upper and lower bound of path A tx power. */
if (rtlphy->rf_type == RF_2T2R) {
rf_pwr_diff = rtlefuse->antenna_txpwdiff[0];
/* Diff=-8~-1 */
if (rf_pwr_diff >= 8) {
/* Prevent underflow!! */
rfa_lower_bound = 0x10 - rf_pwr_diff;
/* if (rf_pwr_diff >= 0) Diff = 0-7 */
} else {
rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff;
}
}
for (i = 0; i < 4; i++) {
rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8));
if (rfa_pwr[i] > RF6052_MAX_TX_PWR)
rfa_pwr[i] = RF6052_MAX_TX_PWR;
/* If path A and Path B coexist, we must limit Path A tx power.
* Protect Path B pwr over or under flow. We need to calculate
* upper and lower bound of path A tx power. */
if (rtlphy->rf_type == RF_2T2R) {
/* Diff=-8~-1 */
if (rf_pwr_diff >= 8) {
/* Prevent underflow!! */
if (rfa_pwr[i] < rfa_lower_bound)
rfa_pwr[i] = rfa_lower_bound;
/* Diff = 0-7 */
} else if (rf_pwr_diff >= 1) {
/* Prevent overflow */
if (rfa_pwr[i] > rfa_upper_bound)
rfa_pwr[i] = rfa_upper_bound;
}
}
}
writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) |
rfa_pwr[0];
rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval);
}
void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw,
u8 *p_pwrlevel, u8 chnl)
{
u32 writeval, pwrbase0, pwrbase1;
u8 index = 0;
u8 finalpwr_idx[4];
_rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1,
&finalpwr_idx[0]);
_rtl92s_set_antennadiff(hw, &finalpwr_idx[0]);
for (index = 0; index < 6; index++) {
_rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index,
pwrbase0, pwrbase1, &writeval);
_rtl92s_write_ofdm_powerreg(hw, index, writeval);
}
}
void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u32 txagc = 0;
bool dont_inc_cck_or_turboscanoff = false;
if (((rtlefuse->eeprom_version >= 2) &&
(rtlefuse->txpwr_safetyflag == 1)) ||
((rtlefuse->eeprom_version >= 2) &&
(rtlefuse->eeprom_regulatory != 0)))
dont_inc_cck_or_turboscanoff = true;
if (mac->act_scanning) {
txagc = 0x3f;
if (dont_inc_cck_or_turboscanoff)
txagc = pwrlevel;
} else {
txagc = pwrlevel;
if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TX_HIGH_PWR_LEVEL_LEVEL1)
txagc = 0x10;
else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TX_HIGH_PWR_LEVEL_LEVEL2)
txagc = 0x0;
}
if (txagc > RF6052_MAX_TX_PWR)
txagc = RF6052_MAX_TX_PWR;
rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc);
}
bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 u4reg_val = 0;
u8 rfpath;
bool rtstatus = true;
struct bb_reg_def *pphyreg;
/* Initialize RF */
for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
pphyreg = &rtlphy->phyreg_def[rfpath];
/* Store original RFENV control type */
switch (rfpath) {
case RF90_PATH_A:
case RF90_PATH_C:
u4reg_val = rtl92s_phy_query_bb_reg(hw,
pphyreg->rfintfs,
BRFSI_RFENV);
break;
case RF90_PATH_B:
case RF90_PATH_D:
u4reg_val = rtl92s_phy_query_bb_reg(hw,
pphyreg->rfintfs,
BRFSI_RFENV << 16);
break;
}
/* Set RF_ENV enable */
rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe,
BRFSI_RFENV << 16, 0x1);
/* Set RF_ENV output high */
rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
/* Set bit number of Address and Data for RF register */
rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2,
B3WIRE_ADDRESSLENGTH, 0x0);
rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2,
B3WIRE_DATALENGTH, 0x0);
/* Initialize RF fom connfiguration file */
switch (rfpath) {
case RF90_PATH_A:
rtstatus = rtl92s_phy_config_rf(hw,
(enum radio_path)rfpath);
break;
case RF90_PATH_B:
rtstatus = rtl92s_phy_config_rf(hw,
(enum radio_path)rfpath);
break;
case RF90_PATH_C:
break;
case RF90_PATH_D:
break;
}
/* Restore RFENV control type */
switch (rfpath) {
case RF90_PATH_A:
case RF90_PATH_C:
rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV,
u4reg_val);
break;
case RF90_PATH_B:
case RF90_PATH_D:
rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs,
BRFSI_RFENV << 16,
u4reg_val);
break;
}
if (!rtstatus) {
pr_err("Radio[%d] Fail!!\n", rfpath);
goto fail;
}
}
return rtstatus;
fail:
return rtstatus;
}
void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
switch (bandwidth) {
case HT_CHANNEL_WIDTH_20:
rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0xfffff3ff) | 0x0400);
rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
rtlphy->rfreg_chnlval[0]);
break;
case HT_CHANNEL_WIDTH_20_40:
rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0xfffff3ff));
rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
rtlphy->rfreg_chnlval[0]);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"unknown bandwidth: %#X\n", bandwidth);
break;
}
}

View file

@ -0,0 +1,43 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __INC_RTL92S_RF_H
#define __INC_RTL92S_RF_H
#define RF6052_MAX_TX_PWR 0x3F
void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
u8 bandwidth);
bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) ;
void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw,
u8 powerlevel);
void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw,
u8 *p_pwrlevel, u8 chnl);
#endif

View file

@ -0,0 +1,442 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../wifi.h"
#include "../core.h"
#include "../base.h"
#include "../pci.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "dm.h"
#include "fw.h"
#include "hw.h"
#include "sw.h"
#include "trx.h"
#include "led.h"
#include <linux/module.h>
static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
/*close ASPM for AMD defaultly */
rtlpci->const_amdpci_aspm = 0;
/* ASPM PS mode.
* 0 - Disable ASPM,
* 1 - Enable ASPM without Clock Req,
* 2 - Enable ASPM with Clock Req,
* 3 - Alwyas Enable ASPM with Clock Req,
* 4 - Always Enable ASPM without Clock Req.
* set defult to RTL8192CE:3 RTL8192E:2
* */
rtlpci->const_pci_aspm = 2;
/*Setting for PCI-E device */
rtlpci->const_devicepci_aspm_setting = 0x03;
/*Setting for PCI-E bridge */
rtlpci->const_hostpci_aspm_setting = 0x02;
/* In Hw/Sw Radio Off situation.
* 0 - Default,
* 1 - From ASPM setting without low Mac Pwr,
* 2 - From ASPM setting with low Mac Pwr,
* 3 - Bus D3
* set default to RTL8192CE:0 RTL8192SE:2
*/
rtlpci->const_hwsw_rfoff_d3 = 2;
/* This setting works for those device with
* backdoor ASPM setting such as EPHY setting.
* 0 - Not support ASPM,
* 1 - Support ASPM,
* 2 - According to chipset.
*/
rtlpci->const_support_pciaspm = 2;
}
static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
{
struct ieee80211_hw *hw = context;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rt_firmware *pfirmware = NULL;
RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
"Firmware callback routine entered!\n");
complete(&rtlpriv->firmware_loading_complete);
if (!firmware) {
pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
rtlpriv->max_fw_size = 0;
return;
}
if (firmware->size > rtlpriv->max_fw_size) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Firmware is too big!\n");
rtlpriv->max_fw_size = 0;
release_firmware(firmware);
return;
}
pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
pfirmware->sz_fw_tmpbufferlen = firmware->size;
release_firmware(firmware);
}
static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
int err = 0;
u16 earlyrxthreshold = 7;
rtlpriv->dm.dm_initialgain_enable = true;
rtlpriv->dm.dm_flag = 0;
rtlpriv->dm.disable_framebursting = false;
rtlpriv->dm.thermalvalue = 0;
rtlpriv->dm.useramask = true;
/* compatible 5G band 91se just 2.4G band & smsp */
rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G;
rtlpriv->rtlhal.bandset = BAND_ON_2_4G;
rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY;
rtlpci->transmit_config = 0;
rtlpci->receive_config =
RCR_APPFCS |
RCR_APWRMGT |
/*RCR_ADD3 |*/
RCR_AMF |
RCR_ADF |
RCR_APP_MIC |
RCR_APP_ICV |
RCR_AICV |
/* Accept ICV error, CRC32 Error */
RCR_ACRC32 |
RCR_AB |
/* Accept Broadcast, Multicast */
RCR_AM |
/* Accept Physical match */
RCR_APM |
/* Accept Destination Address packets */
/*RCR_AAP |*/
RCR_APP_PHYST_STAFF |
/* Accept PHY status */
RCR_APP_PHYST_RXFF |
(earlyrxthreshold << RCR_FIFO_OFFSET);
rtlpci->irq_mask[0] = (u32)
(IMR_ROK |
IMR_VODOK |
IMR_VIDOK |
IMR_BEDOK |
IMR_BKDOK |
IMR_HCCADOK |
IMR_MGNTDOK |
IMR_COMDOK |
IMR_HIGHDOK |
IMR_BDOK |
IMR_RXCMDOK |
/*IMR_TIMEOUT0 |*/
IMR_RDU |
IMR_RXFOVW |
IMR_BCNINT
/*| IMR_TXFOVW*/
/*| IMR_TBDOK |
IMR_TBDER*/);
rtlpci->irq_mask[1] = (u32) 0;
rtlpci->shortretry_limit = 0x30;
rtlpci->longretry_limit = 0x30;
rtlpci->first_init = true;
/* for debug level */
rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
/* for LPS & IPS */
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
if (!rtlpriv->psc.inactiveps)
pr_info("Power Save off (module option)\n");
if (!rtlpriv->psc.fwctrl_lps)
pr_info("FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
* set const_support_pciaspm = 0 */
rtl92s_init_aspm_vars(hw);
if (rtlpriv->psc.reg_fwctrl_lps == 1)
rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
else if (rtlpriv->psc.reg_fwctrl_lps == 2)
rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
else if (rtlpriv->psc.reg_fwctrl_lps == 3)
rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
/* for firmware buf */
rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware));
if (!rtlpriv->rtlhal.pfirmware)
return 1;
rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
sizeof(struct fw_hdr);
pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
"Loading firmware %s\n", rtlpriv->cfg->fw_name);
/* request fw */
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
rtlpriv->io.dev, GFP_KERNEL, hw,
rtl92se_fw_cb);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Failed to request firmware!\n");
return 1;
}
return err;
}
static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->rtlhal.pfirmware) {
vfree(rtlpriv->rtlhal.pfirmware);
rtlpriv->rtlhal.pfirmware = NULL;
}
}
static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
u16 index)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
u8 *entry = (u8 *)(&ring->desc[ring->idx]);
u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN);
if (own)
return false;
return true;
}
static struct rtl_hal_ops rtl8192se_hal_ops = {
.init_sw_vars = rtl92s_init_sw_vars,
.deinit_sw_vars = rtl92s_deinit_sw_vars,
.read_eeprom_info = rtl92se_read_eeprom_info,
.interrupt_recognized = rtl92se_interrupt_recognized,
.hw_init = rtl92se_hw_init,
.hw_disable = rtl92se_card_disable,
.hw_suspend = rtl92se_suspend,
.hw_resume = rtl92se_resume,
.enable_interrupt = rtl92se_enable_interrupt,
.disable_interrupt = rtl92se_disable_interrupt,
.set_network_type = rtl92se_set_network_type,
.set_chk_bssid = rtl92se_set_check_bssid,
.set_qos = rtl92se_set_qos,
.set_bcn_reg = rtl92se_set_beacon_related_registers,
.set_bcn_intv = rtl92se_set_beacon_interval,
.update_interrupt_mask = rtl92se_update_interrupt_mask,
.get_hw_reg = rtl92se_get_hw_reg,
.set_hw_reg = rtl92se_set_hw_reg,
.update_rate_tbl = rtl92se_update_hal_rate_tbl,
.fill_tx_desc = rtl92se_tx_fill_desc,
.fill_tx_cmddesc = rtl92se_tx_fill_cmddesc,
.query_rx_desc = rtl92se_rx_query_desc,
.set_channel_access = rtl92se_update_channel_access_setting,
.radio_onoff_checking = rtl92se_gpio_radio_on_off_checking,
.set_bw_mode = rtl92s_phy_set_bw_mode,
.switch_channel = rtl92s_phy_sw_chnl,
.dm_watchdog = rtl92s_dm_watchdog,
.scan_operation_backup = rtl92s_phy_scan_operation_backup,
.set_rf_power_state = rtl92s_phy_set_rf_power_state,
.led_control = rtl92se_led_control,
.set_desc = rtl92se_set_desc,
.get_desc = rtl92se_get_desc,
.is_tx_desc_closed = rtl92se_is_tx_desc_closed,
.tx_polling = rtl92se_tx_polling,
.enable_hw_sec = rtl92se_enable_hw_security_config,
.set_key = rtl92se_set_key,
.init_sw_leds = rtl92se_init_sw_leds,
.get_bbreg = rtl92s_phy_query_bb_reg,
.set_bbreg = rtl92s_phy_set_bb_reg,
.get_rfreg = rtl92s_phy_query_rf_reg,
.set_rfreg = rtl92s_phy_set_rf_reg,
.get_btc_status = rtl_btc_status_false,
};
static struct rtl_mod_params rtl92se_mod_params = {
.sw_crypto = false,
.inactiveps = true,
.swctrl_lps = true,
.fwctrl_lps = false,
.debug = DBG_EMERG,
};
/* Because memory R/W bursting will cause system hang/crash
* for 92se, so we don't read back after every write action */
static struct rtl_hal_cfg rtl92se_hal_cfg = {
.bar_id = 1,
.write_readback = false,
.name = "rtl92s_pci",
.fw_name = "rtlwifi/rtl8192sefw.bin",
.ops = &rtl8192se_hal_ops,
.mod_params = &rtl92se_mod_params,
.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
.maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
.maps[SYS_CLK] = SYS_CLKR,
.maps[MAC_RCR_AM] = RCR_AM,
.maps[MAC_RCR_AB] = RCR_AB,
.maps[MAC_RCR_ACRC32] = RCR_ACRC32,
.maps[MAC_RCR_ACF] = RCR_ACF,
.maps[MAC_RCR_AAP] = RCR_AAP,
.maps[MAC_HIMR] = INTA_MASK,
.maps[MAC_HIMRE] = INTA_MASK + 4,
.maps[EFUSE_TEST] = REG_EFUSE_TEST,
.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
.maps[EFUSE_CLK] = REG_EFUSE_CLK,
.maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
.maps[EFUSE_PWC_EV12V] = 0, /* nouse for 8192se */
.maps[EFUSE_FEN_ELDR] = 0, /* nouse for 8192se */
.maps[EFUSE_LOADER_CLK_EN] = 0,/* nouse for 8192se */
.maps[EFUSE_ANA8M] = EFUSE_ANA8M,
.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S,
.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
.maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
.maps[RWCAM] = REG_RWCAM,
.maps[WCAMI] = REG_WCAMI,
.maps[RCAMO] = REG_RCAMO,
.maps[CAMDBG] = REG_CAMDBG,
.maps[SECR] = REG_SECR,
.maps[SEC_CAM_NONE] = CAM_NONE,
.maps[SEC_CAM_WEP40] = CAM_WEP40,
.maps[SEC_CAM_TKIP] = CAM_TKIP,
.maps[SEC_CAM_AES] = CAM_AES,
.maps[SEC_CAM_WEP104] = CAM_WEP104,
.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
.maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
.maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
.maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
.maps[RTL_IMR_BCNINT] = IMR_BCNINT,
.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
.maps[RTL_IMR_RDU] = IMR_RDU,
.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
.maps[RTL_IMR_BDOK] = IMR_BDOK,
.maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
.maps[RTL_IMR_TBDER] = IMR_TBDER,
.maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
.maps[RTL_IMR_COMDOK] = IMR_COMDOK,
.maps[RTL_IMR_TBDOK] = IMR_TBDOK,
.maps[RTL_IMR_BKDOK] = IMR_BKDOK,
.maps[RTL_IMR_BEDOK] = IMR_BEDOK,
.maps[RTL_IMR_VIDOK] = IMR_VIDOK,
.maps[RTL_IMR_VODOK] = IMR_VODOK,
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M,
.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M,
.maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M,
.maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M,
.maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M,
.maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M,
.maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M,
.maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M,
.maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M,
.maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M,
.maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M,
.maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M,
.maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7,
.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
static struct pci_device_id rtl92se_pci_ids[] = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8173, rtl92se_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8174, rtl92se_hal_cfg)},
{},
};
MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids);
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin");
module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444);
module_param_named(debug, rtl92se_mod_params.debug, int, 0444);
module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
static struct pci_driver rtl92se_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl92se_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
.driver.pm = &rtlwifi_pm_ops,
};
module_pci_driver(rtl92se_driver);

View file

@ -0,0 +1,36 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
*****************************************************************************/
#ifndef __REALTEK_PCI92SE_SW_H__
#define __REALTEK_PCI92SE_SW_H__
#define EFUSE_MAX_SECTION 16
int rtl92se_init_sw(struct ieee80211_hw *hw);
void rtl92se_deinit_sw(struct ieee80211_hw *hw);
void rtl92se_init_var_map(struct ieee80211_hw *hw);
#endif

View file

@ -0,0 +1,634 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
* Created on 2010/ 5/18, 1:41
*****************************************************************************/
#include "table.h"
u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH] = {
0x01c, 0x07000000,
0x800, 0x00040000,
0x804, 0x00008003,
0x808, 0x0000fc00,
0x80c, 0x0000000a,
0x810, 0x10005088,
0x814, 0x020c3d10,
0x818, 0x00200185,
0x81c, 0x00000000,
0x820, 0x01000000,
0x824, 0x00390004,
0x828, 0x01000000,
0x82c, 0x00390004,
0x830, 0x00000004,
0x834, 0x00690200,
0x838, 0x00000004,
0x83c, 0x00690200,
0x840, 0x00010000,
0x844, 0x00010000,
0x848, 0x00000000,
0x84c, 0x00000000,
0x850, 0x00000000,
0x854, 0x00000000,
0x858, 0x48484848,
0x85c, 0x65a965a9,
0x860, 0x0f7f0130,
0x864, 0x0f7f0130,
0x868, 0x0f7f0130,
0x86c, 0x0f7f0130,
0x870, 0x03000700,
0x874, 0x03000300,
0x878, 0x00020002,
0x87c, 0x004f0201,
0x880, 0xa8300ac1,
0x884, 0x00000058,
0x888, 0x00000008,
0x88c, 0x00000004,
0x890, 0x00000000,
0x894, 0xfffffffe,
0x898, 0x40302010,
0x89c, 0x00706050,
0x8b0, 0x00000000,
0x8e0, 0x00000000,
0x8e4, 0x00000000,
0xe00, 0x30333333,
0xe04, 0x2a2d2e2f,
0xe08, 0x00003232,
0xe10, 0x30333333,
0xe14, 0x2a2d2e2f,
0xe18, 0x30333333,
0xe1c, 0x2a2d2e2f,
0xe30, 0x01007c00,
0xe34, 0x01004800,
0xe38, 0x1000dc1f,
0xe3c, 0x10008c1f,
0xe40, 0x021400a0,
0xe44, 0x281600a0,
0xe48, 0xf8000001,
0xe4c, 0x00002910,
0xe50, 0x01007c00,
0xe54, 0x01004800,
0xe58, 0x1000dc1f,
0xe5c, 0x10008c1f,
0xe60, 0x021400a0,
0xe64, 0x281600a0,
0xe6c, 0x00002910,
0xe70, 0x31ed92fb,
0xe74, 0x361536fb,
0xe78, 0x361536fb,
0xe7c, 0x361536fb,
0xe80, 0x361536fb,
0xe84, 0x000d92fb,
0xe88, 0x000d92fb,
0xe8c, 0x31ed92fb,
0xed0, 0x31ed92fb,
0xed4, 0x31ed92fb,
0xed8, 0x000d92fb,
0xedc, 0x000d92fb,
0xee0, 0x000d92fb,
0xee4, 0x015e5448,
0xee8, 0x21555448,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90c, 0x01121313,
0xa00, 0x00d047c8,
0xa04, 0x80ff0008,
0xa08, 0x8ccd8300,
0xa0c, 0x2e62120f,
0xa10, 0x9500bb78,
0xa14, 0x11144028,
0xa18, 0x00881117,
0xa1c, 0x89140f00,
0xa20, 0x1a1b0000,
0xa24, 0x090e1317,
0xa28, 0x00000204,
0xa2c, 0x10d30000,
0xc00, 0x40071d40,
0xc04, 0x00a05633,
0xc08, 0x000000e4,
0xc0c, 0x6c6c6c6c,
0xc10, 0x08800000,
0xc14, 0x40000100,
0xc18, 0x08000000,
0xc1c, 0x40000100,
0xc20, 0x08000000,
0xc24, 0x40000100,
0xc28, 0x08000000,
0xc2c, 0x40000100,
0xc30, 0x6de9ac44,
0xc34, 0x469652cf,
0xc38, 0x49795994,
0xc3c, 0x0a979764,
0xc40, 0x1f7c403f,
0xc44, 0x000100b7,
0xc48, 0xec020000,
0xc4c, 0x007f037f,
0xc50, 0x69543420,
0xc54, 0x433c0094,
0xc58, 0x69543420,
0xc5c, 0x433c0094,
0xc60, 0x69543420,
0xc64, 0x433c0094,
0xc68, 0x69543420,
0xc6c, 0x433c0094,
0xc70, 0x2c7f000d,
0xc74, 0x0186155b,
0xc78, 0x0000001f,
0xc7c, 0x00b91612,
0xc80, 0x40000100,
0xc84, 0x20f60000,
0xc88, 0x20000080,
0xc8c, 0x20200000,
0xc90, 0x40000100,
0xc94, 0x00000000,
0xc98, 0x40000100,
0xc9c, 0x00000000,
0xca0, 0x00492492,
0xca4, 0x00000000,
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, 0x00000750,
0xd04, 0x00000403,
0xd08, 0x0000907f,
0xd0c, 0x00000001,
0xd10, 0xa0633333,
0xd14, 0x33333c63,
0xd18, 0x6a8f5b6b,
0xd1c, 0x00000000,
0xd20, 0x00000000,
0xd24, 0x00000000,
0xd28, 0x00000000,
0xd2c, 0xcc979975,
0xd30, 0x00000000,
0xd34, 0x00000000,
0xd38, 0x00000000,
0xd3c, 0x00027293,
0xd40, 0x00000000,
0xd44, 0x00000000,
0xd48, 0x00000000,
0xd50, 0x6437140a,
0xd54, 0x024dbd02,
0xd58, 0x00000000,
0xd5c, 0x30032064,
0xd60, 0x4653de68,
0xd64, 0x00518a3c,
0xd68, 0x00002101,
0xf14, 0x00000003,
0xf4c, 0x00000000,
0xf00, 0x00000300,
};
u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH] = {
0x844, 0xffffffff, 0x00010000,
0x804, 0x0000000f, 0x00000001,
0x824, 0x00f0000f, 0x00300004,
0x82c, 0x00f0000f, 0x00100002,
0x870, 0x04000000, 0x00000001,
0x864, 0x00000400, 0x00000000,
0x878, 0x000f000f, 0x00000002,
0xe74, 0x0f000000, 0x00000002,
0xe78, 0x0f000000, 0x00000002,
0xe7c, 0x0f000000, 0x00000002,
0xe80, 0x0f000000, 0x00000002,
0x90c, 0x000000ff, 0x00000011,
0xc04, 0x000000ff, 0x00000011,
0xd04, 0x0000000f, 0x00000001,
0x1f4, 0xffff0000, 0x00007777,
0x234, 0xf8000000, 0x0000000a,
};
u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH] = {
0x804, 0x0000000f, 0x00000003,
0x824, 0x00f0000f, 0x00300004,
0x82c, 0x00f0000f, 0x00300002,
0x870, 0x04000000, 0x00000001,
0x864, 0x00000400, 0x00000000,
0x878, 0x000f000f, 0x00000002,
0xe74, 0x0f000000, 0x00000002,
0xe78, 0x0f000000, 0x00000002,
0xe7c, 0x0f000000, 0x00000002,
0xe80, 0x0f000000, 0x00000002,
0x90c, 0x000000ff, 0x00000011,
0xc04, 0x000000ff, 0x00000033,
0xd04, 0x0000000f, 0x00000003,
0x1f4, 0xffff0000, 0x00007777,
0x234, 0xf8000000, 0x0000000a,
};
u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH] = {
0xe00, 0xffffffff, 0x06090909,
0xe04, 0xffffffff, 0x00030406,
0xe08, 0x0000ff00, 0x00000000,
0xe10, 0xffffffff, 0x0a0c0d0e,
0xe14, 0xffffffff, 0x04070809,
0xe18, 0xffffffff, 0x0a0c0d0e,
0xe1c, 0xffffffff, 0x04070809,
0xe00, 0xffffffff, 0x04040404,
0xe04, 0xffffffff, 0x00020204,
0xe08, 0x0000ff00, 0x00000000,
0xe10, 0xffffffff, 0x02040404,
0xe14, 0xffffffff, 0x00000002,
0xe18, 0xffffffff, 0x02040404,
0xe1c, 0xffffffff, 0x00000002,
0xe00, 0xffffffff, 0x04040404,
0xe04, 0xffffffff, 0x00020204,
0xe08, 0x0000ff00, 0x00000000,
0xe10, 0xffffffff, 0x02040404,
0xe14, 0xffffffff, 0x00000002,
0xe18, 0xffffffff, 0x02040404,
0xe1c, 0xffffffff, 0x00000002,
0xe00, 0xffffffff, 0x02020202,
0xe04, 0xffffffff, 0x00020202,
0xe08, 0x0000ff00, 0x00000000,
0xe10, 0xffffffff, 0x02020202,
0xe14, 0xffffffff, 0x00000002,
0xe18, 0xffffffff, 0x02020202,
0xe1c, 0xffffffff, 0x00000002,
};
u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH] = {
0x000, 0x00030159,
0x001, 0x00030250,
0x002, 0x00010000,
0x010, 0x0008000f,
0x011, 0x000231fc,
0x010, 0x000c000f,
0x011, 0x0003f9f8,
0x010, 0x0002000f,
0x011, 0x00020101,
0x014, 0x0001093e,
0x014, 0x0009093e,
0x015, 0x0000f8f4,
0x017, 0x000f6500,
0x01a, 0x00013056,
0x01b, 0x00060000,
0x01c, 0x00000300,
0x01e, 0x00031059,
0x021, 0x00054000,
0x022, 0x0000083c,
0x023, 0x00001558,
0x024, 0x00000060,
0x025, 0x00022583,
0x026, 0x0000f200,
0x027, 0x000eacf1,
0x028, 0x0009bd54,
0x029, 0x00004582,
0x02a, 0x00000001,
0x02b, 0x00021334,
0x02a, 0x00000000,
0x02b, 0x0000000a,
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, 0x00000709,
0x02b, 0x00053333,
0x02c, 0x0000000d,
0x02a, 0x00000006,
0x02b, 0x00000709,
0x02b, 0x0005b333,
0x02c, 0x0000000d,
0x02a, 0x00000007,
0x02b, 0x00000709,
0x02b, 0x00063333,
0x02c, 0x0000000d,
0x02a, 0x00000008,
0x02b, 0x00000709,
0x02b, 0x0006b333,
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, 0x0000050b,
0x02b, 0x00053333,
0x02c, 0x0000000d,
0x02a, 0x0000000e,
0x02b, 0x0000050b,
0x02b, 0x00066623,
0x02c, 0x0000001a,
0x02a, 0x000e4000,
0x030, 0x00020000,
0x031, 0x000b9631,
0x032, 0x0000130d,
0x033, 0x00000187,
0x013, 0x00019e6c,
0x013, 0x00015e94,
0x000, 0x00010159,
0x018, 0x0000f401,
0x0fe, 0x00000000,
0x01e, 0x0003105b,
0x0fe, 0x00000000,
0x000, 0x00030159,
0x010, 0x0004000f,
0x011, 0x000203f9,
};
u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH] = {
0x000, 0x00030159,
0x001, 0x00001041,
0x002, 0x00011000,
0x005, 0x00080fc0,
0x007, 0x000fc803,
0x013, 0x00017cb0,
0x013, 0x00011cc0,
0x013, 0x0000dc60,
0x013, 0x00008c60,
0x013, 0x00004450,
0x013, 0x00000020,
};
u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH] = {
0x000, 0x00030159,
0x001, 0x00001041,
0x002, 0x00011000,
0x005, 0x00080fc0,
0x007, 0x000fc803,
};
u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH] = {
0x020, 0x00000035,
0x048, 0x0000000e,
0x049, 0x000000f0,
0x04a, 0x00000077,
0x04b, 0x00000083,
0x0b5, 0x00000021,
0x0dc, 0x000000ff,
0x0dd, 0x000000ff,
0x0de, 0x000000ff,
0x0df, 0x000000ff,
0x116, 0x00000000,
0x117, 0x00000000,
0x118, 0x00000000,
0x119, 0x00000000,
0x11a, 0x00000000,
0x11b, 0x00000000,
0x11c, 0x00000000,
0x11d, 0x00000000,
0x160, 0x0000000b,
0x161, 0x0000000b,
0x162, 0x0000000b,
0x163, 0x0000000b,
0x164, 0x0000000b,
0x165, 0x0000000b,
0x166, 0x0000000b,
0x167, 0x0000000b,
0x168, 0x0000000b,
0x169, 0x0000000b,
0x16a, 0x0000000b,
0x16b, 0x0000000b,
0x16c, 0x0000000b,
0x16d, 0x0000000b,
0x16e, 0x0000000b,
0x16f, 0x0000000b,
0x170, 0x0000000b,
0x171, 0x0000000b,
0x172, 0x0000000b,
0x173, 0x0000000b,
0x174, 0x0000000b,
0x175, 0x0000000b,
0x176, 0x0000000b,
0x177, 0x0000000b,
0x178, 0x0000000b,
0x179, 0x0000000b,
0x17a, 0x0000000b,
0x17b, 0x0000000b,
0x17c, 0x0000000b,
0x17d, 0x0000000b,
0x17e, 0x0000000b,
0x17f, 0x0000000b,
0x236, 0x0000000c,
0x503, 0x00000022,
0x560, 0x00000000,
};
u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH] = {
0xc78, 0x7f000001,
0xc78, 0x7f010001,
0xc78, 0x7e020001,
0xc78, 0x7d030001,
0xc78, 0x7c040001,
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, 0x6f120001,
0xc78, 0x6e130001,
0xc78, 0x6d140001,
0xc78, 0x6d150001,
0xc78, 0x6c160001,
0xc78, 0x6b170001,
0xc78, 0x6a180001,
0xc78, 0x6a190001,
0xc78, 0x691a0001,
0xc78, 0x681b0001,
0xc78, 0x671c0001,
0xc78, 0x661d0001,
0xc78, 0x651e0001,
0xc78, 0x641f0001,
0xc78, 0x63200001,
0xc78, 0x4c210001,
0xc78, 0x4b220001,
0xc78, 0x4a230001,
0xc78, 0x49240001,
0xc78, 0x48250001,
0xc78, 0x47260001,
0xc78, 0x46270001,
0xc78, 0x45280001,
0xc78, 0x44290001,
0xc78, 0x2c2a0001,
0xc78, 0x2b2b0001,
0xc78, 0x2a2c0001,
0xc78, 0x292d0001,
0xc78, 0x282e0001,
0xc78, 0x272f0001,
0xc78, 0x26300001,
0xc78, 0x25310001,
0xc78, 0x24320001,
0xc78, 0x23330001,
0xc78, 0x22340001,
0xc78, 0x09350001,
0xc78, 0x08360001,
0xc78, 0x07370001,
0xc78, 0x06380001,
0xc78, 0x05390001,
0xc78, 0x043a0001,
0xc78, 0x033b0001,
0xc78, 0x023c0001,
0xc78, 0x013d0001,
0xc78, 0x003e0001,
0xc78, 0x003f0001,
0xc78, 0x7f400001,
0xc78, 0x7f410001,
0xc78, 0x7e420001,
0xc78, 0x7d430001,
0xc78, 0x7c440001,
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, 0x6f520001,
0xc78, 0x6e530001,
0xc78, 0x6d540001,
0xc78, 0x6d550001,
0xc78, 0x6c560001,
0xc78, 0x6b570001,
0xc78, 0x6a580001,
0xc78, 0x6a590001,
0xc78, 0x695a0001,
0xc78, 0x685b0001,
0xc78, 0x675c0001,
0xc78, 0x665d0001,
0xc78, 0x655e0001,
0xc78, 0x645f0001,
0xc78, 0x63600001,
0xc78, 0x4c610001,
0xc78, 0x4b620001,
0xc78, 0x4a630001,
0xc78, 0x49640001,
0xc78, 0x48650001,
0xc78, 0x47660001,
0xc78, 0x46670001,
0xc78, 0x45680001,
0xc78, 0x44690001,
0xc78, 0x2c6a0001,
0xc78, 0x2b6b0001,
0xc78, 0x2a6c0001,
0xc78, 0x296d0001,
0xc78, 0x286e0001,
0xc78, 0x276f0001,
0xc78, 0x26700001,
0xc78, 0x25710001,
0xc78, 0x24720001,
0xc78, 0x23730001,
0xc78, 0x22740001,
0xc78, 0x09750001,
0xc78, 0x08760001,
0xc78, 0x07770001,
0xc78, 0x06780001,
0xc78, 0x05790001,
0xc78, 0x047a0001,
0xc78, 0x037b0001,
0xc78, 0x027c0001,
0xc78, 0x017d0001,
0xc78, 0x007e0001,
0xc78, 0x007f0001,
0xc78, 0x3000001e,
0xc78, 0x3001001e,
0xc78, 0x3002001e,
0xc78, 0x3003001e,
0xc78, 0x3004001e,
0xc78, 0x3405001e,
0xc78, 0x3806001e,
0xc78, 0x3e07001e,
0xc78, 0x3e08001e,
0xc78, 0x4409001e,
0xc78, 0x460a001e,
0xc78, 0x480b001e,
0xc78, 0x480c001e,
0xc78, 0x4e0d001e,
0xc78, 0x560e001e,
0xc78, 0x5a0f001e,
0xc78, 0x5e10001e,
0xc78, 0x6211001e,
0xc78, 0x6c12001e,
0xc78, 0x7213001e,
0xc78, 0x7214001e,
0xc78, 0x7215001e,
0xc78, 0x7216001e,
0xc78, 0x7217001e,
0xc78, 0x7218001e,
0xc78, 0x7219001e,
0xc78, 0x721a001e,
0xc78, 0x721b001e,
0xc78, 0x721c001e,
0xc78, 0x721d001e,
0xc78, 0x721e001e,
0xc78, 0x721f001e,
};

View file

@ -0,0 +1,49 @@
/******************************************************************************
* Copyright(c) 2008 - 2012 Realtek Corporation. All rights reserved.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
******************************************************************************/
#ifndef __INC_HAL8192SE_FW_IMG_H
#define __INC_HAL8192SE_FW_IMG_H
#include <linux/types.h>
/*Created on 2010/ 4/12, 5:56*/
#define PHY_REG_2T2RARRAYLENGTH 372
extern u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH];
#define PHY_CHANGETO_1T1RARRAYLENGTH 48
extern u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH];
#define PHY_CHANGETO_1T2RARRAYLENGTH 45
extern u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH];
#define PHY_REG_ARRAY_PGLENGTH 84
extern u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH];
#define RADIOA_1T_ARRAYLENGTH 202
extern u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH];
#define RADIOB_ARRAYLENGTH 22
extern u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH];
#define RADIOB_GM_ARRAYLENGTH 10
extern u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH];
#define MAC_2T_ARRAYLENGTH 106
extern u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH];
#define AGCTAB_ARRAYLENGTH 320
extern u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH];
#endif

View file

@ -0,0 +1,659 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "../wifi.h"
#include "../pci.h"
#include "../base.h"
#include "../stats.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "fw.h"
#include "trx.h"
#include "led.h"
static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue)
{
__le16 fc = rtl_get_fc(skb);
if (unlikely(ieee80211_is_beacon(fc)))
return QSLT_BEACON;
if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
return QSLT_MGNT;
if (ieee80211_is_nullfunc(fc))
return QSLT_HIGH;
/* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use
* queue V0 at priority 7; however, the RTL8192SE appears to have
* that queue at priority 6
*/
if (skb->priority == 7)
return QSLT_VO;
return skb->priority;
}
static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
struct rtl_stats *pstats, u8 *pdesc,
struct rx_fwinfo *p_drvinfo,
bool packet_match_bssid,
bool packet_toself,
bool packet_beacon)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct phy_sts_cck_8192s_t *cck_buf;
struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
s8 rx_pwr_all = 0, rx_pwr[4];
u8 rf_rx_num = 0, evm, pwdb_all;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
bool is_cck = pstats->is_cck;
pstats->packet_matchbssid = packet_match_bssid;
pstats->packet_toself = packet_toself;
pstats->packet_beacon = packet_beacon;
pstats->rx_mimo_sig_qual[0] = -1;
pstats->rx_mimo_sig_qual[1] = -1;
if (is_cck) {
u8 report, cck_highpwr;
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
if (ppsc->rfpwr_state == ERFON)
cck_highpwr = (u8) rtl_get_bbreg(hw,
RFPGA0_XA_HSSIPARAMETER2,
0x200);
else
cck_highpwr = false;
if (!cck_highpwr) {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
report = cck_buf->cck_agc_rpt & 0xc0;
report = report >> 6;
switch (report) {
case 0x3:
rx_pwr_all = -40 - (cck_agc_rpt & 0x3e);
break;
case 0x2:
rx_pwr_all = -20 - (cck_agc_rpt & 0x3e);
break;
case 0x1:
rx_pwr_all = -2 - (cck_agc_rpt & 0x3e);
break;
case 0x0:
rx_pwr_all = 14 - (cck_agc_rpt & 0x3e);
break;
}
} else {
u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
report = p_drvinfo->cfosho[0] & 0x60;
report = report >> 5;
switch (report) {
case 0x3:
rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1);
break;
case 0x2:
rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1);
break;
case 0x1:
rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1);
break;
case 0x0:
rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1);
break;
}
}
pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
/* CCK gain is smaller than OFDM/MCS gain, */
/* so we add gain diff by experiences, the val is 6 */
pwdb_all += 6;
if (pwdb_all > 100)
pwdb_all = 100;
/* modify the offset to make the same gain index with OFDM. */
if (pwdb_all > 34 && pwdb_all <= 42)
pwdb_all -= 2;
else if (pwdb_all > 26 && pwdb_all <= 34)
pwdb_all -= 6;
else if (pwdb_all > 14 && pwdb_all <= 26)
pwdb_all -= 8;
else if (pwdb_all > 4 && pwdb_all <= 14)
pwdb_all -= 4;
pstats->rx_pwdb_all = pwdb_all;
pstats->recvsignalpower = rx_pwr_all;
if (packet_match_bssid) {
u8 sq;
if (pstats->rx_pwdb_all > 40) {
sq = 100;
} else {
sq = cck_buf->sq_rpt;
if (sq > 64)
sq = 0;
else if (sq < 20)
sq = 100;
else
sq = ((64 - sq) * 100) / 44;
}
pstats->signalquality = sq;
pstats->rx_mimo_sig_qual[0] = sq;
pstats->rx_mimo_sig_qual[1] = -1;
}
} else {
rtlpriv->dm.rfpath_rxenable[0] =
rtlpriv->dm.rfpath_rxenable[1] = true;
for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
if (rtlpriv->dm.rfpath_rxenable[i])
rf_rx_num++;
rx_pwr[i] = ((p_drvinfo->gain_trsw[i] &
0x3f) * 2) - 110;
rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
total_rssi += rssi;
rtlpriv->stats.rx_snr_db[i] =
(long)(p_drvinfo->rxsnr[i] / 2);
if (packet_match_bssid)
pstats->rx_mimo_signalstrength[i] = (u8) rssi;
}
rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
pstats->rx_pwdb_all = pwdb_all;
pstats->rxpower = rx_pwr_all;
pstats->recvsignalpower = rx_pwr_all;
if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 &&
pstats->rate <= DESC92_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
for (i = 0; i < max_spatial_stream; i++) {
evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
if (packet_match_bssid) {
if (i == 0)
pstats->signalquality = (u8)(evm &
0xff);
pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff);
}
}
}
if (is_cck)
pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
pwdb_all));
else if (rf_rx_num != 0)
pstats->signalstrength = (u8) (rtl_signal_scale_mapping(hw,
total_rssi /= rf_rx_num));
}
static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct sk_buff *skb, struct rtl_stats *pstats,
u8 *pdesc, struct rx_fwinfo *p_drvinfo)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
__le16 fc;
u16 type, cfc;
bool packet_matchbssid, packet_toself, packet_beacon = false;
tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
hdr = (struct ieee80211_hdr *)tmp_buf;
fc = hdr->frame_control;
cfc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
ether_addr_equal(mac->bssid,
(cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 :
(cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 :
hdr->addr3) &&
(!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
packet_toself = packet_matchbssid &&
ether_addr_equal(praddr, rtlefuse->dev_addr);
if (ieee80211_is_beacon(fc))
packet_beacon = true;
_rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
packet_matchbssid, packet_toself, packet_beacon);
rtl_process_phyinfo(hw, tmp_buf, pstats);
}
bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
struct ieee80211_rx_status *rx_status, u8 *pdesc,
struct sk_buff *skb)
{
struct rx_fwinfo *p_drvinfo;
u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc);
struct ieee80211_hdr *hdr;
bool first_ampdu = false;
stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc);
stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8;
stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03);
stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc);
stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc);
stats->hwerror = (u16)(stats->crc | stats->icv);
stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc);
stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc);
stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc);
stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1);
stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1)
&& (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc);
stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc);
if (stats->hwerror)
return false;
rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->band = hw->conf.chandef.chan->band;
if (stats->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (stats->rx_is40Mhzpacket)
rx_status->flag |= RX_FLAG_40MHZ;
if (stats->is_ht)
rx_status->flag |= RX_FLAG_HT;
rx_status->flag |= RX_FLAG_MACTIME_START;
/* hw will set stats->decrypted true, if it finds the
* frame is open data frame or mgmt frame,
* hw will not decrypt robust managment frame
* for IEEE80211w but still set stats->decrypted
* true, so here we should set it back to undecrypted
* for IEEE80211w frame, and mac80211 sw will help
* to decrypt it */
if (stats->decrypted) {
hdr = (struct ieee80211_hdr *)(skb->data +
stats->rx_drvinfo_size + stats->rx_bufshift);
if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
(ieee80211_has_protected(hdr->frame_control)))
rx_status->flag &= ~RX_FLAG_DECRYPTED;
else
rx_status->flag |= RX_FLAG_DECRYPTED;
}
rx_status->rate_idx = rtlwifi_rate_mapping(hw,
stats->is_ht, stats->rate, first_ampdu);
rx_status->mactime = stats->timestamp_low;
if (phystatus) {
p_drvinfo = (struct rx_fwinfo *)(skb->data +
stats->rx_bufshift);
_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
p_drvinfo);
}
/*rx_status->qual = stats->signal; */
rx_status->signal = stats->recvsignalpower + 10;
return true;
}
void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr, u8 *pdesc_tx,
u8 *pbd_desc_tx, struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
struct sk_buff *skb,
u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 *pdesc = pdesc_tx;
u16 seq_number;
__le16 fc = hdr->frame_control;
u8 reserved_macid = 0;
u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue);
bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)));
bool lastseg = (!(hdr->frame_control &
cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)));
dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
u8 bw_40 = 0;
if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error");
return;
}
if (mac->opmode == NL80211_IFTYPE_STATION) {
bw_40 = mac->bw_40;
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta)
bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
}
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S);
if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
firstseg = true;
lastseg = true;
}
if (firstseg) {
if (rtlpriv->dm.useramask) {
/* set txdesc macId */
if (ptcb_desc->mac_id < 32) {
SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
reserved_macid |= ptcb_desc->mac_id;
}
}
SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid);
SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >=
DESC92_RATEMCS0) ? 1 : 0));
if (rtlhal->version == VERSION_8192S_ACUT) {
if (ptcb_desc->hw_rate == DESC92_RATE1M ||
ptcb_desc->hw_rate == DESC92_RATE2M ||
ptcb_desc->hw_rate == DESC92_RATE5_5M ||
ptcb_desc->hw_rate == DESC92_RATE11M) {
ptcb_desc->hw_rate = DESC92_RATE12M;
}
}
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
SET_TX_DESC_TX_SHORT(pdesc, 0);
/* Aggregation related */
if (info->flags & IEEE80211_TX_CTL_AMPDU)
SET_TX_DESC_AGG_ENABLE(pdesc, 1);
/* For AMPDU, we must insert SSN into TX_DESC */
SET_TX_DESC_SEQ(pdesc, seq_number);
/* Protection mode related */
/* For 92S, if RTS/CTS are set, HW will execute RTS. */
/* We choose only one protection mode to execute */
SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
!ptcb_desc->cts_enable) ? 1 : 0));
SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ?
1 : 0));
SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0);
SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
DESC92_RATE54M) ?
(ptcb_desc->rts_use_shortpreamble ? 1 : 0)
: (ptcb_desc->rts_use_shortgi ? 1 : 0)));
/* Set Bandwidth and sub-channel settings. */
if (bw_40) {
if (ptcb_desc->packet_bw) {
SET_TX_DESC_TX_BANDWIDTH(pdesc, 1);
/* use duplicated mode */
SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
} else {
SET_TX_DESC_TX_BANDWIDTH(pdesc, 0);
SET_TX_DESC_TX_SUB_CARRIER(pdesc,
mac->cur_40_prime_sc);
}
} else {
SET_TX_DESC_TX_BANDWIDTH(pdesc, 0);
SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
}
/* 3 Fill necessary field in First Descriptor */
/*DWORD 0*/
SET_TX_DESC_LINIP(pdesc, 0);
SET_TX_DESC_OFFSET(pdesc, 32);
SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
/*DWORD 1*/
SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index);
/* Fill security related */
if (info->control.hw_key) {
struct ieee80211_key_conf *keyconf;
keyconf = info->control.hw_key;
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
break;
case WLAN_CIPHER_SUITE_TKIP:
SET_TX_DESC_SEC_TYPE(pdesc, 0x2);
break;
case WLAN_CIPHER_SUITE_CCMP:
SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
break;
default:
SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
break;
}
}
/* Set Packet ID */
SET_TX_DESC_PACKET_ID(pdesc, 0);
/* We will assign magement queue to BK. */
SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
/* Alwasy enable all rate fallback range */
SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
/* Fix: I don't kown why hw use 6.5M to tx when set it */
SET_TX_DESC_USER_RATE(pdesc,
ptcb_desc->use_driver_rate ? 1 : 0);
/* Set NON_QOS bit. */
if (!ieee80211_is_data_qos(fc))
SET_TX_DESC_NON_QOS(pdesc, 1);
}
/* Fill fields that are required to be initialized
* in all of the descriptors */
/*DWORD 0 */
SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
/* DWORD 7 */
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
/* DOWRD 8 */
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
}
void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
bool firstseg, bool lastseg, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error");
return;
}
/* Clear all status */
CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S);
/* This bit indicate this packet is used for FW download. */
if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) {
/* For firmware downlaod we only need to set LINIP */
SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt);
/* 92SE must set as 1 for firmware download HW DMA error */
SET_TX_DESC_FIRST_SEG(pdesc, 1);
SET_TX_DESC_LAST_SEG(pdesc, 1);
/* 92SE need not to set TX packet size when firmware download */
SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
wmb();
SET_TX_DESC_OWN(pdesc, 1);
} else { /* H2C Command Desc format (Host TXCMD) */
/* 92SE must set as 1 for firmware download HW DMA error */
SET_TX_DESC_FIRST_SEG(pdesc, 1);
SET_TX_DESC_LAST_SEG(pdesc, 1);
SET_TX_DESC_OFFSET(pdesc, 0x20);
/* Buffer size + command header */
SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
/* Fixed queue of H2C command */
SET_TX_DESC_QUEUE_SEL(pdesc, 0x13);
SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq);
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
wmb();
SET_TX_DESC_OWN(pdesc, 1);
}
}
void rtl92se_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
u8 desc_name, u8 *val)
{
if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
wmb();
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
break;
default:
RT_ASSERT(false, "ERR txdesc :%d not process\n",
desc_name);
break;
}
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
wmb();
SET_RX_STATUS_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val);
break;
case HW_DESC_RXPKT_LEN:
SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val);
break;
case HW_DESC_RXERO:
SET_RX_STATUS_DESC_EOR(pdesc, 1);
break;
default:
RT_ASSERT(false, "ERR rxdesc :%d not process\n",
desc_name);
break;
}
}
}
u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
{
u32 ret = 0;
if (istx) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(desc);
break;
case HW_DESC_TXBUFF_ADDR:
ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc);
break;
default:
RT_ASSERT(false, "ERR txdesc :%d not process\n",
desc_name);
break;
}
} else {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_RX_STATUS_DESC_OWN(desc);
break;
case HW_DESC_RXPKT_LEN:
ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
break;
case HW_DESC_RXBUFF_ADDR:
ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc);
break;
default:
RT_ASSERT(false, "ERR rxdesc :%d not process\n",
desc_name);
break;
}
}
return ret;
}
void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue));
}

View file

@ -0,0 +1,48 @@
/******************************************************************************
*
* Copyright(c) 2009-2012 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __REALTEK_PCI92SE_TRX_H__
#define __REALTEK_PCI92SE_TRX_H__
void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr, u8 *pdesc,
u8 *pbd_desc_tx, struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
struct sk_buff *skb, u8 hw_queue,
struct rtl_tcb_desc *ptcb_desc);
void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg,
bool lastseg, struct sk_buff *skb);
bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
struct ieee80211_rx_status *rx_status, u8 *pdesc,
struct sk_buff *skb);
void rtl92se_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
u8 desc_name, u8 *val);
u32 rtl92se_get_desc(u8 *pdesc, bool istx, u8 desc_name);
void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
#endif