2009-04-26 15:47:48 +02:00
/*
Copyright ( C ) 2004 - 2009 rt2x00 SourceForge Project
< http : //rt2x00.serialmonkey.com>
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
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 . ,
59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
/*
Module : rt2800usb
Abstract : rt2800usb device specific routines .
Supported chipsets : RT2800U .
*/
# include <linux/crc-ccitt.h>
# include <linux/delay.h>
# include <linux/etherdevice.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/usb.h>
# include "rt2x00.h"
# include "rt2x00usb.h"
# include "rt2800usb.h"
/*
* Allow hardware encryption to be disabled .
*/
static int modparam_nohwcrypt = 1 ;
module_param_named ( nohwcrypt , modparam_nohwcrypt , bool , S_IRUGO ) ;
MODULE_PARM_DESC ( nohwcrypt , " Disable hardware encryption. " ) ;
/*
* Register access .
* All access to the CSR registers will go through the methods
* rt2x00usb_register_read and rt2x00usb_register_write .
* BBP and RF register require indirect register access ,
* and use the CSR registers BBPCSR and RFCSR to achieve this .
* These indirect registers work with busy bits ,
* and we will try maximal REGISTER_BUSY_COUNT times to access
* the register while taking a REGISTER_BUSY_DELAY us delay
* between each attampt . When the busy bit is still set at that time ,
* the access attempt is considered to have failed ,
* and we will print an error .
* The _lock versions must be used if you already hold the csr_mutex
*/
# define WAIT_FOR_BBP(__dev, __reg) \
rt2x00usb_regbusy_read ( ( __dev ) , BBP_CSR_CFG , BBP_CSR_CFG_BUSY , ( __reg ) )
# define WAIT_FOR_RFCSR(__dev, __reg) \
rt2x00usb_regbusy_read ( ( __dev ) , RF_CSR_CFG , RF_CSR_CFG_BUSY , ( __reg ) )
# define WAIT_FOR_RF(__dev, __reg) \
rt2x00usb_regbusy_read ( ( __dev ) , RF_CSR_CFG0 , RF_CSR_CFG0_BUSY , ( __reg ) )
# define WAIT_FOR_MCU(__dev, __reg) \
rt2x00usb_regbusy_read ( ( __dev ) , H2M_MAILBOX_CSR , \
H2M_MAILBOX_CSR_OWNER , ( __reg ) )
static void rt2800usb_bbp_write ( struct rt2x00_dev * rt2x00dev ,
const unsigned int word , const u8 value )
{
u32 reg ;
mutex_lock ( & rt2x00dev - > csr_mutex ) ;
/*
* Wait until the BBP becomes available , afterwards we
* can safely write the new data into the register .
*/
if ( WAIT_FOR_BBP ( rt2x00dev , & reg ) ) {
reg = 0 ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_VALUE , value ) ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_REGNUM , word ) ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_BUSY , 1 ) ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_READ_CONTROL , 0 ) ;
rt2x00usb_register_write_lock ( rt2x00dev , BBP_CSR_CFG , reg ) ;
}
mutex_unlock ( & rt2x00dev - > csr_mutex ) ;
}
static void rt2800usb_bbp_read ( struct rt2x00_dev * rt2x00dev ,
const unsigned int word , u8 * value )
{
u32 reg ;
mutex_lock ( & rt2x00dev - > csr_mutex ) ;
/*
* Wait until the BBP becomes available , afterwards we
* can safely write the read request into the register .
* After the data has been written , we wait until hardware
* returns the correct value , if at any time the register
* doesn ' t become available in time , reg will be 0xffffffff
* which means we return 0xff to the caller .
*/
if ( WAIT_FOR_BBP ( rt2x00dev , & reg ) ) {
reg = 0 ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_REGNUM , word ) ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_BUSY , 1 ) ;
rt2x00_set_field32 ( & reg , BBP_CSR_CFG_READ_CONTROL , 1 ) ;
rt2x00usb_register_write_lock ( rt2x00dev , BBP_CSR_CFG , reg ) ;
WAIT_FOR_BBP ( rt2x00dev , & reg ) ;
}
* value = rt2x00_get_field32 ( reg , BBP_CSR_CFG_VALUE ) ;
mutex_unlock ( & rt2x00dev - > csr_mutex ) ;
}
static void rt2800usb_rfcsr_write ( struct rt2x00_dev * rt2x00dev ,
const unsigned int word , const u8 value )
{
u32 reg ;
mutex_lock ( & rt2x00dev - > csr_mutex ) ;
/*
* Wait until the RFCSR becomes available , afterwards we
* can safely write the new data into the register .
*/
if ( WAIT_FOR_RFCSR ( rt2x00dev , & reg ) ) {
reg = 0 ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_DATA , value ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_REGNUM , word ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_WRITE , 1 ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_BUSY , 1 ) ;
rt2x00usb_register_write_lock ( rt2x00dev , RF_CSR_CFG , reg ) ;
}
mutex_unlock ( & rt2x00dev - > csr_mutex ) ;
}
static void rt2800usb_rfcsr_read ( struct rt2x00_dev * rt2x00dev ,
const unsigned int word , u8 * value )
{
u32 reg ;
mutex_lock ( & rt2x00dev - > csr_mutex ) ;
/*
* Wait until the RFCSR becomes available , afterwards we
* can safely write the read request into the register .
* After the data has been written , we wait until hardware
* returns the correct value , if at any time the register
* doesn ' t become available in time , reg will be 0xffffffff
* which means we return 0xff to the caller .
*/
if ( WAIT_FOR_RFCSR ( rt2x00dev , & reg ) ) {
reg = 0 ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_REGNUM , word ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_WRITE , 0 ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG_BUSY , 1 ) ;
rt2x00usb_register_write_lock ( rt2x00dev , BBP_CSR_CFG , reg ) ;
WAIT_FOR_RFCSR ( rt2x00dev , & reg ) ;
}
* value = rt2x00_get_field32 ( reg , RF_CSR_CFG_DATA ) ;
mutex_unlock ( & rt2x00dev - > csr_mutex ) ;
}
static void rt2800usb_rf_write ( struct rt2x00_dev * rt2x00dev ,
const unsigned int word , const u32 value )
{
u32 reg ;
mutex_lock ( & rt2x00dev - > csr_mutex ) ;
/*
* Wait until the RF becomes available , afterwards we
* can safely write the new data into the register .
*/
if ( WAIT_FOR_RF ( rt2x00dev , & reg ) ) {
reg = 0 ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG0_REG_VALUE_BW , value ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG0_STANDBYMODE , 0 ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG0_SEL , 0 ) ;
rt2x00_set_field32 ( & reg , RF_CSR_CFG0_BUSY , 1 ) ;
rt2x00usb_register_write_lock ( rt2x00dev , RF_CSR_CFG0 , reg ) ;
rt2x00_rf_write ( rt2x00dev , word , value ) ;
}
mutex_unlock ( & rt2x00dev - > csr_mutex ) ;
}
static void rt2800usb_mcu_request ( struct rt2x00_dev * rt2x00dev ,
const u8 command , const u8 token ,
const u8 arg0 , const u8 arg1 )
{
u32 reg ;
mutex_lock ( & rt2x00dev - > csr_mutex ) ;
/*
* Wait until the MCU becomes available , afterwards we
* can safely write the new data into the register .
*/
if ( WAIT_FOR_MCU ( rt2x00dev , & reg ) ) {
rt2x00_set_field32 ( & reg , H2M_MAILBOX_CSR_OWNER , 1 ) ;
rt2x00_set_field32 ( & reg , H2M_MAILBOX_CSR_CMD_TOKEN , token ) ;
rt2x00_set_field32 ( & reg , H2M_MAILBOX_CSR_ARG0 , arg0 ) ;
rt2x00_set_field32 ( & reg , H2M_MAILBOX_CSR_ARG1 , arg1 ) ;
rt2x00usb_register_write_lock ( rt2x00dev , H2M_MAILBOX_CSR , reg ) ;
reg = 0 ;
rt2x00_set_field32 ( & reg , HOST_CMD_CSR_HOST_COMMAND , command ) ;
rt2x00usb_register_write_lock ( rt2x00dev , HOST_CMD_CSR , reg ) ;
}
mutex_unlock ( & rt2x00dev - > csr_mutex ) ;
}
# ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt2800usb_rt2x00debug = {
. owner = THIS_MODULE ,
. csr = {
. read = rt2x00usb_register_read ,
. write = rt2x00usb_register_write ,
. flags = RT2X00DEBUGFS_OFFSET ,
. word_base = CSR_REG_BASE ,
. word_size = sizeof ( u32 ) ,
. word_count = CSR_REG_SIZE / sizeof ( u32 ) ,
} ,
. eeprom = {
. read = rt2x00_eeprom_read ,
. write = rt2x00_eeprom_write ,
. word_base = EEPROM_BASE ,
. word_size = sizeof ( u16 ) ,
. word_count = EEPROM_SIZE / sizeof ( u16 ) ,
} ,
. bbp = {
. read = rt2800usb_bbp_read ,
. write = rt2800usb_bbp_write ,
. word_base = BBP_BASE ,
. word_size = sizeof ( u8 ) ,
. word_count = BBP_SIZE / sizeof ( u8 ) ,
} ,
. rf = {
. read = rt2x00_rf_read ,
. write = rt2800usb_rf_write ,
. word_base = RF_BASE ,
. word_size = sizeof ( u32 ) ,
. word_count = RF_SIZE / sizeof ( u32 ) ,
} ,
} ;
# endif /* CONFIG_RT2X00_LIB_DEBUGFS */
static int rt2800usb_rfkill_poll ( struct rt2x00_dev * rt2x00dev )
{
u32 reg ;
rt2x00usb_register_read ( rt2x00dev , GPIO_CTRL_CFG , & reg ) ;
return rt2x00_get_field32 ( reg , GPIO_CTRL_CFG_BIT2 ) ;
}
# ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2800usb_brightness_set ( struct led_classdev * led_cdev ,
enum led_brightness brightness )
{
struct rt2x00_led * led =
container_of ( led_cdev , struct rt2x00_led , led_dev ) ;
unsigned int enabled = brightness ! = LED_OFF ;
unsigned int bg_mode =
( enabled & & led - > rt2x00dev - > curr_band = = IEEE80211_BAND_2GHZ ) ;
unsigned int polarity =
rt2x00_get_field16 ( led - > rt2x00dev - > led_mcu_reg ,
EEPROM_FREQ_LED_POLARITY ) ;
unsigned int ledmode =
rt2x00_get_field16 ( led - > rt2x00dev - > led_mcu_reg ,
EEPROM_FREQ_LED_MODE ) ;
if ( led - > type = = LED_TYPE_RADIO ) {
rt2800usb_mcu_request ( led - > rt2x00dev , MCU_LED , 0xff , ledmode ,
enabled ? 0x20 : 0 ) ;
} else if ( led - > type = = LED_TYPE_ASSOC ) {
rt2800usb_mcu_request ( led - > rt2x00dev , MCU_LED , 0xff , ledmode ,
enabled ? ( bg_mode ? 0x60 : 0xa0 ) : 0x20 ) ;
} else if ( led - > type = = LED_TYPE_QUALITY ) {
/*
* The brightness is divided into 6 levels ( 0 - 5 ) ,
* The specs tell us the following levels :
* 0 , 1 , 3 , 7 , 15 , 31
* to determine the level in a simple way we can simply
* work with bitshifting :
* ( 1 < < level ) - 1
*/
rt2800usb_mcu_request ( led - > rt2x00dev , MCU_LED_STRENGTH , 0xff ,
( 1 < < brightness / ( LED_FULL / 6 ) ) - 1 ,
polarity ) ;
}
}
static int rt2800usb_blink_set ( struct led_classdev * led_cdev ,
unsigned long * delay_on ,
unsigned long * delay_off )
{
struct rt2x00_led * led =
container_of ( led_cdev , struct rt2x00_led , led_dev ) ;
u32 reg ;
rt2x00usb_register_read ( led - > rt2x00dev , LED_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , LED_CFG_ON_PERIOD , * delay_on ) ;
rt2x00_set_field32 ( & reg , LED_CFG_OFF_PERIOD , * delay_off ) ;
rt2x00_set_field32 ( & reg , LED_CFG_SLOW_BLINK_PERIOD , 3 ) ;
rt2x00_set_field32 ( & reg , LED_CFG_R_LED_MODE , 3 ) ;
rt2x00_set_field32 ( & reg , LED_CFG_G_LED_MODE , 12 ) ;
rt2x00_set_field32 ( & reg , LED_CFG_Y_LED_MODE , 3 ) ;
rt2x00_set_field32 ( & reg , LED_CFG_LED_POLAR , 1 ) ;
rt2x00usb_register_write ( led - > rt2x00dev , LED_CFG , reg ) ;
return 0 ;
}
static void rt2800usb_init_led ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00_led * led ,
enum led_type type )
{
led - > rt2x00dev = rt2x00dev ;
led - > type = type ;
led - > led_dev . brightness_set = rt2800usb_brightness_set ;
led - > led_dev . blink_set = rt2800usb_blink_set ;
led - > flags = LED_INITIALIZED ;
}
# endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers .
*/
static void rt2800usb_config_wcid_attr ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_crypto * crypto ,
struct ieee80211_key_conf * key )
{
struct mac_wcid_entry wcid_entry ;
struct mac_iveiv_entry iveiv_entry ;
u32 offset ;
u32 reg ;
offset = MAC_WCID_ATTR_ENTRY ( key - > hw_key_idx ) ;
rt2x00usb_register_read ( rt2x00dev , offset , & reg ) ;
rt2x00_set_field32 ( & reg , MAC_WCID_ATTRIBUTE_KEYTAB ,
! ! ( key - > flags & IEEE80211_KEY_FLAG_PAIRWISE ) ) ;
rt2x00_set_field32 ( & reg , MAC_WCID_ATTRIBUTE_CIPHER ,
( crypto - > cmd = = SET_KEY ) * crypto - > cipher ) ;
rt2x00_set_field32 ( & reg , MAC_WCID_ATTRIBUTE_BSS_IDX ,
( crypto - > cmd = = SET_KEY ) * crypto - > bssidx ) ;
rt2x00_set_field32 ( & reg , MAC_WCID_ATTRIBUTE_RX_WIUDF , crypto - > cipher ) ;
rt2x00usb_register_write ( rt2x00dev , offset , reg ) ;
offset = MAC_IVEIV_ENTRY ( key - > hw_key_idx ) ;
memset ( & iveiv_entry , 0 , sizeof ( iveiv_entry ) ) ;
if ( ( crypto - > cipher = = CIPHER_TKIP ) | |
( crypto - > cipher = = CIPHER_TKIP_NO_MIC ) | |
( crypto - > cipher = = CIPHER_AES ) )
iveiv_entry . iv [ 3 ] | = 0x20 ;
iveiv_entry . iv [ 3 ] | = key - > keyidx < < 6 ;
rt2x00usb_register_multiwrite ( rt2x00dev , offset ,
& iveiv_entry , sizeof ( iveiv_entry ) ) ;
offset = MAC_WCID_ENTRY ( key - > hw_key_idx ) ;
memset ( & wcid_entry , 0 , sizeof ( wcid_entry ) ) ;
if ( crypto - > cmd = = SET_KEY )
memcpy ( & wcid_entry , crypto - > address , ETH_ALEN ) ;
rt2x00usb_register_multiwrite ( rt2x00dev , offset ,
& wcid_entry , sizeof ( wcid_entry ) ) ;
}
static int rt2800usb_config_shared_key ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_crypto * crypto ,
struct ieee80211_key_conf * key )
{
struct hw_key_entry key_entry ;
struct rt2x00_field32 field ;
int timeout ;
u32 offset ;
u32 reg ;
if ( crypto - > cmd = = SET_KEY ) {
key - > hw_key_idx = ( 4 * crypto - > bssidx ) + key - > keyidx ;
memcpy ( key_entry . key , crypto - > key ,
sizeof ( key_entry . key ) ) ;
memcpy ( key_entry . tx_mic , crypto - > tx_mic ,
sizeof ( key_entry . tx_mic ) ) ;
memcpy ( key_entry . rx_mic , crypto - > rx_mic ,
sizeof ( key_entry . rx_mic ) ) ;
offset = SHARED_KEY_ENTRY ( key - > hw_key_idx ) ;
timeout = REGISTER_TIMEOUT32 ( sizeof ( key_entry ) ) ;
rt2x00usb_vendor_request_large_buff ( rt2x00dev , USB_MULTI_WRITE ,
USB_VENDOR_REQUEST_OUT ,
offset , & key_entry ,
sizeof ( key_entry ) ,
timeout ) ;
}
/*
* The cipher types are stored over multiple registers
* starting with SHARED_KEY_MODE_BASE each word will have
* 32 bits and contains the cipher types for 2 bssidx each .
* Using the correct defines correctly will cause overhead ,
* so just calculate the correct offset .
*/
field . bit_offset = 4 * ( key - > hw_key_idx % 8 ) ;
field . bit_mask = 0x7 < < field . bit_offset ;
offset = SHARED_KEY_MODE_ENTRY ( key - > hw_key_idx / 8 ) ;
rt2x00usb_register_read ( rt2x00dev , offset , & reg ) ;
rt2x00_set_field32 ( & reg , field ,
( crypto - > cmd = = SET_KEY ) * crypto - > cipher ) ;
rt2x00usb_register_write ( rt2x00dev , offset , reg ) ;
/*
* Update WCID information
*/
rt2800usb_config_wcid_attr ( rt2x00dev , crypto , key ) ;
return 0 ;
}
static int rt2800usb_config_pairwise_key ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_crypto * crypto ,
struct ieee80211_key_conf * key )
{
struct hw_key_entry key_entry ;
int timeout ;
u32 offset ;
if ( crypto - > cmd = = SET_KEY ) {
/*
* 1 pairwise key is possible per AID , this means that the AID
* equals our hw_key_idx . Make sure the WCID starts _after_ the
* last possible shared key entry .
*/
if ( crypto - > aid > ( 256 - 32 ) )
return - ENOSPC ;
key - > hw_key_idx = 32 + crypto - > aid ;
memcpy ( key_entry . key , crypto - > key ,
sizeof ( key_entry . key ) ) ;
memcpy ( key_entry . tx_mic , crypto - > tx_mic ,
sizeof ( key_entry . tx_mic ) ) ;
memcpy ( key_entry . rx_mic , crypto - > rx_mic ,
sizeof ( key_entry . rx_mic ) ) ;
offset = PAIRWISE_KEY_ENTRY ( key - > hw_key_idx ) ;
timeout = REGISTER_TIMEOUT32 ( sizeof ( key_entry ) ) ;
rt2x00usb_vendor_request_large_buff ( rt2x00dev , USB_MULTI_WRITE ,
USB_VENDOR_REQUEST_OUT ,
offset , & key_entry ,
sizeof ( key_entry ) ,
timeout ) ;
}
/*
* Update WCID information
*/
rt2800usb_config_wcid_attr ( rt2x00dev , crypto , key ) ;
return 0 ;
}
static void rt2800usb_config_filter ( struct rt2x00_dev * rt2x00dev ,
const unsigned int filter_flags )
{
u32 reg ;
/*
* Start configuration steps .
* Note that the version error will always be dropped
* and broadcast frames will always be accepted since
* there is no filter for it at this time .
*/
rt2x00usb_register_read ( rt2x00dev , RX_FILTER_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_CRC_ERROR ,
! ( filter_flags & FIF_FCSFAIL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_PHY_ERROR ,
! ( filter_flags & FIF_PLCPFAIL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_NOT_TO_ME ,
! ( filter_flags & FIF_PROMISC_IN_BSS ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_NOT_MY_BSSD , 0 ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_VER_ERROR , 1 ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_MULTICAST ,
! ( filter_flags & FIF_ALLMULTI ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_BROADCAST , 0 ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_DUPLICATE , 1 ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_CF_END_ACK ,
! ( filter_flags & FIF_CONTROL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_CF_END ,
! ( filter_flags & FIF_CONTROL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_ACK ,
! ( filter_flags & FIF_CONTROL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_CTS ,
! ( filter_flags & FIF_CONTROL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_RTS ,
! ( filter_flags & FIF_CONTROL ) ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_PSPOLL ,
2009-08-08 23:55:55 +02:00
! ( filter_flags & FIF_PSPOLL ) ) ;
2009-04-26 15:47:48 +02:00
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_BA , 1 ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_BAR , 0 ) ;
rt2x00_set_field32 ( & reg , RX_FILTER_CFG_DROP_CNTL ,
! ( filter_flags & FIF_CONTROL ) ) ;
rt2x00usb_register_write ( rt2x00dev , RX_FILTER_CFG , reg ) ;
}
static void rt2800usb_config_intf ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00_intf * intf ,
struct rt2x00intf_conf * conf ,
const unsigned int flags )
{
unsigned int beacon_base ;
u32 reg ;
if ( flags & CONFIG_UPDATE_TYPE ) {
/*
* Clear current synchronisation setup .
* For the Beacon base registers we only need to clear
* the first byte since that byte contains the VALID and OWNER
* bits which ( when set to 0 ) will invalidate the entire beacon .
*/
beacon_base = HW_BEACON_OFFSET ( intf - > beacon - > entry_idx ) ;
rt2x00usb_register_write ( rt2x00dev , beacon_base , 0 ) ;
/*
* Enable synchronisation .
*/
rt2x00usb_register_read ( rt2x00dev , BCN_TIME_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TSF_TICKING , 1 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TSF_SYNC , conf - > sync ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TBTT_ENABLE , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , BCN_TIME_CFG , reg ) ;
}
if ( flags & CONFIG_UPDATE_MAC ) {
reg = le32_to_cpu ( conf - > mac [ 1 ] ) ;
rt2x00_set_field32 ( & reg , MAC_ADDR_DW1_UNICAST_TO_ME_MASK , 0xff ) ;
conf - > mac [ 1 ] = cpu_to_le32 ( reg ) ;
rt2x00usb_register_multiwrite ( rt2x00dev , MAC_ADDR_DW0 ,
conf - > mac , sizeof ( conf - > mac ) ) ;
}
if ( flags & CONFIG_UPDATE_BSSID ) {
reg = le32_to_cpu ( conf - > bssid [ 1 ] ) ;
rt2x00_set_field32 ( & reg , MAC_BSSID_DW1_BSS_ID_MASK , 0 ) ;
rt2x00_set_field32 ( & reg , MAC_BSSID_DW1_BSS_BCN_NUM , 0 ) ;
conf - > bssid [ 1 ] = cpu_to_le32 ( reg ) ;
rt2x00usb_register_multiwrite ( rt2x00dev , MAC_BSSID_DW0 ,
conf - > bssid , sizeof ( conf - > bssid ) ) ;
}
}
static void rt2800usb_config_erp ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_erp * erp )
{
u32 reg ;
rt2x00usb_register_read ( rt2x00dev , TX_TIMEOUT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_TIMEOUT_CFG_RX_ACK_TIMEOUT ,
DIV_ROUND_UP ( erp - > ack_timeout , erp - > slot_time ) ) ;
rt2x00usb_register_write ( rt2x00dev , TX_TIMEOUT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , AUTO_RSP_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_BAC_ACK_POLICY ,
! ! erp - > short_preamble ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_AR_PREAMBLE ,
! ! erp - > short_preamble ) ;
rt2x00usb_register_write ( rt2x00dev , AUTO_RSP_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , OFDM_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_PROTECT_CTRL ,
erp - > cts_protection ? 2 : 0 ) ;
rt2x00usb_register_write ( rt2x00dev , OFDM_PROT_CFG , reg ) ;
rt2x00usb_register_write ( rt2x00dev , LEGACY_BASIC_RATE ,
erp - > basic_rates ) ;
rt2x00usb_register_write ( rt2x00dev , HT_BASIC_RATE , 0x00008003 ) ;
rt2x00usb_register_read ( rt2x00dev , BKOFF_SLOT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , BKOFF_SLOT_CFG_SLOT_TIME , erp - > slot_time ) ;
rt2x00_set_field32 ( & reg , BKOFF_SLOT_CFG_CC_DELAY_TIME , 2 ) ;
rt2x00usb_register_write ( rt2x00dev , BKOFF_SLOT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , XIFS_TIME_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , XIFS_TIME_CFG_CCKM_SIFS_TIME , erp - > sifs ) ;
rt2x00_set_field32 ( & reg , XIFS_TIME_CFG_OFDM_SIFS_TIME , erp - > sifs ) ;
rt2x00_set_field32 ( & reg , XIFS_TIME_CFG_OFDM_XIFS_TIME , 4 ) ;
rt2x00_set_field32 ( & reg , XIFS_TIME_CFG_EIFS , erp - > eifs ) ;
rt2x00_set_field32 ( & reg , XIFS_TIME_CFG_BB_RXEND_ENABLE , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , XIFS_TIME_CFG , reg ) ;
2009-05-21 19:16:46 +02:00
rt2x00usb_register_read ( rt2x00dev , BCN_TIME_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_BEACON_INTERVAL ,
erp - > beacon_int * 16 ) ;
rt2x00usb_register_write ( rt2x00dev , BCN_TIME_CFG , reg ) ;
2009-04-26 15:47:48 +02:00
}
static void rt2800usb_config_ant ( struct rt2x00_dev * rt2x00dev ,
struct antenna_setup * ant )
{
u8 r1 ;
u8 r3 ;
rt2800usb_bbp_read ( rt2x00dev , 1 , & r1 ) ;
rt2800usb_bbp_read ( rt2x00dev , 3 , & r3 ) ;
/*
* Configure the TX antenna .
*/
switch ( ( int ) ant - > tx ) {
case 1 :
rt2x00_set_field8 ( & r1 , BBP1_TX_ANTENNA , 0 ) ;
break ;
case 2 :
rt2x00_set_field8 ( & r1 , BBP1_TX_ANTENNA , 2 ) ;
break ;
case 3 :
/* Do nothing */
break ;
}
/*
* Configure the RX antenna .
*/
switch ( ( int ) ant - > rx ) {
case 1 :
rt2x00_set_field8 ( & r3 , BBP3_RX_ANTENNA , 0 ) ;
break ;
case 2 :
rt2x00_set_field8 ( & r3 , BBP3_RX_ANTENNA , 1 ) ;
break ;
case 3 :
rt2x00_set_field8 ( & r3 , BBP3_RX_ANTENNA , 2 ) ;
break ;
}
rt2800usb_bbp_write ( rt2x00dev , 3 , r3 ) ;
rt2800usb_bbp_write ( rt2x00dev , 1 , r1 ) ;
}
static void rt2800usb_config_lna_gain ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_conf * libconf )
{
u16 eeprom ;
short lna_gain ;
if ( libconf - > rf . channel < = 14 ) {
rt2x00_eeprom_read ( rt2x00dev , EEPROM_LNA , & eeprom ) ;
lna_gain = rt2x00_get_field16 ( eeprom , EEPROM_LNA_BG ) ;
} else if ( libconf - > rf . channel < = 64 ) {
rt2x00_eeprom_read ( rt2x00dev , EEPROM_LNA , & eeprom ) ;
lna_gain = rt2x00_get_field16 ( eeprom , EEPROM_LNA_A0 ) ;
} else if ( libconf - > rf . channel < = 128 ) {
rt2x00_eeprom_read ( rt2x00dev , EEPROM_RSSI_BG2 , & eeprom ) ;
lna_gain = rt2x00_get_field16 ( eeprom , EEPROM_RSSI_BG2_LNA_A1 ) ;
} else {
rt2x00_eeprom_read ( rt2x00dev , EEPROM_RSSI_A2 , & eeprom ) ;
lna_gain = rt2x00_get_field16 ( eeprom , EEPROM_RSSI_A2_LNA_A2 ) ;
}
rt2x00dev - > lna_gain = lna_gain ;
}
static void rt2800usb_config_channel_rt2x ( struct rt2x00_dev * rt2x00dev ,
struct ieee80211_conf * conf ,
struct rf_channel * rf ,
struct channel_info * info )
{
rt2x00_set_field32 ( & rf - > rf4 , RF4_FREQ_OFFSET , rt2x00dev - > freq_offset ) ;
if ( rt2x00dev - > default_ant . tx = = 1 )
rt2x00_set_field32 ( & rf - > rf2 , RF2_ANTENNA_TX1 , 1 ) ;
if ( rt2x00dev - > default_ant . rx = = 1 ) {
rt2x00_set_field32 ( & rf - > rf2 , RF2_ANTENNA_RX1 , 1 ) ;
rt2x00_set_field32 ( & rf - > rf2 , RF2_ANTENNA_RX2 , 1 ) ;
} else if ( rt2x00dev - > default_ant . rx = = 2 )
rt2x00_set_field32 ( & rf - > rf2 , RF2_ANTENNA_RX2 , 1 ) ;
if ( rf - > channel > 14 ) {
/*
* When TX power is below 0 , we should increase it by 7 to
* make it a positive value ( Minumum value is - 7 ) .
* However this means that values between 0 and 7 have
* double meaning , and we should set a 7 DBm boost flag .
*/
rt2x00_set_field32 ( & rf - > rf3 , RF3_TXPOWER_A_7DBM_BOOST ,
( info - > tx_power1 > = 0 ) ) ;
if ( info - > tx_power1 < 0 )
info - > tx_power1 + = 7 ;
rt2x00_set_field32 ( & rf - > rf3 , RF3_TXPOWER_A ,
TXPOWER_A_TO_DEV ( info - > tx_power1 ) ) ;
rt2x00_set_field32 ( & rf - > rf4 , RF4_TXPOWER_A_7DBM_BOOST ,
( info - > tx_power2 > = 0 ) ) ;
if ( info - > tx_power2 < 0 )
info - > tx_power2 + = 7 ;
rt2x00_set_field32 ( & rf - > rf4 , RF4_TXPOWER_A ,
TXPOWER_A_TO_DEV ( info - > tx_power2 ) ) ;
} else {
rt2x00_set_field32 ( & rf - > rf3 , RF3_TXPOWER_G ,
TXPOWER_G_TO_DEV ( info - > tx_power1 ) ) ;
rt2x00_set_field32 ( & rf - > rf4 , RF4_TXPOWER_G ,
TXPOWER_G_TO_DEV ( info - > tx_power2 ) ) ;
}
rt2x00_set_field32 ( & rf - > rf4 , RF4_HT40 , conf_is_ht40 ( conf ) ) ;
rt2800usb_rf_write ( rt2x00dev , 1 , rf - > rf1 ) ;
rt2800usb_rf_write ( rt2x00dev , 2 , rf - > rf2 ) ;
rt2800usb_rf_write ( rt2x00dev , 3 , rf - > rf3 & ~ 0x00000004 ) ;
rt2800usb_rf_write ( rt2x00dev , 4 , rf - > rf4 ) ;
udelay ( 200 ) ;
rt2800usb_rf_write ( rt2x00dev , 1 , rf - > rf1 ) ;
rt2800usb_rf_write ( rt2x00dev , 2 , rf - > rf2 ) ;
rt2800usb_rf_write ( rt2x00dev , 3 , rf - > rf3 | 0x00000004 ) ;
rt2800usb_rf_write ( rt2x00dev , 4 , rf - > rf4 ) ;
udelay ( 200 ) ;
rt2800usb_rf_write ( rt2x00dev , 1 , rf - > rf1 ) ;
rt2800usb_rf_write ( rt2x00dev , 2 , rf - > rf2 ) ;
rt2800usb_rf_write ( rt2x00dev , 3 , rf - > rf3 & ~ 0x00000004 ) ;
rt2800usb_rf_write ( rt2x00dev , 4 , rf - > rf4 ) ;
}
static void rt2800usb_config_channel_rt3x ( struct rt2x00_dev * rt2x00dev ,
struct ieee80211_conf * conf ,
struct rf_channel * rf ,
struct channel_info * info )
{
u8 rfcsr ;
rt2800usb_rfcsr_write ( rt2x00dev , 2 , rf - > rf1 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 2 , rf - > rf3 ) ;
rt2800usb_rfcsr_read ( rt2x00dev , 6 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR6_R , rf - > rf2 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 6 , rfcsr ) ;
rt2800usb_rfcsr_read ( rt2x00dev , 12 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR12_TX_POWER ,
TXPOWER_G_TO_DEV ( info - > tx_power1 ) ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 12 , rfcsr ) ;
rt2800usb_rfcsr_read ( rt2x00dev , 23 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR23_FREQ_OFFSET , rt2x00dev - > freq_offset ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 23 , rfcsr ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 24 ,
rt2x00dev - > calibration [ conf_is_ht40 ( conf ) ] ) ;
rt2800usb_rfcsr_read ( rt2x00dev , 23 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR7_RF_TUNING , 1 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 23 , rfcsr ) ;
}
static void rt2800usb_config_channel ( struct rt2x00_dev * rt2x00dev ,
struct ieee80211_conf * conf ,
struct rf_channel * rf ,
struct channel_info * info )
{
u32 reg ;
unsigned int tx_pin ;
u8 bbp ;
if ( rt2x00_rev ( & rt2x00dev - > chip ) ! = RT3070_VERSION )
rt2800usb_config_channel_rt2x ( rt2x00dev , conf , rf , info ) ;
else
rt2800usb_config_channel_rt3x ( rt2x00dev , conf , rf , info ) ;
/*
* Change BBP settings
*/
rt2800usb_bbp_write ( rt2x00dev , 62 , 0x37 - rt2x00dev - > lna_gain ) ;
rt2800usb_bbp_write ( rt2x00dev , 63 , 0x37 - rt2x00dev - > lna_gain ) ;
rt2800usb_bbp_write ( rt2x00dev , 64 , 0x37 - rt2x00dev - > lna_gain ) ;
rt2800usb_bbp_write ( rt2x00dev , 86 , 0 ) ;
if ( rf - > channel < = 14 ) {
if ( test_bit ( CONFIG_EXTERNAL_LNA_BG , & rt2x00dev - > flags ) ) {
rt2800usb_bbp_write ( rt2x00dev , 82 , 0x62 ) ;
rt2800usb_bbp_write ( rt2x00dev , 75 , 0x46 ) ;
} else {
rt2800usb_bbp_write ( rt2x00dev , 82 , 0x84 ) ;
rt2800usb_bbp_write ( rt2x00dev , 75 , 0x50 ) ;
}
} else {
rt2800usb_bbp_write ( rt2x00dev , 82 , 0xf2 ) ;
if ( test_bit ( CONFIG_EXTERNAL_LNA_A , & rt2x00dev - > flags ) )
rt2800usb_bbp_write ( rt2x00dev , 75 , 0x46 ) ;
else
rt2800usb_bbp_write ( rt2x00dev , 75 , 0x50 ) ;
}
rt2x00usb_register_read ( rt2x00dev , TX_BAND_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_BAND_CFG_HT40_PLUS , conf_is_ht40_plus ( conf ) ) ;
rt2x00_set_field32 ( & reg , TX_BAND_CFG_A , rf - > channel > 14 ) ;
rt2x00_set_field32 ( & reg , TX_BAND_CFG_BG , rf - > channel < = 14 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_BAND_CFG , reg ) ;
tx_pin = 0 ;
/* Turn on unused PA or LNA when not using 1T or 1R */
if ( rt2x00dev - > default_ant . tx ! = 1 ) {
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_PA_PE_A1_EN , 1 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_PA_PE_G1_EN , 1 ) ;
}
/* Turn on unused PA or LNA when not using 1T or 1R */
if ( rt2x00dev - > default_ant . rx ! = 1 ) {
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_LNA_PE_A1_EN , 1 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_LNA_PE_G1_EN , 1 ) ;
}
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_LNA_PE_A0_EN , 1 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_LNA_PE_G0_EN , 1 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_RFTR_EN , 1 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_TRSW_EN , 1 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_PA_PE_G0_EN , rf - > channel < = 14 ) ;
rt2x00_set_field32 ( & tx_pin , TX_PIN_CFG_PA_PE_A0_EN , rf - > channel > 14 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PIN_CFG , tx_pin ) ;
rt2800usb_bbp_read ( rt2x00dev , 4 , & bbp ) ;
rt2x00_set_field8 ( & bbp , BBP4_BANDWIDTH , 2 * conf_is_ht40 ( conf ) ) ;
rt2800usb_bbp_write ( rt2x00dev , 4 , bbp ) ;
rt2800usb_bbp_read ( rt2x00dev , 3 , & bbp ) ;
rt2x00_set_field8 ( & bbp , BBP3_HT40_PLUS , conf_is_ht40_plus ( conf ) ) ;
rt2800usb_bbp_write ( rt2x00dev , 3 , bbp ) ;
if ( rt2x00_rev ( & rt2x00dev - > chip ) = = RT2860C_VERSION ) {
if ( conf_is_ht40 ( conf ) ) {
rt2800usb_bbp_write ( rt2x00dev , 69 , 0x1a ) ;
rt2800usb_bbp_write ( rt2x00dev , 70 , 0x0a ) ;
rt2800usb_bbp_write ( rt2x00dev , 73 , 0x16 ) ;
} else {
rt2800usb_bbp_write ( rt2x00dev , 69 , 0x16 ) ;
rt2800usb_bbp_write ( rt2x00dev , 70 , 0x08 ) ;
rt2800usb_bbp_write ( rt2x00dev , 73 , 0x11 ) ;
}
}
msleep ( 1 ) ;
}
static void rt2800usb_config_txpower ( struct rt2x00_dev * rt2x00dev ,
const int txpower )
{
u32 reg ;
u32 value = TXPOWER_G_TO_DEV ( txpower ) ;
u8 r1 ;
rt2800usb_bbp_read ( rt2x00dev , 1 , & r1 ) ;
rt2x00_set_field8 ( & reg , BBP1_TX_POWER , 0 ) ;
rt2800usb_bbp_write ( rt2x00dev , 1 , r1 ) ;
rt2x00usb_register_read ( rt2x00dev , TX_PWR_CFG_0 , & reg ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_1MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_2MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_55MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_11MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_6MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_9MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_12MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_0_18MBS , value ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PWR_CFG_0 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_PWR_CFG_1 , & reg ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_24MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_36MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_48MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_54MBS , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_MCS0 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_MCS1 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_MCS2 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_1_MCS3 , value ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PWR_CFG_1 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_PWR_CFG_2 , & reg ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS4 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS5 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS6 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS7 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS8 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS9 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS10 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_2_MCS11 , value ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PWR_CFG_2 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_PWR_CFG_3 , & reg ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_MCS12 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_MCS13 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_MCS14 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_MCS15 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_UKNOWN1 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_UKNOWN2 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_UKNOWN3 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_3_UKNOWN4 , value ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PWR_CFG_3 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_PWR_CFG_4 , & reg ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_4_UKNOWN5 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_4_UKNOWN6 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_4_UKNOWN7 , value ) ;
rt2x00_set_field32 ( & reg , TX_PWR_CFG_4_UKNOWN8 , value ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PWR_CFG_4 , reg ) ;
}
static void rt2800usb_config_retry_limit ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_conf * libconf )
{
u32 reg ;
rt2x00usb_register_read ( rt2x00dev , TX_RTY_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_RTY_CFG_SHORT_RTY_LIMIT ,
libconf - > conf - > short_frame_max_tx_count ) ;
rt2x00_set_field32 ( & reg , TX_RTY_CFG_LONG_RTY_LIMIT ,
libconf - > conf - > long_frame_max_tx_count ) ;
rt2x00_set_field32 ( & reg , TX_RTY_CFG_LONG_RTY_THRE , 2000 ) ;
rt2x00_set_field32 ( & reg , TX_RTY_CFG_NON_AGG_RTY_MODE , 0 ) ;
rt2x00_set_field32 ( & reg , TX_RTY_CFG_AGG_RTY_MODE , 0 ) ;
rt2x00_set_field32 ( & reg , TX_RTY_CFG_TX_AUTO_FB_ENABLE , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_RTY_CFG , reg ) ;
}
static void rt2800usb_config_ps ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_conf * libconf )
{
enum dev_state state =
( libconf - > conf - > flags & IEEE80211_CONF_PS ) ?
STATE_SLEEP : STATE_AWAKE ;
u32 reg ;
if ( state = = STATE_SLEEP ) {
rt2x00usb_register_write ( rt2x00dev , AUTOWAKEUP_CFG , 0 ) ;
rt2x00usb_register_read ( rt2x00dev , AUTOWAKEUP_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , AUTOWAKEUP_CFG_AUTO_LEAD_TIME , 5 ) ;
rt2x00_set_field32 ( & reg , AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE ,
libconf - > conf - > listen_interval - 1 ) ;
rt2x00_set_field32 ( & reg , AUTOWAKEUP_CFG_AUTOWAKE , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , AUTOWAKEUP_CFG , reg ) ;
2009-04-28 20:14:58 +02:00
rt2x00dev - > ops - > lib - > set_device_state ( rt2x00dev , state ) ;
2009-04-26 15:47:48 +02:00
} else {
2009-04-28 20:14:58 +02:00
rt2x00dev - > ops - > lib - > set_device_state ( rt2x00dev , state ) ;
2009-04-26 15:47:48 +02:00
rt2x00usb_register_read ( rt2x00dev , AUTOWAKEUP_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , AUTOWAKEUP_CFG_AUTO_LEAD_TIME , 0 ) ;
rt2x00_set_field32 ( & reg , AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE , 0 ) ;
rt2x00_set_field32 ( & reg , AUTOWAKEUP_CFG_AUTOWAKE , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , AUTOWAKEUP_CFG , reg ) ;
}
}
static void rt2800usb_config ( struct rt2x00_dev * rt2x00dev ,
struct rt2x00lib_conf * libconf ,
const unsigned int flags )
{
/* Always recalculate LNA gain before changing configuration */
rt2800usb_config_lna_gain ( rt2x00dev , libconf ) ;
if ( flags & IEEE80211_CONF_CHANGE_CHANNEL )
rt2800usb_config_channel ( rt2x00dev , libconf - > conf ,
& libconf - > rf , & libconf - > channel ) ;
if ( flags & IEEE80211_CONF_CHANGE_POWER )
rt2800usb_config_txpower ( rt2x00dev , libconf - > conf - > power_level ) ;
if ( flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS )
rt2800usb_config_retry_limit ( rt2x00dev , libconf ) ;
if ( flags & IEEE80211_CONF_CHANGE_PS )
rt2800usb_config_ps ( rt2x00dev , libconf ) ;
}
/*
* Link tuning
*/
static void rt2800usb_link_stats ( struct rt2x00_dev * rt2x00dev ,
struct link_qual * qual )
{
u32 reg ;
/*
* Update FCS error count from register .
*/
rt2x00usb_register_read ( rt2x00dev , RX_STA_CNT0 , & reg ) ;
qual - > rx_failed = rt2x00_get_field32 ( reg , RX_STA_CNT0_CRC_ERR ) ;
}
static u8 rt2800usb_get_default_vgc ( struct rt2x00_dev * rt2x00dev )
{
if ( rt2x00dev - > curr_band = = IEEE80211_BAND_2GHZ ) {
if ( rt2x00_rev ( & rt2x00dev - > chip ) = = RT3070_VERSION )
return 0x1c + ( 2 * rt2x00dev - > lna_gain ) ;
else
return 0x2e + rt2x00dev - > lna_gain ;
}
if ( ! test_bit ( CONFIG_CHANNEL_HT40 , & rt2x00dev - > flags ) )
return 0x32 + ( rt2x00dev - > lna_gain * 5 ) / 3 ;
else
return 0x3a + ( rt2x00dev - > lna_gain * 5 ) / 3 ;
}
static inline void rt2800usb_set_vgc ( struct rt2x00_dev * rt2x00dev ,
struct link_qual * qual , u8 vgc_level )
{
if ( qual - > vgc_level ! = vgc_level ) {
rt2800usb_bbp_write ( rt2x00dev , 66 , vgc_level ) ;
qual - > vgc_level = vgc_level ;
qual - > vgc_level_reg = vgc_level ;
}
}
static void rt2800usb_reset_tuner ( struct rt2x00_dev * rt2x00dev ,
struct link_qual * qual )
{
rt2800usb_set_vgc ( rt2x00dev , qual ,
rt2800usb_get_default_vgc ( rt2x00dev ) ) ;
}
static void rt2800usb_link_tuner ( struct rt2x00_dev * rt2x00dev ,
struct link_qual * qual , const u32 count )
{
if ( rt2x00_rev ( & rt2x00dev - > chip ) = = RT2860C_VERSION )
return ;
/*
* When RSSI is better then - 80 increase VGC level with 0x10
*/
rt2800usb_set_vgc ( rt2x00dev , qual ,
rt2800usb_get_default_vgc ( rt2x00dev ) +
( ( qual - > rssi > - 80 ) * 0x10 ) ) ;
}
/*
* Firmware functions
*/
static char * rt2800usb_get_firmware_name ( struct rt2x00_dev * rt2x00dev )
{
return FIRMWARE_RT2870 ;
}
static bool rt2800usb_check_crc ( const u8 * data , const size_t len )
{
u16 fw_crc ;
u16 crc ;
/*
* The last 2 bytes in the firmware array are the crc checksum itself ,
* this means that we should never pass those 2 bytes to the crc
* algorithm .
*/
fw_crc = ( data [ len - 2 ] < < 8 | data [ len - 1 ] ) ;
/*
* Use the crc ccitt algorithm .
* This will return the same value as the legacy driver which
* used bit ordering reversion on the both the firmware bytes
* before input input as well as on the final output .
* Obviously using crc ccitt directly is much more efficient .
*/
crc = crc_ccitt ( ~ 0 , data , len - 2 ) ;
/*
* There is a small difference between the crc - itu - t + bitrev and
* the crc - ccitt crc calculation . In the latter method the 2 bytes
* will be swapped , use swab16 to convert the crc to the correct
* value .
*/
crc = swab16 ( crc ) ;
return fw_crc = = crc ;
}
static int rt2800usb_check_firmware ( struct rt2x00_dev * rt2x00dev ,
const u8 * data , const size_t len )
{
u16 chipset = ( rt2x00_rev ( & rt2x00dev - > chip ) > > 16 ) & 0xffff ;
size_t offset = 0 ;
/*
* Firmware files :
* There are 2 variations of the rt2870 firmware .
* a ) size : 4 kb
* b ) size : 8 kb
* Note that ( b ) contains 2 seperate firmware blobs of 4 k
* within the file . The first blob is the same firmware as ( a ) ,
* but the second blob is for the additional chipsets .
*/
if ( len ! = 4096 & & len ! = 8192 )
return FW_BAD_LENGTH ;
/*
* Check if we need the upper 4 kb firmware data or not .
*/
if ( ( len = = 4096 ) & &
( chipset ! = 0x2860 ) & &
( chipset ! = 0x2872 ) & &
( chipset ! = 0x3070 ) )
return FW_BAD_VERSION ;
/*
* 8 kb firmware files must be checked as if it were
* 2 seperate firmware files .
*/
while ( offset < len ) {
if ( ! rt2800usb_check_crc ( data + offset , 4096 ) )
return FW_BAD_CRC ;
offset + = 4096 ;
}
return FW_OK ;
}
static int rt2800usb_load_firmware ( struct rt2x00_dev * rt2x00dev ,
const u8 * data , const size_t len )
{
unsigned int i ;
int status ;
u32 reg ;
u32 offset ;
u32 length ;
u16 chipset = ( rt2x00_rev ( & rt2x00dev - > chip ) > > 16 ) & 0xffff ;
/*
* Check which section of the firmware we need .
*/
2009-04-28 20:14:58 +02:00
if ( ( chipset = = 0x2860 ) | |
( chipset = = 0x2872 ) | |
( chipset = = 0x3070 ) ) {
2009-04-26 15:47:48 +02:00
offset = 0 ;
length = 4096 ;
} else {
offset = 4096 ;
length = 4096 ;
}
/*
* Wait for stable hardware .
*/
for ( i = 0 ; i < REGISTER_BUSY_COUNT ; i + + ) {
rt2x00usb_register_read ( rt2x00dev , MAC_CSR0 , & reg ) ;
if ( reg & & reg ! = ~ 0 )
break ;
msleep ( 1 ) ;
}
if ( i = = REGISTER_BUSY_COUNT ) {
ERROR ( rt2x00dev , " Unstable hardware. \n " ) ;
return - EBUSY ;
}
/*
* Write firmware to device .
*/
rt2x00usb_vendor_request_large_buff ( rt2x00dev , USB_MULTI_WRITE ,
USB_VENDOR_REQUEST_OUT ,
FIRMWARE_IMAGE_BASE ,
data + offset , length ,
REGISTER_TIMEOUT32 ( length ) ) ;
rt2x00usb_register_write ( rt2x00dev , H2M_MAILBOX_CID , ~ 0 ) ;
rt2x00usb_register_write ( rt2x00dev , H2M_MAILBOX_STATUS , ~ 0 ) ;
/*
* Send firmware request to device to load firmware ,
* we need to specify a long timeout time .
*/
status = rt2x00usb_vendor_request_sw ( rt2x00dev , USB_DEVICE_MODE ,
0 , USB_MODE_FIRMWARE ,
REGISTER_TIMEOUT_FIRMWARE ) ;
if ( status < 0 ) {
ERROR ( rt2x00dev , " Failed to write Firmware to device. \n " ) ;
return status ;
}
2009-04-28 20:14:58 +02:00
msleep ( 10 ) ;
rt2x00usb_register_write ( rt2x00dev , H2M_MAILBOX_CSR , 0 ) ;
/*
* Send signal to firmware during boot time .
*/
rt2800usb_mcu_request ( rt2x00dev , MCU_BOOT_SIGNAL , 0xff , 0 , 0 ) ;
if ( ( chipset = = 0x3070 ) | |
( chipset = = 0x3071 ) | |
( chipset = = 0x3572 ) ) {
udelay ( 200 ) ;
rt2800usb_mcu_request ( rt2x00dev , MCU_CURRENT , 0 , 0 , 0 ) ;
udelay ( 10 ) ;
}
2009-04-26 15:47:48 +02:00
/*
* Wait for device to stabilize .
*/
for ( i = 0 ; i < REGISTER_BUSY_COUNT ; i + + ) {
rt2x00usb_register_read ( rt2x00dev , PBF_SYS_CTRL , & reg ) ;
if ( rt2x00_get_field32 ( reg , PBF_SYS_CTRL_READY ) )
break ;
msleep ( 1 ) ;
}
if ( i = = REGISTER_BUSY_COUNT ) {
ERROR ( rt2x00dev , " PBF system register not ready. \n " ) ;
return - EBUSY ;
}
/*
* Initialize firmware .
*/
rt2x00usb_register_write ( rt2x00dev , H2M_BBP_AGENT , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , H2M_MAILBOX_CSR , 0 ) ;
msleep ( 1 ) ;
return 0 ;
}
/*
* Initialization functions .
*/
static int rt2800usb_init_registers ( struct rt2x00_dev * rt2x00dev )
{
u32 reg ;
unsigned int i ;
/*
* Wait untill BBP and RF are ready .
*/
for ( i = 0 ; i < REGISTER_BUSY_COUNT ; i + + ) {
rt2x00usb_register_read ( rt2x00dev , MAC_CSR0 , & reg ) ;
if ( reg & & reg ! = ~ 0 )
break ;
msleep ( 1 ) ;
}
if ( i = = REGISTER_BUSY_COUNT ) {
ERROR ( rt2x00dev , " Unstable hardware. \n " ) ;
return - EBUSY ;
}
rt2x00usb_register_read ( rt2x00dev , PBF_SYS_CTRL , & reg ) ;
rt2x00usb_register_write ( rt2x00dev , PBF_SYS_CTRL , reg & ~ 0x00002000 ) ;
rt2x00usb_register_read ( rt2x00dev , MAC_SYS_CTRL , & reg ) ;
rt2x00_set_field32 ( & reg , MAC_SYS_CTRL_RESET_CSR , 1 ) ;
rt2x00_set_field32 ( & reg , MAC_SYS_CTRL_RESET_BBP , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , reg ) ;
rt2x00usb_register_write ( rt2x00dev , USB_DMA_CFG , 0x00000000 ) ;
rt2x00usb_vendor_request_sw ( rt2x00dev , USB_DEVICE_MODE , 0 ,
USB_MODE_RESET , REGISTER_TIMEOUT ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , 0x00000000 ) ;
rt2x00usb_register_read ( rt2x00dev , BCN_OFFSET0 , & reg ) ;
rt2x00_set_field32 ( & reg , BCN_OFFSET0_BCN0 , 0xe0 ) ; /* 0x3800 */
rt2x00_set_field32 ( & reg , BCN_OFFSET0_BCN1 , 0xe8 ) ; /* 0x3a00 */
rt2x00_set_field32 ( & reg , BCN_OFFSET0_BCN2 , 0xf0 ) ; /* 0x3c00 */
rt2x00_set_field32 ( & reg , BCN_OFFSET0_BCN3 , 0xf8 ) ; /* 0x3e00 */
rt2x00usb_register_write ( rt2x00dev , BCN_OFFSET0 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , BCN_OFFSET1 , & reg ) ;
rt2x00_set_field32 ( & reg , BCN_OFFSET1_BCN4 , 0xc8 ) ; /* 0x3200 */
rt2x00_set_field32 ( & reg , BCN_OFFSET1_BCN5 , 0xd0 ) ; /* 0x3400 */
rt2x00_set_field32 ( & reg , BCN_OFFSET1_BCN6 , 0x77 ) ; /* 0x1dc0 */
rt2x00_set_field32 ( & reg , BCN_OFFSET1_BCN7 , 0x6f ) ; /* 0x1bc0 */
rt2x00usb_register_write ( rt2x00dev , BCN_OFFSET1 , reg ) ;
rt2x00usb_register_write ( rt2x00dev , LEGACY_BASIC_RATE , 0x0000013f ) ;
rt2x00usb_register_write ( rt2x00dev , HT_BASIC_RATE , 0x00008003 ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , 0x00000000 ) ;
rt2x00usb_register_read ( rt2x00dev , BCN_TIME_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_BEACON_INTERVAL , 0 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TSF_TICKING , 0 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TSF_SYNC , 0 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TBTT_ENABLE , 0 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_BEACON_GEN , 0 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TX_TIME_COMPENSATE , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , BCN_TIME_CFG , reg ) ;
if ( rt2x00_rev ( & rt2x00dev - > chip ) = = RT3070_VERSION ) {
rt2x00usb_register_write ( rt2x00dev , TX_SW_CFG0 , 0x00000400 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_SW_CFG1 , 0x00000000 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_SW_CFG2 , 0x00000000 ) ;
} else {
rt2x00usb_register_write ( rt2x00dev , TX_SW_CFG0 , 0x00000000 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_SW_CFG1 , 0x00080606 ) ;
}
rt2x00usb_register_read ( rt2x00dev , TX_LINK_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_REMOTE_MFB_LIFETIME , 32 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_MFB_ENABLE , 0 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_REMOTE_UMFS_ENABLE , 0 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_TX_MRQ_EN , 0 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_TX_RDG_EN , 0 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_TX_CF_ACK_EN , 1 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_REMOTE_MFB , 0 ) ;
rt2x00_set_field32 ( & reg , TX_LINK_CFG_REMOTE_MFS , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_LINK_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_TIMEOUT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_TIMEOUT_CFG_MPDU_LIFETIME , 9 ) ;
rt2x00_set_field32 ( & reg , TX_TIMEOUT_CFG_TX_OP_TIMEOUT , 10 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_TIMEOUT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , MAX_LEN_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , MAX_LEN_CFG_MAX_MPDU , AGGREGATION_SIZE ) ;
if ( rt2x00_rev ( & rt2x00dev - > chip ) > = RT2880E_VERSION & &
rt2x00_rev ( & rt2x00dev - > chip ) < RT3070_VERSION )
rt2x00_set_field32 ( & reg , MAX_LEN_CFG_MAX_PSDU , 2 ) ;
else
rt2x00_set_field32 ( & reg , MAX_LEN_CFG_MAX_PSDU , 1 ) ;
rt2x00_set_field32 ( & reg , MAX_LEN_CFG_MIN_PSDU , 0 ) ;
rt2x00_set_field32 ( & reg , MAX_LEN_CFG_MIN_MPDU , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , MAX_LEN_CFG , reg ) ;
rt2x00usb_register_write ( rt2x00dev , PBF_MAX_PCNT , 0x1f3fbf9f ) ;
rt2x00usb_register_read ( rt2x00dev , AUTO_RSP_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_AUTORESPONDER , 1 ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_CTS_40_MMODE , 0 ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_CTS_40_MREF , 0 ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_DUAL_CTS_EN , 0 ) ;
rt2x00_set_field32 ( & reg , AUTO_RSP_CFG_ACK_CTS_PSM_BIT , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , AUTO_RSP_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , CCK_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_PROTECT_RATE , 8 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_PROTECT_CTRL , 0 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_PROTECT_NAV , 1 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_TX_OP_ALLOW_CCK , 1 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_TX_OP_ALLOW_OFDM , 1 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_TX_OP_ALLOW_MM20 , 1 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_TX_OP_ALLOW_MM40 , 1 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_TX_OP_ALLOW_GF20 , 1 ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_TX_OP_ALLOW_GF40 , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , CCK_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , OFDM_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_PROTECT_RATE , 8 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_PROTECT_CTRL , 0 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_PROTECT_NAV , 1 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_TX_OP_ALLOW_CCK , 1 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_TX_OP_ALLOW_OFDM , 1 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_TX_OP_ALLOW_MM20 , 1 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_TX_OP_ALLOW_MM40 , 1 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_TX_OP_ALLOW_GF20 , 1 ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_TX_OP_ALLOW_GF40 , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , OFDM_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , MM20_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_PROTECT_RATE , 0x4004 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_PROTECT_CTRL , 0 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_PROTECT_NAV , 1 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_TX_OP_ALLOW_CCK , 1 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_TX_OP_ALLOW_OFDM , 1 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_TX_OP_ALLOW_MM20 , 1 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_TX_OP_ALLOW_MM40 , 0 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_TX_OP_ALLOW_GF20 , 1 ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_TX_OP_ALLOW_GF40 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , MM20_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , MM40_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_PROTECT_RATE , 0x4084 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_PROTECT_CTRL , 0 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_PROTECT_NAV , 1 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_TX_OP_ALLOW_CCK , 1 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_TX_OP_ALLOW_OFDM , 1 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_TX_OP_ALLOW_MM20 , 1 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_TX_OP_ALLOW_MM40 , 1 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_TX_OP_ALLOW_GF20 , 1 ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_TX_OP_ALLOW_GF40 , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , MM40_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , GF20_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_PROTECT_RATE , 0x4004 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_PROTECT_CTRL , 0 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_PROTECT_NAV , 1 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_TX_OP_ALLOW_CCK , 1 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_TX_OP_ALLOW_OFDM , 1 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_TX_OP_ALLOW_MM20 , 1 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_TX_OP_ALLOW_MM40 , 0 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_TX_OP_ALLOW_GF20 , 1 ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_TX_OP_ALLOW_GF40 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , GF20_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , GF40_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_PROTECT_RATE , 0x4084 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_PROTECT_CTRL , 0 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_PROTECT_NAV , 1 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_TX_OP_ALLOW_CCK , 1 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_TX_OP_ALLOW_OFDM , 1 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_TX_OP_ALLOW_MM20 , 1 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_TX_OP_ALLOW_MM40 , 1 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_TX_OP_ALLOW_GF20 , 1 ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_TX_OP_ALLOW_GF40 , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , GF40_PROT_CFG , reg ) ;
rt2x00usb_register_write ( rt2x00dev , PBF_CFG , 0xf40006 ) ;
rt2x00usb_register_read ( rt2x00dev , WPDMA_GLO_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_ENABLE_TX_DMA , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_TX_DMA_BUSY , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_ENABLE_RX_DMA , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_RX_DMA_BUSY , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_WP_DMA_BURST_SIZE , 3 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_TX_WRITEBACK_DONE , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_BIG_ENDIAN , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_RX_HDR_SCATTER , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_HDR_SEG_LEN , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , WPDMA_GLO_CFG , reg ) ;
rt2x00usb_register_write ( rt2x00dev , TXOP_CTRL_CFG , 0x0000583f ) ;
rt2x00usb_register_write ( rt2x00dev , TXOP_HLDR_ET , 0x00000002 ) ;
rt2x00usb_register_read ( rt2x00dev , TX_RTS_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT , 32 ) ;
rt2x00_set_field32 ( & reg , TX_RTS_CFG_RTS_THRES ,
IEEE80211_MAX_RTS_THRESHOLD ) ;
rt2x00_set_field32 ( & reg , TX_RTS_CFG_RTS_FBK_EN , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_RTS_CFG , reg ) ;
rt2x00usb_register_write ( rt2x00dev , EXP_ACK_TIME , 0x002400ca ) ;
rt2x00usb_register_write ( rt2x00dev , PWR_PIN_CFG , 0x00000003 ) ;
/*
* ASIC will keep garbage value after boot , clear encryption keys .
*/
2009-08-17 18:53:57 +02:00
for ( i = 0 ; i < 4 ; i + + )
rt2x00usb_register_write ( rt2x00dev ,
SHARED_KEY_MODE_ENTRY ( i ) , 0 ) ;
2009-04-26 15:47:48 +02:00
for ( i = 0 ; i < 256 ; i + + ) {
u32 wcid [ 2 ] = { 0xffffffff , 0x00ffffff } ;
rt2x00usb_register_multiwrite ( rt2x00dev , MAC_WCID_ENTRY ( i ) ,
wcid , sizeof ( wcid ) ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_WCID_ATTR_ENTRY ( i ) , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_IVEIV_ENTRY ( i ) , 0 ) ;
}
/*
* Clear all beacons
* For the Beacon base registers we only need to clear
* the first byte since that byte contains the VALID and OWNER
* bits which ( when set to 0 ) will invalidate the entire beacon .
*/
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE0 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE1 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE2 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE3 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE4 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE5 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE6 , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , HW_BEACON_BASE7 , 0 ) ;
rt2x00usb_register_read ( rt2x00dev , USB_CYC_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , USB_CYC_CFG_CLOCK_CYCLE , 30 ) ;
rt2x00usb_register_write ( rt2x00dev , USB_CYC_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , HT_FBK_CFG0 , & reg ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS0FBK , 0 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS1FBK , 0 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS2FBK , 1 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS3FBK , 2 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS4FBK , 3 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS5FBK , 4 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS6FBK , 5 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG0_HTMCS7FBK , 6 ) ;
rt2x00usb_register_write ( rt2x00dev , HT_FBK_CFG0 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , HT_FBK_CFG1 , & reg ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS8FBK , 8 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS9FBK , 8 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS10FBK , 9 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS11FBK , 10 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS12FBK , 11 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS13FBK , 12 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS14FBK , 13 ) ;
rt2x00_set_field32 ( & reg , HT_FBK_CFG1_HTMCS15FBK , 14 ) ;
rt2x00usb_register_write ( rt2x00dev , HT_FBK_CFG1 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , LG_FBK_CFG0 , & reg ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS0FBK , 8 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS1FBK , 8 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS2FBK , 3 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS3FBK , 10 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS4FBK , 11 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS5FBK , 12 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS6FBK , 13 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_OFDMMCS7FBK , 14 ) ;
rt2x00usb_register_write ( rt2x00dev , LG_FBK_CFG0 , reg ) ;
rt2x00usb_register_read ( rt2x00dev , LG_FBK_CFG1 , & reg ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_CCKMCS0FBK , 0 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_CCKMCS1FBK , 0 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_CCKMCS2FBK , 1 ) ;
rt2x00_set_field32 ( & reg , LG_FBK_CFG0_CCKMCS3FBK , 2 ) ;
rt2x00usb_register_write ( rt2x00dev , LG_FBK_CFG1 , reg ) ;
/*
* We must clear the error counters .
* These registers are cleared on read ,
* so we may pass a useless variable to store the value .
*/
rt2x00usb_register_read ( rt2x00dev , RX_STA_CNT0 , & reg ) ;
rt2x00usb_register_read ( rt2x00dev , RX_STA_CNT1 , & reg ) ;
rt2x00usb_register_read ( rt2x00dev , RX_STA_CNT2 , & reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_STA_CNT0 , & reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_STA_CNT1 , & reg ) ;
rt2x00usb_register_read ( rt2x00dev , TX_STA_CNT2 , & reg ) ;
return 0 ;
}
static int rt2800usb_wait_bbp_rf_ready ( struct rt2x00_dev * rt2x00dev )
{
unsigned int i ;
u32 reg ;
for ( i = 0 ; i < REGISTER_BUSY_COUNT ; i + + ) {
rt2x00usb_register_read ( rt2x00dev , MAC_STATUS_CFG , & reg ) ;
if ( ! rt2x00_get_field32 ( reg , MAC_STATUS_CFG_BBP_RF_BUSY ) )
return 0 ;
udelay ( REGISTER_BUSY_DELAY ) ;
}
ERROR ( rt2x00dev , " BBP/RF register access failed, aborting. \n " ) ;
return - EACCES ;
}
static int rt2800usb_wait_bbp_ready ( struct rt2x00_dev * rt2x00dev )
{
unsigned int i ;
u8 value ;
2009-04-28 20:14:58 +02:00
/*
* BBP was enabled after firmware was loaded ,
* but we need to reactivate it now .
*/
rt2x00usb_register_write ( rt2x00dev , H2M_BBP_AGENT , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , H2M_MAILBOX_CSR , 0 ) ;
msleep ( 1 ) ;
2009-04-26 15:47:48 +02:00
for ( i = 0 ; i < REGISTER_BUSY_COUNT ; i + + ) {
rt2800usb_bbp_read ( rt2x00dev , 0 , & value ) ;
if ( ( value ! = 0xff ) & & ( value ! = 0x00 ) )
return 0 ;
udelay ( REGISTER_BUSY_DELAY ) ;
}
ERROR ( rt2x00dev , " BBP register access failed, aborting. \n " ) ;
return - EACCES ;
}
static int rt2800usb_init_bbp ( struct rt2x00_dev * rt2x00dev )
{
unsigned int i ;
u16 eeprom ;
u8 reg_id ;
u8 value ;
if ( unlikely ( rt2800usb_wait_bbp_rf_ready ( rt2x00dev ) | |
rt2800usb_wait_bbp_ready ( rt2x00dev ) ) )
return - EACCES ;
rt2800usb_bbp_write ( rt2x00dev , 65 , 0x2c ) ;
rt2800usb_bbp_write ( rt2x00dev , 66 , 0x38 ) ;
rt2800usb_bbp_write ( rt2x00dev , 69 , 0x12 ) ;
rt2800usb_bbp_write ( rt2x00dev , 70 , 0x0a ) ;
rt2800usb_bbp_write ( rt2x00dev , 73 , 0x10 ) ;
rt2800usb_bbp_write ( rt2x00dev , 81 , 0x37 ) ;
rt2800usb_bbp_write ( rt2x00dev , 82 , 0x62 ) ;
rt2800usb_bbp_write ( rt2x00dev , 83 , 0x6a ) ;
rt2800usb_bbp_write ( rt2x00dev , 84 , 0x99 ) ;
rt2800usb_bbp_write ( rt2x00dev , 86 , 0x00 ) ;
rt2800usb_bbp_write ( rt2x00dev , 91 , 0x04 ) ;
rt2800usb_bbp_write ( rt2x00dev , 92 , 0x00 ) ;
rt2800usb_bbp_write ( rt2x00dev , 103 , 0x00 ) ;
rt2800usb_bbp_write ( rt2x00dev , 105 , 0x05 ) ;
if ( rt2x00_rev ( & rt2x00dev - > chip ) = = RT2860C_VERSION ) {
rt2800usb_bbp_write ( rt2x00dev , 69 , 0x16 ) ;
rt2800usb_bbp_write ( rt2x00dev , 73 , 0x12 ) ;
}
if ( rt2x00_rev ( & rt2x00dev - > chip ) > RT2860D_VERSION ) {
rt2800usb_bbp_write ( rt2x00dev , 84 , 0x19 ) ;
}
if ( rt2x00_rev ( & rt2x00dev - > chip ) = = RT3070_VERSION ) {
rt2800usb_bbp_write ( rt2x00dev , 70 , 0x0a ) ;
rt2800usb_bbp_write ( rt2x00dev , 84 , 0x99 ) ;
rt2800usb_bbp_write ( rt2x00dev , 105 , 0x05 ) ;
}
for ( i = 0 ; i < EEPROM_BBP_SIZE ; i + + ) {
rt2x00_eeprom_read ( rt2x00dev , EEPROM_BBP_START + i , & eeprom ) ;
if ( eeprom ! = 0xffff & & eeprom ! = 0x0000 ) {
reg_id = rt2x00_get_field16 ( eeprom , EEPROM_BBP_REG_ID ) ;
value = rt2x00_get_field16 ( eeprom , EEPROM_BBP_VALUE ) ;
rt2800usb_bbp_write ( rt2x00dev , reg_id , value ) ;
}
}
return 0 ;
}
static u8 rt2800usb_init_rx_filter ( struct rt2x00_dev * rt2x00dev ,
bool bw40 , u8 rfcsr24 , u8 filter_target )
{
unsigned int i ;
u8 bbp ;
u8 rfcsr ;
u8 passband ;
u8 stopband ;
u8 overtuned = 0 ;
rt2800usb_rfcsr_write ( rt2x00dev , 24 , rfcsr24 ) ;
rt2800usb_bbp_read ( rt2x00dev , 4 , & bbp ) ;
rt2x00_set_field8 ( & bbp , BBP4_BANDWIDTH , 2 * bw40 ) ;
rt2800usb_bbp_write ( rt2x00dev , 4 , bbp ) ;
rt2800usb_rfcsr_read ( rt2x00dev , 22 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR22_BASEBAND_LOOPBACK , 1 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 22 , rfcsr ) ;
/*
* Set power & frequency of passband test tone
*/
rt2800usb_bbp_write ( rt2x00dev , 24 , 0 ) ;
for ( i = 0 ; i < 100 ; i + + ) {
rt2800usb_bbp_write ( rt2x00dev , 25 , 0x90 ) ;
msleep ( 1 ) ;
rt2800usb_bbp_read ( rt2x00dev , 55 , & passband ) ;
if ( passband )
break ;
}
/*
* Set power & frequency of stopband test tone
*/
rt2800usb_bbp_write ( rt2x00dev , 24 , 0x06 ) ;
for ( i = 0 ; i < 100 ; i + + ) {
rt2800usb_bbp_write ( rt2x00dev , 25 , 0x90 ) ;
msleep ( 1 ) ;
rt2800usb_bbp_read ( rt2x00dev , 55 , & stopband ) ;
if ( ( passband - stopband ) < = filter_target ) {
rfcsr24 + + ;
overtuned + = ( ( passband - stopband ) = = filter_target ) ;
} else
break ;
rt2800usb_rfcsr_write ( rt2x00dev , 24 , rfcsr24 ) ;
}
rfcsr24 - = ! ! overtuned ;
rt2800usb_rfcsr_write ( rt2x00dev , 24 , rfcsr24 ) ;
return rfcsr24 ;
}
static int rt2800usb_init_rfcsr ( struct rt2x00_dev * rt2x00dev )
{
u8 rfcsr ;
u8 bbp ;
if ( rt2x00_rev ( & rt2x00dev - > chip ) ! = RT3070_VERSION )
return 0 ;
/*
* Init RF calibration .
*/
rt2800usb_rfcsr_read ( rt2x00dev , 30 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR30_RF_CALIBRATION , 1 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 30 , rfcsr ) ;
msleep ( 1 ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR30_RF_CALIBRATION , 0 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 30 , rfcsr ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 4 , 0x40 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 5 , 0x03 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 6 , 0x02 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 7 , 0x70 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 9 , 0x0f ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 10 , 0x71 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 11 , 0x21 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 12 , 0x7b ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 14 , 0x90 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 15 , 0x58 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 16 , 0xb3 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 17 , 0x92 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 18 , 0x2c ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 19 , 0x02 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 20 , 0xba ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 21 , 0xdb ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 24 , 0x16 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 25 , 0x01 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 27 , 0x03 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 29 , 0x1f ) ;
/*
* Set RX Filter calibration for 20 MHz and 40 MHz
*/
rt2x00dev - > calibration [ 0 ] =
rt2800usb_init_rx_filter ( rt2x00dev , false , 0x07 , 0x16 ) ;
rt2x00dev - > calibration [ 1 ] =
rt2800usb_init_rx_filter ( rt2x00dev , true , 0x27 , 0x19 ) ;
/*
* Set back to initial state
*/
rt2800usb_bbp_write ( rt2x00dev , 24 , 0 ) ;
rt2800usb_rfcsr_read ( rt2x00dev , 22 , & rfcsr ) ;
rt2x00_set_field8 ( & rfcsr , RFCSR22_BASEBAND_LOOPBACK , 0 ) ;
rt2800usb_rfcsr_write ( rt2x00dev , 22 , rfcsr ) ;
/*
* set BBP back to BW20
*/
rt2800usb_bbp_read ( rt2x00dev , 4 , & bbp ) ;
rt2x00_set_field8 ( & bbp , BBP4_BANDWIDTH , 0 ) ;
rt2800usb_bbp_write ( rt2x00dev , 4 , bbp ) ;
return 0 ;
}
/*
* Device state switch handlers .
*/
static void rt2800usb_toggle_rx ( struct rt2x00_dev * rt2x00dev ,
enum dev_state state )
{
u32 reg ;
rt2x00usb_register_read ( rt2x00dev , MAC_SYS_CTRL , & reg ) ;
rt2x00_set_field32 ( & reg , MAC_SYS_CTRL_ENABLE_RX ,
( state = = STATE_RADIO_RX_ON ) | |
( state = = STATE_RADIO_RX_ON_LINK ) ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , reg ) ;
}
static int rt2800usb_wait_wpdma_ready ( struct rt2x00_dev * rt2x00dev )
{
unsigned int i ;
u32 reg ;
for ( i = 0 ; i < REGISTER_BUSY_COUNT ; i + + ) {
rt2x00usb_register_read ( rt2x00dev , WPDMA_GLO_CFG , & reg ) ;
if ( ! rt2x00_get_field32 ( reg , WPDMA_GLO_CFG_TX_DMA_BUSY ) & &
! rt2x00_get_field32 ( reg , WPDMA_GLO_CFG_RX_DMA_BUSY ) )
return 0 ;
msleep ( 1 ) ;
}
ERROR ( rt2x00dev , " WPDMA TX/RX busy, aborting. \n " ) ;
return - EACCES ;
}
static int rt2800usb_enable_radio ( struct rt2x00_dev * rt2x00dev )
{
u32 reg ;
u16 word ;
/*
* Initialize all registers .
*/
if ( unlikely ( rt2800usb_wait_wpdma_ready ( rt2x00dev ) | |
rt2800usb_init_registers ( rt2x00dev ) | |
rt2800usb_init_bbp ( rt2x00dev ) | |
rt2800usb_init_rfcsr ( rt2x00dev ) ) )
return - EIO ;
rt2x00usb_register_read ( rt2x00dev , MAC_SYS_CTRL , & reg ) ;
rt2x00_set_field32 ( & reg , MAC_SYS_CTRL_ENABLE_TX , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , reg ) ;
udelay ( 50 ) ;
rt2x00usb_register_read ( rt2x00dev , WPDMA_GLO_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_TX_WRITEBACK_DONE , 1 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_ENABLE_RX_DMA , 1 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_ENABLE_TX_DMA , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , WPDMA_GLO_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , USB_DMA_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , USB_DMA_CFG_PHY_CLEAR , 0 ) ;
/* Don't use bulk in aggregation when working with USB 1.1 */
rt2x00_set_field32 ( & reg , USB_DMA_CFG_RX_BULK_AGG_EN ,
( rt2x00dev - > rx - > usb_maxpacket = = 512 ) ) ;
rt2x00_set_field32 ( & reg , USB_DMA_CFG_RX_BULK_AGG_TIMEOUT , 128 ) ;
2009-04-28 20:14:58 +02:00
/*
* Total room for RX frames in kilobytes , PBF might still exceed
* this limit so reduce the number to prevent errors .
*/
rt2x00_set_field32 ( & reg , USB_DMA_CFG_RX_BULK_AGG_LIMIT ,
( ( RX_ENTRIES * DATA_FRAME_SIZE ) / 1024 ) - 3 ) ;
2009-04-26 15:47:48 +02:00
rt2x00_set_field32 ( & reg , USB_DMA_CFG_RX_BULK_EN , 1 ) ;
rt2x00_set_field32 ( & reg , USB_DMA_CFG_TX_BULK_EN , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , USB_DMA_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , MAC_SYS_CTRL , & reg ) ;
rt2x00_set_field32 ( & reg , MAC_SYS_CTRL_ENABLE_TX , 1 ) ;
rt2x00_set_field32 ( & reg , MAC_SYS_CTRL_ENABLE_RX , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , reg ) ;
/*
* Initialize LED control
*/
rt2x00_eeprom_read ( rt2x00dev , EEPROM_LED1 , & word ) ;
rt2800usb_mcu_request ( rt2x00dev , MCU_LED_1 , 0xff ,
word & 0xff , ( word > > 8 ) & 0xff ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_LED2 , & word ) ;
rt2800usb_mcu_request ( rt2x00dev , MCU_LED_2 , 0xff ,
word & 0xff , ( word > > 8 ) & 0xff ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_LED3 , & word ) ;
rt2800usb_mcu_request ( rt2x00dev , MCU_LED_3 , 0xff ,
word & 0xff , ( word > > 8 ) & 0xff ) ;
return 0 ;
}
static void rt2800usb_disable_radio ( struct rt2x00_dev * rt2x00dev )
{
u32 reg ;
rt2x00usb_register_read ( rt2x00dev , WPDMA_GLO_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_ENABLE_TX_DMA , 0 ) ;
rt2x00_set_field32 ( & reg , WPDMA_GLO_CFG_ENABLE_RX_DMA , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , WPDMA_GLO_CFG , reg ) ;
rt2x00usb_register_write ( rt2x00dev , MAC_SYS_CTRL , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , PWR_PIN_CFG , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , TX_PIN_CFG , 0 ) ;
/* Wait for DMA, ignore error */
rt2800usb_wait_wpdma_ready ( rt2x00dev ) ;
rt2x00usb_disable_radio ( rt2x00dev ) ;
}
static int rt2800usb_set_state ( struct rt2x00_dev * rt2x00dev ,
enum dev_state state )
{
if ( state = = STATE_AWAKE )
rt2800usb_mcu_request ( rt2x00dev , MCU_WAKEUP , 0xff , 0 , 0 ) ;
else
rt2800usb_mcu_request ( rt2x00dev , MCU_SLEEP , 0xff , 0 , 2 ) ;
return 0 ;
}
static int rt2800usb_set_device_state ( struct rt2x00_dev * rt2x00dev ,
enum dev_state state )
{
int retval = 0 ;
switch ( state ) {
case STATE_RADIO_ON :
/*
* Before the radio can be enabled , the device first has
* to be woken up . After that it needs a bit of time
2009-07-17 21:39:19 +02:00
* to be fully awake and then the radio can be enabled .
2009-04-26 15:47:48 +02:00
*/
rt2800usb_set_state ( rt2x00dev , STATE_AWAKE ) ;
msleep ( 1 ) ;
retval = rt2800usb_enable_radio ( rt2x00dev ) ;
break ;
case STATE_RADIO_OFF :
/*
2009-07-17 21:39:19 +02:00
* After the radio has been disabled , the device should
2009-04-26 15:47:48 +02:00
* be put to sleep for powersaving .
*/
rt2800usb_disable_radio ( rt2x00dev ) ;
rt2800usb_set_state ( rt2x00dev , STATE_SLEEP ) ;
break ;
case STATE_RADIO_RX_ON :
case STATE_RADIO_RX_ON_LINK :
case STATE_RADIO_RX_OFF :
case STATE_RADIO_RX_OFF_LINK :
rt2800usb_toggle_rx ( rt2x00dev , state ) ;
break ;
case STATE_RADIO_IRQ_ON :
case STATE_RADIO_IRQ_OFF :
/* No support, but no error either */
break ;
case STATE_DEEP_SLEEP :
case STATE_SLEEP :
case STATE_STANDBY :
case STATE_AWAKE :
retval = rt2800usb_set_state ( rt2x00dev , state ) ;
break ;
default :
retval = - ENOTSUPP ;
break ;
}
if ( unlikely ( retval ) )
ERROR ( rt2x00dev , " Device failed to enter state %d (%d). \n " ,
state , retval ) ;
return retval ;
}
/*
* TX descriptor initialization
*/
static void rt2800usb_write_tx_desc ( struct rt2x00_dev * rt2x00dev ,
struct sk_buff * skb ,
struct txentry_desc * txdesc )
{
struct skb_frame_desc * skbdesc = get_skb_frame_desc ( skb ) ;
__le32 * txi = skbdesc - > desc ;
__le32 * txwi = & txi [ TXINFO_DESC_SIZE / sizeof ( __le32 ) ] ;
u32 word ;
/*
* Initialize TX Info descriptor
*/
rt2x00_desc_read ( txwi , 0 , & word ) ;
rt2x00_set_field32 ( & word , TXWI_W0_FRAG ,
test_bit ( ENTRY_TXD_MORE_FRAG , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W0_MIMO_PS , 0 ) ;
rt2x00_set_field32 ( & word , TXWI_W0_CF_ACK , 0 ) ;
rt2x00_set_field32 ( & word , TXWI_W0_TS ,
test_bit ( ENTRY_TXD_REQ_TIMESTAMP , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W0_AMPDU ,
test_bit ( ENTRY_TXD_HT_AMPDU , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W0_MPDU_DENSITY , txdesc - > mpdu_density ) ;
rt2x00_set_field32 ( & word , TXWI_W0_TX_OP , txdesc - > ifs ) ;
rt2x00_set_field32 ( & word , TXWI_W0_MCS , txdesc - > mcs ) ;
rt2x00_set_field32 ( & word , TXWI_W0_BW ,
test_bit ( ENTRY_TXD_HT_BW_40 , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W0_SHORT_GI ,
test_bit ( ENTRY_TXD_HT_SHORT_GI , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W0_STBC , txdesc - > stbc ) ;
rt2x00_set_field32 ( & word , TXWI_W0_PHYMODE , txdesc - > rate_mode ) ;
rt2x00_desc_write ( txwi , 0 , word ) ;
rt2x00_desc_read ( txwi , 1 , & word ) ;
rt2x00_set_field32 ( & word , TXWI_W1_ACK ,
test_bit ( ENTRY_TXD_ACK , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W1_NSEQ ,
test_bit ( ENTRY_TXD_GENERATE_SEQ , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXWI_W1_BW_WIN_SIZE , txdesc - > ba_size ) ;
rt2x00_set_field32 ( & word , TXWI_W1_WIRELESS_CLI_ID ,
test_bit ( ENTRY_TXD_ENCRYPT , & txdesc - > flags ) ?
txdesc - > key_idx : 0xff ) ;
rt2x00_set_field32 ( & word , TXWI_W1_MPDU_TOTAL_BYTE_COUNT ,
skb - > len - txdesc - > l2pad ) ;
rt2x00_set_field32 ( & word , TXWI_W1_PACKETID ,
skbdesc - > entry - > entry_idx ) ;
rt2x00_desc_write ( txwi , 1 , word ) ;
/*
* Always write 0 to IV / EIV fields , hardware will insert the IV
* from the IVEIV register when TXINFO_W0_WIV is set to 0.
* When TXINFO_W0_WIV is set to 1 it will use the IV data
* from the descriptor . The TXWI_W1_WIRELESS_CLI_ID indicates which
* crypto entry in the registers should be used to encrypt the frame .
*/
_rt2x00_desc_write ( txwi , 2 , 0 /* skbdesc->iv[0] */ ) ;
_rt2x00_desc_write ( txwi , 3 , 0 /* skbdesc->iv[1] */ ) ;
/*
* Initialize TX descriptor
*/
rt2x00_desc_read ( txi , 0 , & word ) ;
rt2x00_set_field32 ( & word , TXINFO_W0_USB_DMA_TX_PKT_LEN ,
skb - > len + TXWI_DESC_SIZE ) ;
rt2x00_set_field32 ( & word , TXINFO_W0_WIV ,
! test_bit ( ENTRY_TXD_ENCRYPT_IV , & txdesc - > flags ) ) ;
rt2x00_set_field32 ( & word , TXINFO_W0_QSEL , 2 ) ;
rt2x00_set_field32 ( & word , TXINFO_W0_SW_USE_LAST_ROUND , 0 ) ;
rt2x00_set_field32 ( & word , TXINFO_W0_USB_DMA_NEXT_VALID , 0 ) ;
rt2x00_set_field32 ( & word , TXINFO_W0_USB_DMA_TX_BURST ,
test_bit ( ENTRY_TXD_BURST , & txdesc - > flags ) ) ;
rt2x00_desc_write ( txi , 0 , word ) ;
}
/*
* TX data initialization
*/
static void rt2800usb_write_beacon ( struct queue_entry * entry )
{
struct rt2x00_dev * rt2x00dev = entry - > queue - > rt2x00dev ;
struct skb_frame_desc * skbdesc = get_skb_frame_desc ( entry - > skb ) ;
unsigned int beacon_base ;
u32 reg ;
/*
* Add the descriptor in front of the skb .
*/
skb_push ( entry - > skb , entry - > queue - > desc_size ) ;
memcpy ( entry - > skb - > data , skbdesc - > desc , skbdesc - > desc_len ) ;
skbdesc - > desc = entry - > skb - > data ;
/*
* Disable beaconing while we are reloading the beacon data ,
* otherwise we might be sending out invalid data .
*/
rt2x00usb_register_read ( rt2x00dev , BCN_TIME_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_BEACON_GEN , 0 ) ;
rt2x00usb_register_write ( rt2x00dev , BCN_TIME_CFG , reg ) ;
/*
* Write entire beacon with descriptor to register .
*/
beacon_base = HW_BEACON_OFFSET ( entry - > entry_idx ) ;
rt2x00usb_vendor_request_large_buff ( rt2x00dev , USB_MULTI_WRITE ,
USB_VENDOR_REQUEST_OUT , beacon_base ,
entry - > skb - > data , entry - > skb - > len ,
REGISTER_TIMEOUT32 ( entry - > skb - > len ) ) ;
/*
* Clean up the beacon skb .
*/
dev_kfree_skb ( entry - > skb ) ;
entry - > skb = NULL ;
}
static int rt2800usb_get_tx_data_len ( struct queue_entry * entry )
{
int length ;
/*
* The length _must_ include 4 bytes padding ,
* it should always be multiple of 4 ,
* but it must _not_ be a multiple of the USB packet size .
*/
length = roundup ( entry - > skb - > len + 4 , 4 ) ;
length + = ( 4 * ! ( length % entry - > queue - > usb_maxpacket ) ) ;
return length ;
}
static void rt2800usb_kick_tx_queue ( struct rt2x00_dev * rt2x00dev ,
const enum data_queue_qid queue )
{
u32 reg ;
if ( queue ! = QID_BEACON ) {
rt2x00usb_kick_tx_queue ( rt2x00dev , queue ) ;
return ;
}
rt2x00usb_register_read ( rt2x00dev , BCN_TIME_CFG , & reg ) ;
if ( ! rt2x00_get_field32 ( reg , BCN_TIME_CFG_BEACON_GEN ) ) {
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TSF_TICKING , 1 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_TBTT_ENABLE , 1 ) ;
rt2x00_set_field32 ( & reg , BCN_TIME_CFG_BEACON_GEN , 1 ) ;
rt2x00usb_register_write ( rt2x00dev , BCN_TIME_CFG , reg ) ;
}
}
/*
* RX control handlers
*/
static void rt2800usb_fill_rxdone ( struct queue_entry * entry ,
struct rxdone_entry_desc * rxdesc )
{
struct rt2x00_dev * rt2x00dev = entry - > queue - > rt2x00dev ;
struct skb_frame_desc * skbdesc = get_skb_frame_desc ( entry - > skb ) ;
__le32 * rxd = ( __le32 * ) entry - > skb - > data ;
__le32 * rxwi ;
u32 rxd0 ;
u32 rxwi0 ;
u32 rxwi1 ;
u32 rxwi2 ;
u32 rxwi3 ;
/*
* Copy descriptor to the skbdesc - > desc buffer , making it safe from
* moving of frame data in rt2x00usb .
*/
memcpy ( skbdesc - > desc , rxd , skbdesc - > desc_len ) ;
rxd = ( __le32 * ) skbdesc - > desc ;
rxwi = & rxd [ RXD_DESC_SIZE / sizeof ( __le32 ) ] ;
/*
* It is now safe to read the descriptor on all architectures .
*/
rt2x00_desc_read ( rxd , 0 , & rxd0 ) ;
rt2x00_desc_read ( rxwi , 0 , & rxwi0 ) ;
rt2x00_desc_read ( rxwi , 1 , & rxwi1 ) ;
rt2x00_desc_read ( rxwi , 2 , & rxwi2 ) ;
rt2x00_desc_read ( rxwi , 3 , & rxwi3 ) ;
if ( rt2x00_get_field32 ( rxd0 , RXD_W0_CRC_ERROR ) )
rxdesc - > flags | = RX_FLAG_FAILED_FCS_CRC ;
if ( test_bit ( CONFIG_SUPPORT_HW_CRYPTO , & rt2x00dev - > flags ) ) {
rxdesc - > cipher = rt2x00_get_field32 ( rxwi0 , RXWI_W0_UDF ) ;
rxdesc - > cipher_status =
rt2x00_get_field32 ( rxd0 , RXD_W0_CIPHER_ERROR ) ;
}
if ( rt2x00_get_field32 ( rxd0 , RXD_W0_DECRYPTED ) ) {
/*
* Hardware has stripped IV / EIV data from 802.11 frame during
* decryption . Unfortunately the descriptor doesn ' t contain
* any fields with the EIV / IV data either , so they can ' t
* be restored by rt2x00lib .
*/
rxdesc - > flags | = RX_FLAG_IV_STRIPPED ;
if ( rxdesc - > cipher_status = = RX_CRYPTO_SUCCESS )
rxdesc - > flags | = RX_FLAG_DECRYPTED ;
else if ( rxdesc - > cipher_status = = RX_CRYPTO_FAIL_MIC )
rxdesc - > flags | = RX_FLAG_MMIC_ERROR ;
}
if ( rt2x00_get_field32 ( rxd0 , RXD_W0_MY_BSS ) )
rxdesc - > dev_flags | = RXDONE_MY_BSS ;
2009-08-17 18:54:50 +02:00
if ( rt2x00_get_field32 ( rxd0 , RXD_W0_L2PAD ) ) {
2009-04-26 15:47:48 +02:00
rxdesc - > dev_flags | = RXDONE_L2PAD ;
2009-08-17 18:54:50 +02:00
skbdesc - > flags | = SKBDESC_L2_PADDED ;
}
2009-04-26 15:47:48 +02:00
if ( rt2x00_get_field32 ( rxwi1 , RXWI_W1_SHORT_GI ) )
rxdesc - > flags | = RX_FLAG_SHORT_GI ;
if ( rt2x00_get_field32 ( rxwi1 , RXWI_W1_BW ) )
rxdesc - > flags | = RX_FLAG_40MHZ ;
/*
* Detect RX rate , always use MCS as signal type .
*/
rxdesc - > dev_flags | = RXDONE_SIGNAL_MCS ;
rxdesc - > rate_mode = rt2x00_get_field32 ( rxwi1 , RXWI_W1_PHYMODE ) ;
rxdesc - > signal = rt2x00_get_field32 ( rxwi1 , RXWI_W1_MCS ) ;
/*
* Mask of 0x8 bit to remove the short preamble flag .
*/
if ( rxdesc - > rate_mode = = RATE_MODE_CCK )
rxdesc - > signal & = ~ 0x8 ;
rxdesc - > rssi =
( rt2x00_get_field32 ( rxwi2 , RXWI_W2_RSSI0 ) +
rt2x00_get_field32 ( rxwi2 , RXWI_W2_RSSI1 ) ) / 2 ;
rxdesc - > noise =
( rt2x00_get_field32 ( rxwi3 , RXWI_W3_SNR0 ) +
rt2x00_get_field32 ( rxwi3 , RXWI_W3_SNR1 ) ) / 2 ;
rxdesc - > size = rt2x00_get_field32 ( rxwi0 , RXWI_W0_MPDU_TOTAL_BYTE_COUNT ) ;
/*
* Remove RXWI descriptor from start of buffer .
*/
skb_pull ( entry - > skb , skbdesc - > desc_len ) ;
skb_trim ( entry - > skb , rxdesc - > size ) ;
}
/*
* Device probe functions .
*/
static int rt2800usb_validate_eeprom ( struct rt2x00_dev * rt2x00dev )
{
u16 word ;
u8 * mac ;
u8 default_lna_gain ;
rt2x00usb_eeprom_read ( rt2x00dev , rt2x00dev - > eeprom , EEPROM_SIZE ) ;
/*
* Start validation of the data that has been read .
*/
mac = rt2x00_eeprom_addr ( rt2x00dev , EEPROM_MAC_ADDR_0 ) ;
if ( ! is_valid_ether_addr ( mac ) ) {
random_ether_addr ( mac ) ;
2009-07-15 17:21:41 +02:00
EEPROM ( rt2x00dev , " MAC: %pM \n " , mac ) ;
2009-04-26 15:47:48 +02:00
}
rt2x00_eeprom_read ( rt2x00dev , EEPROM_ANTENNA , & word ) ;
if ( word = = 0xffff ) {
rt2x00_set_field16 ( & word , EEPROM_ANTENNA_RXPATH , 2 ) ;
rt2x00_set_field16 ( & word , EEPROM_ANTENNA_TXPATH , 1 ) ;
rt2x00_set_field16 ( & word , EEPROM_ANTENNA_RF_TYPE , RF2820 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_ANTENNA , word ) ;
EEPROM ( rt2x00dev , " Antenna: 0x%04x \n " , word ) ;
} else if ( rt2x00_rev ( & rt2x00dev - > chip ) < RT2883_VERSION ) {
/*
* There is a max of 2 RX streams for RT2870 series
*/
if ( rt2x00_get_field16 ( word , EEPROM_ANTENNA_RXPATH ) > 2 )
rt2x00_set_field16 ( & word , EEPROM_ANTENNA_RXPATH , 2 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_ANTENNA , word ) ;
}
rt2x00_eeprom_read ( rt2x00dev , EEPROM_NIC , & word ) ;
if ( word = = 0xffff ) {
rt2x00_set_field16 ( & word , EEPROM_NIC_HW_RADIO , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_DYNAMIC_TX_AGC , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_EXTERNAL_LNA_BG , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_EXTERNAL_LNA_A , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_CARDBUS_ACCEL , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_BW40M_SB_BG , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_BW40M_SB_A , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_WPS_PBC , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_BW40M_BG , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_NIC_BW40M_A , 0 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_NIC , word ) ;
EEPROM ( rt2x00dev , " NIC: 0x%04x \n " , word ) ;
}
rt2x00_eeprom_read ( rt2x00dev , EEPROM_FREQ , & word ) ;
if ( ( word & 0x00ff ) = = 0x00ff ) {
rt2x00_set_field16 ( & word , EEPROM_FREQ_OFFSET , 0 ) ;
rt2x00_set_field16 ( & word , EEPROM_FREQ_LED_MODE ,
LED_MODE_TXRX_ACTIVITY ) ;
rt2x00_set_field16 ( & word , EEPROM_FREQ_LED_POLARITY , 0 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_FREQ , word ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_LED1 , 0x5555 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_LED2 , 0x2221 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_LED3 , 0xa9f8 ) ;
EEPROM ( rt2x00dev , " Freq: 0x%04x \n " , word ) ;
}
/*
* During the LNA validation we are going to use
* lna0 as correct value . Note that EEPROM_LNA
* is never validated .
*/
rt2x00_eeprom_read ( rt2x00dev , EEPROM_LNA , & word ) ;
default_lna_gain = rt2x00_get_field16 ( word , EEPROM_LNA_A0 ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_RSSI_BG , & word ) ;
if ( abs ( rt2x00_get_field16 ( word , EEPROM_RSSI_BG_OFFSET0 ) ) > 10 )
rt2x00_set_field16 ( & word , EEPROM_RSSI_BG_OFFSET0 , 0 ) ;
if ( abs ( rt2x00_get_field16 ( word , EEPROM_RSSI_BG_OFFSET1 ) ) > 10 )
rt2x00_set_field16 ( & word , EEPROM_RSSI_BG_OFFSET1 , 0 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_RSSI_BG , word ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_RSSI_BG2 , & word ) ;
if ( abs ( rt2x00_get_field16 ( word , EEPROM_RSSI_BG2_OFFSET2 ) ) > 10 )
rt2x00_set_field16 ( & word , EEPROM_RSSI_BG2_OFFSET2 , 0 ) ;
if ( rt2x00_get_field16 ( word , EEPROM_RSSI_BG2_LNA_A1 ) = = 0x00 | |
rt2x00_get_field16 ( word , EEPROM_RSSI_BG2_LNA_A1 ) = = 0xff )
rt2x00_set_field16 ( & word , EEPROM_RSSI_BG2_LNA_A1 ,
default_lna_gain ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_RSSI_BG2 , word ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_RSSI_A , & word ) ;
if ( abs ( rt2x00_get_field16 ( word , EEPROM_RSSI_A_OFFSET0 ) ) > 10 )
rt2x00_set_field16 ( & word , EEPROM_RSSI_A_OFFSET0 , 0 ) ;
if ( abs ( rt2x00_get_field16 ( word , EEPROM_RSSI_A_OFFSET1 ) ) > 10 )
rt2x00_set_field16 ( & word , EEPROM_RSSI_A_OFFSET1 , 0 ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_RSSI_A , word ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_RSSI_A2 , & word ) ;
if ( abs ( rt2x00_get_field16 ( word , EEPROM_RSSI_A2_OFFSET2 ) ) > 10 )
rt2x00_set_field16 ( & word , EEPROM_RSSI_A2_OFFSET2 , 0 ) ;
if ( rt2x00_get_field16 ( word , EEPROM_RSSI_A2_LNA_A2 ) = = 0x00 | |
rt2x00_get_field16 ( word , EEPROM_RSSI_A2_LNA_A2 ) = = 0xff )
rt2x00_set_field16 ( & word , EEPROM_RSSI_A2_LNA_A2 ,
default_lna_gain ) ;
rt2x00_eeprom_write ( rt2x00dev , EEPROM_RSSI_A2 , word ) ;
return 0 ;
}
static int rt2800usb_init_eeprom ( struct rt2x00_dev * rt2x00dev )
{
u32 reg ;
u16 value ;
u16 eeprom ;
/*
* Read EEPROM word for configuration .
*/
rt2x00_eeprom_read ( rt2x00dev , EEPROM_ANTENNA , & eeprom ) ;
/*
* Identify RF chipset .
*/
value = rt2x00_get_field16 ( eeprom , EEPROM_ANTENNA_RF_TYPE ) ;
rt2x00usb_register_read ( rt2x00dev , MAC_CSR0 , & reg ) ;
rt2x00_set_chip ( rt2x00dev , RT2870 , value , reg ) ;
/*
* The check for rt2860 is not a typo , some rt2870 hardware
* identifies itself as rt2860 in the CSR register .
*/
2009-05-05 19:46:08 +02:00
if ( ! rt2x00_check_rev ( & rt2x00dev - > chip , 0xfff00000 , 0x28600000 ) & &
! rt2x00_check_rev ( & rt2x00dev - > chip , 0xfff00000 , 0x28700000 ) & &
! rt2x00_check_rev ( & rt2x00dev - > chip , 0xfff00000 , 0x28800000 ) & &
! rt2x00_check_rev ( & rt2x00dev - > chip , 0xffff0000 , 0x30700000 ) ) {
2009-04-26 15:47:48 +02:00
ERROR ( rt2x00dev , " Invalid RT chipset detected. \n " ) ;
return - ENODEV ;
}
if ( ! rt2x00_rf ( & rt2x00dev - > chip , RF2820 ) & &
! rt2x00_rf ( & rt2x00dev - > chip , RF2850 ) & &
! rt2x00_rf ( & rt2x00dev - > chip , RF2720 ) & &
! rt2x00_rf ( & rt2x00dev - > chip , RF2750 ) & &
! rt2x00_rf ( & rt2x00dev - > chip , RF3020 ) & &
! rt2x00_rf ( & rt2x00dev - > chip , RF2020 ) ) {
ERROR ( rt2x00dev , " Invalid RF chipset detected. \n " ) ;
return - ENODEV ;
}
/*
* Identify default antenna configuration .
*/
rt2x00dev - > default_ant . tx =
rt2x00_get_field16 ( eeprom , EEPROM_ANTENNA_TXPATH ) ;
rt2x00dev - > default_ant . rx =
rt2x00_get_field16 ( eeprom , EEPROM_ANTENNA_RXPATH ) ;
/*
* Read frequency offset and RF programming sequence .
*/
rt2x00_eeprom_read ( rt2x00dev , EEPROM_FREQ , & eeprom ) ;
rt2x00dev - > freq_offset = rt2x00_get_field16 ( eeprom , EEPROM_FREQ_OFFSET ) ;
/*
* Read external LNA informations .
*/
rt2x00_eeprom_read ( rt2x00dev , EEPROM_NIC , & eeprom ) ;
if ( rt2x00_get_field16 ( eeprom , EEPROM_NIC_EXTERNAL_LNA_A ) )
__set_bit ( CONFIG_EXTERNAL_LNA_A , & rt2x00dev - > flags ) ;
if ( rt2x00_get_field16 ( eeprom , EEPROM_NIC_EXTERNAL_LNA_BG ) )
__set_bit ( CONFIG_EXTERNAL_LNA_BG , & rt2x00dev - > flags ) ;
/*
* Detect if this device has an hardware controlled radio .
*/
if ( rt2x00_get_field16 ( eeprom , EEPROM_NIC_HW_RADIO ) )
__set_bit ( CONFIG_SUPPORT_HW_BUTTON , & rt2x00dev - > flags ) ;
/*
* Store led settings , for correct led behaviour .
*/
# ifdef CONFIG_RT2X00_LIB_LEDS
rt2800usb_init_led ( rt2x00dev , & rt2x00dev - > led_radio , LED_TYPE_RADIO ) ;
rt2800usb_init_led ( rt2x00dev , & rt2x00dev - > led_assoc , LED_TYPE_ASSOC ) ;
rt2800usb_init_led ( rt2x00dev , & rt2x00dev - > led_qual , LED_TYPE_QUALITY ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_FREQ ,
& rt2x00dev - > led_mcu_reg ) ;
# endif /* CONFIG_RT2X00_LIB_LEDS */
return 0 ;
}
/*
* RF value list for rt2870
* Supports : 2.4 GHz ( all ) & 5.2 GHz ( RF2850 & RF2750 )
*/
static const struct rf_channel rf_vals [ ] = {
{ 1 , 0x18402ecc , 0x184c0786 , 0x1816b455 , 0x1800510b } ,
{ 2 , 0x18402ecc , 0x184c0786 , 0x18168a55 , 0x1800519f } ,
{ 3 , 0x18402ecc , 0x184c078a , 0x18168a55 , 0x1800518b } ,
{ 4 , 0x18402ecc , 0x184c078a , 0x18168a55 , 0x1800519f } ,
{ 5 , 0x18402ecc , 0x184c078e , 0x18168a55 , 0x1800518b } ,
{ 6 , 0x18402ecc , 0x184c078e , 0x18168a55 , 0x1800519f } ,
{ 7 , 0x18402ecc , 0x184c0792 , 0x18168a55 , 0x1800518b } ,
{ 8 , 0x18402ecc , 0x184c0792 , 0x18168a55 , 0x1800519f } ,
{ 9 , 0x18402ecc , 0x184c0796 , 0x18168a55 , 0x1800518b } ,
{ 10 , 0x18402ecc , 0x184c0796 , 0x18168a55 , 0x1800519f } ,
{ 11 , 0x18402ecc , 0x184c079a , 0x18168a55 , 0x1800518b } ,
{ 12 , 0x18402ecc , 0x184c079a , 0x18168a55 , 0x1800519f } ,
{ 13 , 0x18402ecc , 0x184c079e , 0x18168a55 , 0x1800518b } ,
{ 14 , 0x18402ecc , 0x184c07a2 , 0x18168a55 , 0x18005193 } ,
/* 802.11 UNI / HyperLan 2 */
{ 36 , 0x18402ecc , 0x184c099a , 0x18158a55 , 0x180ed1a3 } ,
{ 38 , 0x18402ecc , 0x184c099e , 0x18158a55 , 0x180ed193 } ,
{ 40 , 0x18402ec8 , 0x184c0682 , 0x18158a55 , 0x180ed183 } ,
{ 44 , 0x18402ec8 , 0x184c0682 , 0x18158a55 , 0x180ed1a3 } ,
{ 46 , 0x18402ec8 , 0x184c0686 , 0x18158a55 , 0x180ed18b } ,
{ 48 , 0x18402ec8 , 0x184c0686 , 0x18158a55 , 0x180ed19b } ,
{ 52 , 0x18402ec8 , 0x184c068a , 0x18158a55 , 0x180ed193 } ,
{ 54 , 0x18402ec8 , 0x184c068a , 0x18158a55 , 0x180ed1a3 } ,
{ 56 , 0x18402ec8 , 0x184c068e , 0x18158a55 , 0x180ed18b } ,
{ 60 , 0x18402ec8 , 0x184c0692 , 0x18158a55 , 0x180ed183 } ,
{ 62 , 0x18402ec8 , 0x184c0692 , 0x18158a55 , 0x180ed193 } ,
{ 64 , 0x18402ec8 , 0x184c0692 , 0x18158a55 , 0x180ed1a3 } ,
/* 802.11 HyperLan 2 */
{ 100 , 0x18402ec8 , 0x184c06b2 , 0x18178a55 , 0x180ed783 } ,
{ 102 , 0x18402ec8 , 0x184c06b2 , 0x18578a55 , 0x180ed793 } ,
{ 104 , 0x18402ec8 , 0x185c06b2 , 0x18578a55 , 0x180ed1a3 } ,
{ 108 , 0x18402ecc , 0x185c0a32 , 0x18578a55 , 0x180ed193 } ,
{ 110 , 0x18402ecc , 0x184c0a36 , 0x18178a55 , 0x180ed183 } ,
{ 112 , 0x18402ecc , 0x184c0a36 , 0x18178a55 , 0x180ed19b } ,
{ 116 , 0x18402ecc , 0x184c0a3a , 0x18178a55 , 0x180ed1a3 } ,
{ 118 , 0x18402ecc , 0x184c0a3e , 0x18178a55 , 0x180ed193 } ,
{ 120 , 0x18402ec4 , 0x184c0382 , 0x18178a55 , 0x180ed183 } ,
{ 124 , 0x18402ec4 , 0x184c0382 , 0x18178a55 , 0x180ed193 } ,
{ 126 , 0x18402ec4 , 0x184c0382 , 0x18178a55 , 0x180ed15b } ,
{ 128 , 0x18402ec4 , 0x184c0382 , 0x18178a55 , 0x180ed1a3 } ,
{ 132 , 0x18402ec4 , 0x184c0386 , 0x18178a55 , 0x180ed18b } ,
{ 134 , 0x18402ec4 , 0x184c0386 , 0x18178a55 , 0x180ed193 } ,
{ 136 , 0x18402ec4 , 0x184c0386 , 0x18178a55 , 0x180ed19b } ,
{ 140 , 0x18402ec4 , 0x184c038a , 0x18178a55 , 0x180ed183 } ,
/* 802.11 UNII */
{ 149 , 0x18402ec4 , 0x184c038a , 0x18178a55 , 0x180ed1a7 } ,
{ 151 , 0x18402ec4 , 0x184c038e , 0x18178a55 , 0x180ed187 } ,
{ 153 , 0x18402ec4 , 0x184c038e , 0x18178a55 , 0x180ed18f } ,
{ 157 , 0x18402ec4 , 0x184c038e , 0x18178a55 , 0x180ed19f } ,
{ 159 , 0x18402ec4 , 0x184c038e , 0x18178a55 , 0x180ed1a7 } ,
{ 161 , 0x18402ec4 , 0x184c0392 , 0x18178a55 , 0x180ed187 } ,
{ 165 , 0x18402ec4 , 0x184c0392 , 0x18178a55 , 0x180ed197 } ,
{ 167 , 0x18402ec4 , 0x184c03d2 , 0x18179855 , 0x1815531f } ,
{ 169 , 0x18402ec4 , 0x184c03d2 , 0x18179855 , 0x18155327 } ,
{ 171 , 0x18402ec4 , 0x184c03d6 , 0x18179855 , 0x18155307 } ,
{ 173 , 0x18402ec4 , 0x184c03d6 , 0x18179855 , 0x1815530f } ,
/* 802.11 Japan */
{ 184 , 0x15002ccc , 0x1500491e , 0x1509be55 , 0x150c0a0b } ,
{ 188 , 0x15002ccc , 0x15004922 , 0x1509be55 , 0x150c0a13 } ,
{ 192 , 0x15002ccc , 0x15004926 , 0x1509be55 , 0x150c0a1b } ,
{ 196 , 0x15002ccc , 0x1500492a , 0x1509be55 , 0x150c0a23 } ,
{ 208 , 0x15002ccc , 0x1500493a , 0x1509be55 , 0x150c0a13 } ,
{ 212 , 0x15002ccc , 0x1500493e , 0x1509be55 , 0x150c0a1b } ,
{ 216 , 0x15002ccc , 0x15004982 , 0x1509be55 , 0x150c0a23 } ,
} ;
/*
* RF value list for rt3070
* Supports : 2.4 GHz
*/
static const struct rf_channel rf_vals_3070 [ ] = {
{ 1 , 241 , 2 , 2 } ,
{ 2 , 241 , 2 , 7 } ,
{ 3 , 242 , 2 , 2 } ,
{ 4 , 242 , 2 , 7 } ,
{ 5 , 243 , 2 , 2 } ,
{ 6 , 243 , 2 , 7 } ,
{ 7 , 244 , 2 , 2 } ,
{ 8 , 244 , 2 , 7 } ,
{ 9 , 245 , 2 , 2 } ,
{ 10 , 245 , 2 , 7 } ,
{ 11 , 246 , 2 , 2 } ,
{ 12 , 246 , 2 , 7 } ,
{ 13 , 247 , 2 , 2 } ,
{ 14 , 248 , 2 , 4 } ,
} ;
static int rt2800usb_probe_hw_mode ( struct rt2x00_dev * rt2x00dev )
{
struct hw_mode_spec * spec = & rt2x00dev - > spec ;
struct channel_info * info ;
char * tx_power1 ;
char * tx_power2 ;
unsigned int i ;
u16 eeprom ;
/*
* Initialize all hw fields .
*/
rt2x00dev - > hw - > flags =
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK ;
rt2x00dev - > hw - > extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE ;
SET_IEEE80211_DEV ( rt2x00dev - > hw , rt2x00dev - > dev ) ;
SET_IEEE80211_PERM_ADDR ( rt2x00dev - > hw ,
rt2x00_eeprom_addr ( rt2x00dev ,
EEPROM_MAC_ADDR_0 ) ) ;
rt2x00_eeprom_read ( rt2x00dev , EEPROM_ANTENNA , & eeprom ) ;
/*
* Initialize HT information .
*/
spec - > ht . ht_supported = true ;
spec - > ht . cap =
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_TX_STBC |
IEEE80211_HT_CAP_RX_STBC |
IEEE80211_HT_CAP_PSMP_SUPPORT ;
spec - > ht . ampdu_factor = 3 ;
spec - > ht . ampdu_density = 4 ;
spec - > ht . mcs . tx_params =
IEEE80211_HT_MCS_TX_DEFINED |
IEEE80211_HT_MCS_TX_RX_DIFF |
( ( rt2x00_get_field16 ( eeprom , EEPROM_ANTENNA_TXPATH ) - 1 ) < <
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT ) ;
switch ( rt2x00_get_field16 ( eeprom , EEPROM_ANTENNA_RXPATH ) ) {
case 3 :
spec - > ht . mcs . rx_mask [ 2 ] = 0xff ;
case 2 :
spec - > ht . mcs . rx_mask [ 1 ] = 0xff ;
case 1 :
spec - > ht . mcs . rx_mask [ 0 ] = 0xff ;
spec - > ht . mcs . rx_mask [ 4 ] = 0x1 ; /* MCS32 */
break ;
}
/*
* Initialize hw_mode information .
*/
spec - > supported_bands = SUPPORT_BAND_2GHZ ;
spec - > supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM ;
if ( rt2x00_rf ( & rt2x00dev - > chip , RF2820 ) | |
rt2x00_rf ( & rt2x00dev - > chip , RF2720 ) ) {
spec - > num_channels = 14 ;
spec - > channels = rf_vals ;
} else if ( rt2x00_rf ( & rt2x00dev - > chip , RF2850 ) | |
rt2x00_rf ( & rt2x00dev - > chip , RF2750 ) ) {
spec - > supported_bands | = SUPPORT_BAND_5GHZ ;
spec - > num_channels = ARRAY_SIZE ( rf_vals ) ;
spec - > channels = rf_vals ;
} else if ( rt2x00_rf ( & rt2x00dev - > chip , RF3020 ) | |
rt2x00_rf ( & rt2x00dev - > chip , RF2020 ) ) {
spec - > num_channels = ARRAY_SIZE ( rf_vals_3070 ) ;
spec - > channels = rf_vals_3070 ;
}
/*
* Create channel information array
*/
info = kzalloc ( spec - > num_channels * sizeof ( * info ) , GFP_KERNEL ) ;
if ( ! info )
return - ENOMEM ;
spec - > channels_info = info ;
tx_power1 = rt2x00_eeprom_addr ( rt2x00dev , EEPROM_TXPOWER_BG1 ) ;
tx_power2 = rt2x00_eeprom_addr ( rt2x00dev , EEPROM_TXPOWER_BG2 ) ;
for ( i = 0 ; i < 14 ; i + + ) {
info [ i ] . tx_power1 = TXPOWER_G_FROM_DEV ( tx_power1 [ i ] ) ;
info [ i ] . tx_power2 = TXPOWER_G_FROM_DEV ( tx_power2 [ i ] ) ;
}
if ( spec - > num_channels > 14 ) {
tx_power1 = rt2x00_eeprom_addr ( rt2x00dev , EEPROM_TXPOWER_A1 ) ;
tx_power2 = rt2x00_eeprom_addr ( rt2x00dev , EEPROM_TXPOWER_A2 ) ;
for ( i = 14 ; i < spec - > num_channels ; i + + ) {
info [ i ] . tx_power1 = TXPOWER_A_FROM_DEV ( tx_power1 [ i ] ) ;
info [ i ] . tx_power2 = TXPOWER_A_FROM_DEV ( tx_power2 [ i ] ) ;
}
}
return 0 ;
}
static int rt2800usb_probe_hw ( struct rt2x00_dev * rt2x00dev )
{
int retval ;
/*
* Allocate eeprom data .
*/
retval = rt2800usb_validate_eeprom ( rt2x00dev ) ;
if ( retval )
return retval ;
retval = rt2800usb_init_eeprom ( rt2x00dev ) ;
if ( retval )
return retval ;
/*
* Initialize hw specifications .
*/
retval = rt2800usb_probe_hw_mode ( rt2x00dev ) ;
if ( retval )
return retval ;
2009-08-08 23:55:55 +02:00
/*
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames .
*/
__set_bit ( DRIVER_SUPPORT_CONTROL_FILTERS , & rt2x00dev - > flags ) ;
__set_bit ( DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL , & rt2x00dev - > flags ) ;
2009-04-26 15:47:48 +02:00
/*
* This device requires firmware .
*/
__set_bit ( DRIVER_REQUIRE_FIRMWARE , & rt2x00dev - > flags ) ;
__set_bit ( DRIVER_REQUIRE_SCHEDULED , & rt2x00dev - > flags ) ;
__set_bit ( DRIVER_REQUIRE_L2PAD , & rt2x00dev - > flags ) ;
if ( ! modparam_nohwcrypt )
__set_bit ( CONFIG_SUPPORT_HW_CRYPTO , & rt2x00dev - > flags ) ;
/*
* Set the rssi offset .
*/
rt2x00dev - > rssi_offset = DEFAULT_RSSI_OFFSET ;
return 0 ;
}
/*
* IEEE80211 stack callback functions .
*/
static void rt2800usb_get_tkip_seq ( struct ieee80211_hw * hw , u8 hw_key_idx ,
u32 * iv32 , u16 * iv16 )
{
struct rt2x00_dev * rt2x00dev = hw - > priv ;
struct mac_iveiv_entry iveiv_entry ;
u32 offset ;
offset = MAC_IVEIV_ENTRY ( hw_key_idx ) ;
rt2x00usb_register_multiread ( rt2x00dev , offset ,
& iveiv_entry , sizeof ( iveiv_entry ) ) ;
memcpy ( & iveiv_entry . iv [ 0 ] , iv16 , sizeof ( iv16 ) ) ;
memcpy ( & iveiv_entry . iv [ 4 ] , iv32 , sizeof ( iv32 ) ) ;
}
static int rt2800usb_set_rts_threshold ( struct ieee80211_hw * hw , u32 value )
{
struct rt2x00_dev * rt2x00dev = hw - > priv ;
u32 reg ;
bool enabled = ( value < IEEE80211_MAX_RTS_THRESHOLD ) ;
rt2x00usb_register_read ( rt2x00dev , TX_RTS_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , TX_RTS_CFG_RTS_THRES , value ) ;
rt2x00usb_register_write ( rt2x00dev , TX_RTS_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , CCK_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , CCK_PROT_CFG_RTS_TH_EN , enabled ) ;
rt2x00usb_register_write ( rt2x00dev , CCK_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , OFDM_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , OFDM_PROT_CFG_RTS_TH_EN , enabled ) ;
rt2x00usb_register_write ( rt2x00dev , OFDM_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , MM20_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , MM20_PROT_CFG_RTS_TH_EN , enabled ) ;
rt2x00usb_register_write ( rt2x00dev , MM20_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , MM40_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , MM40_PROT_CFG_RTS_TH_EN , enabled ) ;
rt2x00usb_register_write ( rt2x00dev , MM40_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , GF20_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , GF20_PROT_CFG_RTS_TH_EN , enabled ) ;
rt2x00usb_register_write ( rt2x00dev , GF20_PROT_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , GF40_PROT_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , GF40_PROT_CFG_RTS_TH_EN , enabled ) ;
rt2x00usb_register_write ( rt2x00dev , GF40_PROT_CFG , reg ) ;
return 0 ;
}
static int rt2800usb_conf_tx ( struct ieee80211_hw * hw , u16 queue_idx ,
const struct ieee80211_tx_queue_params * params )
{
struct rt2x00_dev * rt2x00dev = hw - > priv ;
struct data_queue * queue ;
struct rt2x00_field32 field ;
int retval ;
u32 reg ;
u32 offset ;
/*
* First pass the configuration through rt2x00lib , that will
* update the queue settings and validate the input . After that
* we are free to update the registers based on the value
* in the queue parameter .
*/
retval = rt2x00mac_conf_tx ( hw , queue_idx , params ) ;
if ( retval )
return retval ;
/*
* We only need to perform additional register initialization
* for WMM queues /
*/
if ( queue_idx > = 4 )
return 0 ;
queue = rt2x00queue_get_queue ( rt2x00dev , queue_idx ) ;
/* Update WMM TXOP register */
offset = WMM_TXOP0_CFG + ( sizeof ( u32 ) * ( ! ! ( queue_idx & 2 ) ) ) ;
field . bit_offset = ( queue_idx & 1 ) * 16 ;
field . bit_mask = 0xffff < < field . bit_offset ;
rt2x00usb_register_read ( rt2x00dev , offset , & reg ) ;
rt2x00_set_field32 ( & reg , field , queue - > txop ) ;
rt2x00usb_register_write ( rt2x00dev , offset , reg ) ;
/* Update WMM registers */
field . bit_offset = queue_idx * 4 ;
field . bit_mask = 0xf < < field . bit_offset ;
rt2x00usb_register_read ( rt2x00dev , WMM_AIFSN_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , field , queue - > aifs ) ;
rt2x00usb_register_write ( rt2x00dev , WMM_AIFSN_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , WMM_CWMIN_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , field , queue - > cw_min ) ;
rt2x00usb_register_write ( rt2x00dev , WMM_CWMIN_CFG , reg ) ;
rt2x00usb_register_read ( rt2x00dev , WMM_CWMAX_CFG , & reg ) ;
rt2x00_set_field32 ( & reg , field , queue - > cw_max ) ;
rt2x00usb_register_write ( rt2x00dev , WMM_CWMAX_CFG , reg ) ;
/* Update EDCA registers */
offset = EDCA_AC0_CFG + ( sizeof ( u32 ) * queue_idx ) ;
rt2x00usb_register_read ( rt2x00dev , offset , & reg ) ;
rt2x00_set_field32 ( & reg , EDCA_AC0_CFG_TX_OP , queue - > txop ) ;
rt2x00_set_field32 ( & reg , EDCA_AC0_CFG_AIFSN , queue - > aifs ) ;
rt2x00_set_field32 ( & reg , EDCA_AC0_CFG_CWMIN , queue - > cw_min ) ;
rt2x00_set_field32 ( & reg , EDCA_AC0_CFG_CWMAX , queue - > cw_max ) ;
rt2x00usb_register_write ( rt2x00dev , offset , reg ) ;
return 0 ;
}
static u64 rt2800usb_get_tsf ( struct ieee80211_hw * hw )
{
struct rt2x00_dev * rt2x00dev = hw - > priv ;
u64 tsf ;
u32 reg ;
rt2x00usb_register_read ( rt2x00dev , TSF_TIMER_DW1 , & reg ) ;
tsf = ( u64 ) rt2x00_get_field32 ( reg , TSF_TIMER_DW1_HIGH_WORD ) < < 32 ;
rt2x00usb_register_read ( rt2x00dev , TSF_TIMER_DW0 , & reg ) ;
tsf | = rt2x00_get_field32 ( reg , TSF_TIMER_DW0_LOW_WORD ) ;
return tsf ;
}
static const struct ieee80211_ops rt2800usb_mac80211_ops = {
. tx = rt2x00mac_tx ,
. start = rt2x00mac_start ,
. stop = rt2x00mac_stop ,
. add_interface = rt2x00mac_add_interface ,
. remove_interface = rt2x00mac_remove_interface ,
. config = rt2x00mac_config ,
. configure_filter = rt2x00mac_configure_filter ,
2009-07-10 20:42:55 +02:00
. set_tim = rt2x00mac_set_tim ,
2009-04-26 15:47:48 +02:00
. set_key = rt2x00mac_set_key ,
. get_stats = rt2x00mac_get_stats ,
. get_tkip_seq = rt2800usb_get_tkip_seq ,
. set_rts_threshold = rt2800usb_set_rts_threshold ,
. bss_info_changed = rt2x00mac_bss_info_changed ,
. conf_tx = rt2800usb_conf_tx ,
. get_tx_stats = rt2x00mac_get_tx_stats ,
. get_tsf = rt2800usb_get_tsf ,
2009-07-01 15:17:35 +02:00
. rfkill_poll = rt2x00mac_rfkill_poll ,
2009-04-26 15:47:48 +02:00
} ;
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
. probe_hw = rt2800usb_probe_hw ,
. get_firmware_name = rt2800usb_get_firmware_name ,
. check_firmware = rt2800usb_check_firmware ,
. load_firmware = rt2800usb_load_firmware ,
. initialize = rt2x00usb_initialize ,
. uninitialize = rt2x00usb_uninitialize ,
. clear_entry = rt2x00usb_clear_entry ,
. set_device_state = rt2800usb_set_device_state ,
. rfkill_poll = rt2800usb_rfkill_poll ,
. link_stats = rt2800usb_link_stats ,
. reset_tuner = rt2800usb_reset_tuner ,
. link_tuner = rt2800usb_link_tuner ,
. write_tx_desc = rt2800usb_write_tx_desc ,
. write_tx_data = rt2x00usb_write_tx_data ,
. write_beacon = rt2800usb_write_beacon ,
. get_tx_data_len = rt2800usb_get_tx_data_len ,
. kick_tx_queue = rt2800usb_kick_tx_queue ,
. kill_tx_queue = rt2x00usb_kill_tx_queue ,
. fill_rxdone = rt2800usb_fill_rxdone ,
. config_shared_key = rt2800usb_config_shared_key ,
. config_pairwise_key = rt2800usb_config_pairwise_key ,
. config_filter = rt2800usb_config_filter ,
. config_intf = rt2800usb_config_intf ,
. config_erp = rt2800usb_config_erp ,
. config_ant = rt2800usb_config_ant ,
. config = rt2800usb_config ,
} ;
static const struct data_queue_desc rt2800usb_queue_rx = {
. entry_num = RX_ENTRIES ,
. data_size = AGGREGATION_SIZE ,
. desc_size = RXD_DESC_SIZE + RXWI_DESC_SIZE ,
. priv_size = sizeof ( struct queue_entry_priv_usb ) ,
} ;
static const struct data_queue_desc rt2800usb_queue_tx = {
. entry_num = TX_ENTRIES ,
. data_size = AGGREGATION_SIZE ,
. desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE ,
. priv_size = sizeof ( struct queue_entry_priv_usb ) ,
} ;
static const struct data_queue_desc rt2800usb_queue_bcn = {
. entry_num = 8 * BEACON_ENTRIES ,
. data_size = MGMT_FRAME_SIZE ,
. desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE ,
. priv_size = sizeof ( struct queue_entry_priv_usb ) ,
} ;
static const struct rt2x00_ops rt2800usb_ops = {
. name = KBUILD_MODNAME ,
. max_sta_intf = 1 ,
. max_ap_intf = 8 ,
. eeprom_size = EEPROM_SIZE ,
. rf_size = RF_SIZE ,
. tx_queues = NUM_TX_QUEUES ,
. rx = & rt2800usb_queue_rx ,
. tx = & rt2800usb_queue_tx ,
. bcn = & rt2800usb_queue_bcn ,
. lib = & rt2800usb_rt2x00_ops ,
. hw = & rt2800usb_mac80211_ops ,
# ifdef CONFIG_RT2X00_LIB_DEBUGFS
. debugfs = & rt2800usb_rt2x00debug ,
# endif /* CONFIG_RT2X00_LIB_DEBUGFS */
} ;
/*
* rt2800usb module information .
*/
static struct usb_device_id rt2800usb_device_table [ ] = {
/* Abocom */
{ USB_DEVICE ( 0x07b8 , 0x2870 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07b8 , 0x2770 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07b8 , 0x3070 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07b8 , 0x3071 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07b8 , 0x3072 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1482 , 0x3c09 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* AirTies */
{ USB_DEVICE ( 0x1eda , 0x2310 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Amigo */
{ USB_DEVICE ( 0x0e0b , 0x9031 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0e0b , 0x9041 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Amit */
{ USB_DEVICE ( 0x15c5 , 0x0008 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* ASUS */
{ USB_DEVICE ( 0x0b05 , 0x1731 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0b05 , 0x1732 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0b05 , 0x1742 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0b05 , 0x1760 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0b05 , 0x1761 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* AzureWave */
{ USB_DEVICE ( 0x13d3 , 0x3247 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x13d3 , 0x3262 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x13d3 , 0x3273 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x13d3 , 0x3284 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Belkin */
{ USB_DEVICE ( 0x050d , 0x8053 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x050d , 0x805c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x050d , 0x815c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-19 07:26:04 +02:00
{ USB_DEVICE ( 0x050d , 0x825a ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* Buffalo */
{ USB_DEVICE ( 0x0411 , 0x00e8 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0411 , 0x012e ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Conceptronic */
{ USB_DEVICE ( 0x14b2 , 0x3c06 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c07 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c08 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c09 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c11 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c12 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c23 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c25 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c27 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x14b2 , 0x3c28 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Corega */
{ USB_DEVICE ( 0x07aa , 0x002f ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07aa , 0x003c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07aa , 0x003f ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x18c5 , 0x0008 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x18c5 , 0x0012 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* D-Link */
{ USB_DEVICE ( 0x07d1 , 0x3c09 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07d1 , 0x3c0a ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07d1 , 0x3c0b ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-22 21:33:21 +02:00
{ USB_DEVICE ( 0x07d1 , 0x3c0d ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07d1 , 0x3c0e ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07d1 , 0x3c0f ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
{ USB_DEVICE ( 0x07d1 , 0x3c11 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x07d1 , 0x3c13 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Edimax */
{ USB_DEVICE ( 0x7392 , 0x7711 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x7392 , 0x7717 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x7392 , 0x7718 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-22 21:33:21 +02:00
/* Encore */
{ USB_DEVICE ( 0x203d , 0x1480 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* EnGenius */
{ USB_DEVICE ( 0 X1740 , 0x9701 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1740 , 0x9702 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1740 , 0x9703 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1740 , 0x9705 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1740 , 0x9706 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1740 , 0x9801 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Gemtek */
{ USB_DEVICE ( 0x15a9 , 0x0010 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Gigabyte */
{ USB_DEVICE ( 0x1044 , 0x800b ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1044 , 0x800c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1044 , 0x800d ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Hawking */
{ USB_DEVICE ( 0x0e66 , 0x0001 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0e66 , 0x0003 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0e66 , 0x0009 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0e66 , 0x000b ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-22 21:33:21 +02:00
/* I-O DATA */
{ USB_DEVICE ( 0x04bb , 0x0945 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* LevelOne */
{ USB_DEVICE ( 0x1740 , 0x0605 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1740 , 0x0615 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Linksys */
{ USB_DEVICE ( 0x1737 , 0x0070 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1737 , 0x0071 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-27 23:58:31 +02:00
{ USB_DEVICE ( 0x1737 , 0x0077 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* Logitec */
{ USB_DEVICE ( 0x0789 , 0x0162 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0789 , 0x0163 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0789 , 0x0164 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Motorola */
{ USB_DEVICE ( 0x100d , 0x9031 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x100d , 0x9032 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Ovislink */
{ USB_DEVICE ( 0x1b75 , 0x3072 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Pegatron */
{ USB_DEVICE ( 0x1d4d , 0x0002 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x1d4d , 0x000c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-22 21:33:21 +02:00
{ USB_DEVICE ( 0x1d4d , 0x000e ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* Philips */
{ USB_DEVICE ( 0x0471 , 0x200f ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Planex */
{ USB_DEVICE ( 0x2019 , 0xed06 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x2019 , 0xab24 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x2019 , 0xab25 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Qcom */
{ USB_DEVICE ( 0x18e8 , 0x6259 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Quanta */
{ USB_DEVICE ( 0x1a32 , 0x0304 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Ralink */
2009-05-22 21:33:21 +02:00
{ USB_DEVICE ( 0x0db0 , 0x3820 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
{ USB_DEVICE ( 0x0db0 , 0x6899 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x2070 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x2770 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x2870 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x3070 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x3071 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x3072 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x148f , 0x3572 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Samsung */
{ USB_DEVICE ( 0x04e8 , 0x2018 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Siemens */
{ USB_DEVICE ( 0x129b , 0x1828 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Sitecom */
{ USB_DEVICE ( 0x0df6 , 0x0017 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x002b ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x002c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x002d ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x0039 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x003b ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x003c ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x003d ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x003e ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x003f ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0df6 , 0x0040 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-22 21:33:21 +02:00
{ USB_DEVICE ( 0x0df6 , 0x0042 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* SMC */
{ USB_DEVICE ( 0x083a , 0x6618 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0x7511 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0x7512 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0x7522 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0x8522 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0xa512 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0xa618 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0xb522 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x083a , 0xc522 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Sparklan */
{ USB_DEVICE ( 0x15a9 , 0x0006 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-21 19:16:14 +02:00
/* Sweex */
{ USB_DEVICE ( 0x177f , 0x0153 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x177f , 0x0302 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x177f , 0x0313 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* U-Media*/
{ USB_DEVICE ( 0x157e , 0x300e ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* ZCOM */
{ USB_DEVICE ( 0x0cde , 0x0022 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0cde , 0x0025 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
/* Zinwell */
{ USB_DEVICE ( 0x5a57 , 0x0280 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x5a57 , 0x0282 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-05-22 21:33:21 +02:00
{ USB_DEVICE ( 0x5a57 , 0x0283 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x5a57 , 0x5257 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
2009-04-26 15:47:48 +02:00
/* Zyxel */
{ USB_DEVICE ( 0x0586 , 0x3416 ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ USB_DEVICE ( 0x0586 , 0x341a ) , USB_DEVICE_DATA ( & rt2800usb_ops ) } ,
{ 0 , }
} ;
MODULE_AUTHOR ( DRV_PROJECT ) ;
MODULE_VERSION ( DRV_VERSION ) ;
MODULE_DESCRIPTION ( " Ralink RT2800 USB Wireless LAN driver. " ) ;
MODULE_SUPPORTED_DEVICE ( " Ralink RT2870 USB chipset based cards " ) ;
MODULE_DEVICE_TABLE ( usb , rt2800usb_device_table ) ;
MODULE_FIRMWARE ( FIRMWARE_RT2870 ) ;
MODULE_LICENSE ( " GPL " ) ;
static struct usb_driver rt2800usb_driver = {
. name = KBUILD_MODNAME ,
. id_table = rt2800usb_device_table ,
. probe = rt2x00usb_probe ,
. disconnect = rt2x00usb_disconnect ,
. suspend = rt2x00usb_suspend ,
. resume = rt2x00usb_resume ,
} ;
static int __init rt2800usb_init ( void )
{
return usb_register ( & rt2800usb_driver ) ;
}
static void __exit rt2800usb_exit ( void )
{
usb_deregister ( & rt2800usb_driver ) ;
}
module_init ( rt2800usb_init ) ;
module_exit ( rt2800usb_exit ) ;