1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-08-19 00:42:25 +03:00

Fix rt2x00 compilation and upgrade to the current mainline version (2.6.24)

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10573 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
florian 2008-03-09 10:55:19 +00:00
parent eccad93958
commit bffb95528c
27 changed files with 6901 additions and 5202 deletions

View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=rt2x00 PKG_NAME:=rt2x00
PKG_VERSION:=cvs-20070712 PKG_VERSION:=$(KERNEL_VERSION)
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
@ -109,6 +109,7 @@ PKG_EXTRA_KCONFIG:= \
CONFIG_MAC80211=y \ CONFIG_MAC80211=y \
CONFIG_RT2X00=y \ CONFIG_RT2X00=y \
CONFIG_RT2X00_DEBUG=y \ CONFIG_RT2X00_DEBUG=y \
CONFIG_RT2X00_LIB_FIRMWARE=y \
ifneq ($(CONFIG_PACKAGE_kmod-rt2x00-pci),) ifneq ($(CONFIG_PACKAGE_kmod-rt2x00-pci),)
PKG_EXTRA_KCONFIG+= CONFIG_RT2X00PCI=y PKG_EXTRA_KCONFIG+= CONFIG_RT2X00PCI=y

View File

@ -62,7 +62,7 @@ ifeq ($(CONFIG_RT2400PCI),y)
obj-m += rt2400pci.o obj-m += rt2400pci.o
ifeq ($(CONFIG_RT2400PCI_RFKILL),y) ifeq ($(CONFIG_RT2400PCI_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o rt2x00lib-objs += rt2x00rfkill.o
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
endif endif
endif endif
@ -70,7 +70,7 @@ ifeq ($(CONFIG_RT2500PCI),y)
obj-m += rt2500pci.o obj-m += rt2500pci.o
ifeq ($(CONFIG_RT2500PCI_RFKILL),y) ifeq ($(CONFIG_RT2500PCI_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o rt2x00lib-objs += rt2x00rfkill.o
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
endif endif
endif endif
@ -79,17 +79,17 @@ ifeq ($(CONFIG_RT2500USB),y)
endif endif
ifeq ($(CONFIG_RT61PCI),y) ifeq ($(CONFIG_RT61PCI),y)
CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
rt2x00lib-objs += rt2x00firmware.o rt2x00lib-objs += rt2x00firmware.o
obj-m += rt61pci.o obj-m += rt61pci.o
ifeq ($(CONFIG_RT61PCI_RFKILL),y) ifeq ($(CONFIG_RT61PCI_RFKILL),y)
rt2x00lib-objs += rt2x00rfkill.o rt2x00lib-objs += rt2x00rfkill.o
CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
endif endif
endif endif
ifeq ($(CONFIG_RT73USB),y) ifeq ($(CONFIG_RT73USB),y)
CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
rt2x00lib-objs += rt2x00firmware.o rt2x00lib-objs += rt2x00firmware.o
obj-m += rt73usb.o obj-m += rt73usb.o
endif endif
@ -97,7 +97,7 @@ endif
endif endif
MAKEFLAGS += --no-print-directory MAKEFLAGS += --no-print-directory
CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS) EXTRA_CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
all: default all: default

File diff suppressed because it is too large Load Diff

View File

@ -35,9 +35,10 @@
/* /*
* Signal information. * Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/ */
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1 #define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 100 #define DEFAULT_RSSI_OFFSET 100
/* /*
@ -48,6 +49,7 @@
#define EEPROM_BASE 0x0000 #define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100 #define EEPROM_SIZE 0x0100
#define BBP_SIZE 0x0020 #define BBP_SIZE 0x0020
#define RF_SIZE 0x0010
/* /*
* Control/Status Registers(CSR). * Control/Status Registers(CSR).
@ -544,7 +546,6 @@
*/ */
#define MACCSR0 0x00e0 #define MACCSR0 0x00e0
/* /*
* MACCSR1: MAC configuration register 1. * MACCSR1: MAC configuration register 1.
* KICK_RX: Kick one-shot rx in one-shot rx mode. * KICK_RX: Kick one-shot rx in one-shot rx mode.
@ -716,10 +717,33 @@
#define ARCSR5_SERVICE FIELD32(0x0000ff00) #define ARCSR5_SERVICE FIELD32(0x0000ff00)
#define ARCSR5_LENGTH FIELD32(0xffff0000) #define ARCSR5_LENGTH FIELD32(0xffff0000)
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R1: TX antenna control
*/
#define BBP_R1_TX_ANTENNA FIELD8(0x03)
/*
* R4: RX antenna control
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x06)
/* /*
* RF registers * RF registers
*/ */
/*
* RF 1
*/
#define RF1_TUNER FIELD32(0x00020000) #define RF1_TUNER FIELD32(0x00020000)
/*
* RF 3
*/
#define RF3_TUNER FIELD32(0x00000100) #define RF3_TUNER FIELD32(0x00000100)
#define RF3_TXPOWER FIELD32(0x00003e00) #define RF3_TXPOWER FIELD32(0x00003e00)
@ -776,21 +800,6 @@
#define EEPROM_TXPOWER_1 FIELD16(0x00ff) #define EEPROM_TXPOWER_1 FIELD16(0x00ff)
#define EEPROM_TXPOWER_2 FIELD16(0xff00) #define EEPROM_TXPOWER_2 FIELD16(0xff00)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R1: TX antenna control
*/
#define BBP_R1_TX_ANTENNA FIELD8(0x03)
/*
* BBP_R4: RX antenna control
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x06)
/* /*
* DMA descriptor defines. * DMA descriptor defines.
*/ */
@ -867,7 +876,7 @@
#define RXD_W0_MULTICAST FIELD32(0x00000004) #define RXD_W0_MULTICAST FIELD32(0x00000004)
#define RXD_W0_BROADCAST FIELD32(0x00000008) #define RXD_W0_BROADCAST FIELD32(0x00000008)
#define RXD_W0_MY_BSS FIELD32(0x00000010) #define RXD_W0_MY_BSS FIELD32(0x00000010)
#define RXD_W0_CRC FIELD32(0x00000020) #define RXD_W0_CRC_ERROR FIELD32(0x00000020)
#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080) #define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080)
#define RXD_W0_DATABYTE_COUNT FIELD32(0xffff0000) #define RXD_W0_DATABYTE_COUNT FIELD32(0xffff0000)

File diff suppressed because it is too large Load Diff

View File

@ -46,9 +46,10 @@
/* /*
* Signal information. * Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/ */
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1 #define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 121 #define DEFAULT_RSSI_OFFSET 121
/* /*
@ -59,6 +60,7 @@
#define EEPROM_BASE 0x0000 #define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0200 #define EEPROM_SIZE 0x0200
#define BBP_SIZE 0x0040 #define BBP_SIZE 0x0040
#define RF_SIZE 0x0014
/* /*
* Control/Status Registers(CSR). * Control/Status Registers(CSR).
@ -438,16 +440,16 @@
/* /*
* TXCSR8: CCK Tx BBP register. * TXCSR8: CCK Tx BBP register.
* CCK_SIGNAL: BBP rate field address for CCK.
* CCK_SERVICE: BBP service field address for CCK.
* CCK_LENGTH_LOW: BBP length low byte address for CCK.
* CCK_LENGTH_HIGH: BBP length high byte address for CCK.
*/ */
#define TXCSR8 0x0098 #define TXCSR8 0x0098
#define TXCSR8_CCK_SIGNAL FIELD32(0x000000ff) #define TXCSR8_BBP_ID0 FIELD32(0x0000007f)
#define TXCSR8_CCK_SERVICE FIELD32(0x0000ff00) #define TXCSR8_BBP_ID0_VALID FIELD32(0x00000080)
#define TXCSR8_CCK_LENGTH_LOW FIELD32(0x00ff0000) #define TXCSR8_BBP_ID1 FIELD32(0x00007f00)
#define TXCSR8_CCK_LENGTH_HIGH FIELD32(0xff000000) #define TXCSR8_BBP_ID1_VALID FIELD32(0x00008000)
#define TXCSR8_BBP_ID2 FIELD32(0x007f0000)
#define TXCSR8_BBP_ID2_VALID FIELD32(0x00800000)
#define TXCSR8_BBP_ID3 FIELD32(0x7f000000)
#define TXCSR8_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXCSR9: OFDM TX BBP registers * TXCSR9: OFDM TX BBP registers
@ -862,14 +864,32 @@
#define ARCSR5_LENGTH FIELD32(0xffff0000) #define ARCSR5_LENGTH FIELD32(0xffff0000)
/* /*
* ACK/CTS payload consumed time registers.
* ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps. * ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps.
* ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
* ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/ */
#define ARTCSR0 0x014c #define ARTCSR0 0x014c
#define ARTCSR0_ACK_CTS_11MBS FIELD32(0x000000ff)
#define ARTCSR0_ACK_CTS_5_5MBS FIELD32(0x0000ff00)
#define ARTCSR0_ACK_CTS_2MBS FIELD32(0x00ff0000)
#define ARTCSR0_ACK_CTS_1MBS FIELD32(0xff000000)
/*
* ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
*/
#define ARTCSR1 0x0150 #define ARTCSR1 0x0150
#define ARTCSR1_ACK_CTS_6MBS FIELD32(0x000000ff)
#define ARTCSR1_ACK_CTS_9MBS FIELD32(0x0000ff00)
#define ARTCSR1_ACK_CTS_12MBS FIELD32(0x00ff0000)
#define ARTCSR1_ACK_CTS_18MBS FIELD32(0xff000000)
/*
* ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define ARTCSR2 0x0154 #define ARTCSR2 0x0154
#define ARTCSR2_ACK_CTS_24MBS FIELD32(0x000000ff)
#define ARTCSR2_ACK_CTS_36MBS FIELD32(0x0000ff00)
#define ARTCSR2_ACK_CTS_48MBS FIELD32(0x00ff0000)
#define ARTCSR2_ACK_CTS_54MBS FIELD32(0xff000000)
/* /*
* SECCSR1_RT2509: WEP control register. * SECCSR1_RT2509: WEP control register.
@ -945,10 +965,40 @@
#define UART2CSR3 0x0198 #define UART2CSR3 0x0198
#define UART2CSR4 0x019c #define UART2CSR4 0x019c
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R70
*/
#define BBP_R70_JAPAN_FILTER FIELD8(0x08)
/* /*
* RF registers * RF registers
*/ */
/*
* RF 1
*/
#define RF1_TUNER FIELD32(0x00020000) #define RF1_TUNER FIELD32(0x00020000)
/*
* RF 3
*/
#define RF3_TUNER FIELD32(0x00000100) #define RF3_TUNER FIELD32(0x00000100)
#define RF3_TXPOWER FIELD32(0x00003e00) #define RF3_TXPOWER FIELD32(0x00003e00)
@ -1029,28 +1079,6 @@
#define EEPROM_CALIBRATE_OFFSET 0x3e #define EEPROM_CALIBRATE_OFFSET 0x3e
#define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff) #define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R70
*/
#define BBP_R70_JAPAN_FILTER FIELD8(0x08)
/* /*
* DMA descriptor defines. * DMA descriptor defines.
*/ */
@ -1135,7 +1163,7 @@
#define RXD_W0_MULTICAST FIELD32(0x00000004) #define RXD_W0_MULTICAST FIELD32(0x00000004)
#define RXD_W0_BROADCAST FIELD32(0x00000008) #define RXD_W0_BROADCAST FIELD32(0x00000008)
#define RXD_W0_MY_BSS FIELD32(0x00000010) #define RXD_W0_MY_BSS FIELD32(0x00000010)
#define RXD_W0_CRC FIELD32(0x00000020) #define RXD_W0_CRC_ERROR FIELD32(0x00000020)
#define RXD_W0_OFDM FIELD32(0x00000040) #define RXD_W0_OFDM FIELD32(0x00000040)
#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080) #define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080)
#define RXD_W0_CIPHER_OWNER FIELD32(0x00000100) #define RXD_W0_CIPHER_OWNER FIELD32(0x00000100)

File diff suppressed because it is too large Load Diff

View File

@ -46,9 +46,10 @@
/* /*
* Signal information. * Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/ */
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1 #define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 120 #define DEFAULT_RSSI_OFFSET 120
/* /*
@ -59,6 +60,7 @@
#define EEPROM_BASE 0x0000 #define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x006a #define EEPROM_SIZE 0x006a
#define BBP_SIZE 0x0060 #define BBP_SIZE 0x0060
#define RF_SIZE 0x0014
/* /*
* Control/Status Registers(CSR). * Control/Status Registers(CSR).
@ -72,8 +74,14 @@
/* /*
* MAC_CSR1: System control. * MAC_CSR1: System control.
* SOFT_RESET: Software reset, 1: reset, 0: normal.
* BBP_RESET: Hardware reset, 1: reset, 0, release.
* HOST_READY: Host ready after initialization.
*/ */
#define MAC_CSR1 0x0402 #define MAC_CSR1 0x0402
#define MAC_CSR1_SOFT_RESET FIELD16(0x00000001)
#define MAC_CSR1_BBP_RESET FIELD16(0x00000002)
#define MAC_CSR1_HOST_READY FIELD16(0x00000004)
/* /*
* MAC_CSR2: STA MAC register 0. * MAC_CSR2: STA MAC register 0.
@ -246,8 +254,8 @@
#define TXRX_CSR2_DROP_NOT_TO_ME FIELD16(0x0010) #define TXRX_CSR2_DROP_NOT_TO_ME FIELD16(0x0010)
#define TXRX_CSR2_DROP_TODS FIELD16(0x0020) #define TXRX_CSR2_DROP_TODS FIELD16(0x0020)
#define TXRX_CSR2_DROP_VERSION_ERROR FIELD16(0x0040) #define TXRX_CSR2_DROP_VERSION_ERROR FIELD16(0x0040)
#define TXRX_CSR2_DROP_MCAST FIELD16(0x0200) #define TXRX_CSR2_DROP_MULTICAST FIELD16(0x0200)
#define TXRX_CSR2_DROP_BCAST FIELD16(0x0400) #define TXRX_CSR2_DROP_BROADCAST FIELD16(0x0400)
/* /*
* RX BBP ID registers * RX BBP ID registers
@ -258,16 +266,40 @@
#define TXRX_CSR4 0x0448 #define TXRX_CSR4 0x0448
/* /*
* TX BBP ID registers
* TXRX_CSR5: CCK TX BBP ID0. * TXRX_CSR5: CCK TX BBP ID0.
* TXRX_CSR5: CCK TX BBP ID1.
* TXRX_CSR5: OFDM TX BBP ID0.
* TXRX_CSR5: OFDM TX BBP ID1.
*/ */
#define TXRX_CSR5 0x044a #define TXRX_CSR5 0x044a
#define TXRX_CSR5_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR5_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR5_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR5_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR6: CCK TX BBP ID1.
*/
#define TXRX_CSR6 0x044c #define TXRX_CSR6 0x044c
#define TXRX_CSR6_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR6_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR6_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR6_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR7: OFDM TX BBP ID0.
*/
#define TXRX_CSR7 0x044e #define TXRX_CSR7 0x044e
#define TXRX_CSR7_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR7_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR7_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR7_BBP_ID1_VALID FIELD16(0x8000)
/*
* TXRX_CSR5: OFDM TX BBP ID1.
*/
#define TXRX_CSR8 0x0450 #define TXRX_CSR8 0x0450
#define TXRX_CSR8_BBP_ID0 FIELD16(0x007f)
#define TXRX_CSR8_BBP_ID0_VALID FIELD16(0x0080)
#define TXRX_CSR8_BBP_ID1 FIELD16(0x7f00)
#define TXRX_CSR8_BBP_ID1_VALID FIELD16(0x8000)
/* /*
* TXRX_CSR9: TX ACK time-out. * TXRX_CSR9: TX ACK time-out.
@ -408,6 +440,7 @@
* PHY_CSR4: Interface configuration. * PHY_CSR4: Interface configuration.
*/ */
#define PHY_CSR4 0x04c8 #define PHY_CSR4 0x04c8
#define PHY_CSR4_LOW_RF_LE FIELD16(0x0001)
/* /*
* BBP pre-TX registers. * BBP pre-TX registers.
@ -473,28 +506,70 @@
#define STA_CSR0_FCS_ERROR FIELD16(0xffff) #define STA_CSR0_FCS_ERROR FIELD16(0xffff)
/* /*
* Statistic Register. * STA_CSR1: PLCP error count.
* STA_CSR1: PLCP error.
* STA_CSR2: LONG error.
* STA_CSR3: CCA false alarm.
* STA_CSR4: RX FIFO overflow.
* STA_CSR5: Beacon sent counter.
*/ */
#define STA_CSR1 0x04e2 #define STA_CSR1 0x04e2
/*
* STA_CSR2: LONG error count.
*/
#define STA_CSR2 0x04e4 #define STA_CSR2 0x04e4
/*
* STA_CSR3: CCA false alarm.
* FALSE_CCA_ERROR: False CCA error count, cleared when read.
*/
#define STA_CSR3 0x04e6 #define STA_CSR3 0x04e6
#define STA_CSR3_FALSE_CCA_ERROR FIELD16(0xffff)
/*
* STA_CSR4: RX FIFO overflow.
*/
#define STA_CSR4 0x04e8 #define STA_CSR4 0x04e8
/*
* STA_CSR5: Beacon sent counter.
*/
#define STA_CSR5 0x04ea #define STA_CSR5 0x04ea
/*
* Statistics registers
*/
#define STA_CSR6 0x04ec #define STA_CSR6 0x04ec
#define STA_CSR7 0x04ee #define STA_CSR7 0x04ee
#define STA_CSR8 0x04f0 #define STA_CSR8 0x04f0
#define STA_CSR9 0x04f2 #define STA_CSR9 0x04f2
#define STA_CSR10 0x04f4 #define STA_CSR10 0x04f4
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/* /*
* RF registers. * RF registers.
*/ */
/*
* RF 1
*/
#define RF1_TUNER FIELD32(0x00020000) #define RF1_TUNER FIELD32(0x00020000)
/*
* RF 3
*/
#define RF3_TUNER FIELD32(0x00000100) #define RF3_TUNER FIELD32(0x00000100)
#define RF3_TXPOWER FIELD32(0x00003e00) #define RF3_TXPOWER FIELD32(0x00003e00)
@ -614,23 +689,6 @@
#define EEPROM_CALIBRATE_OFFSET 0x0036 #define EEPROM_CALIBRATE_OFFSET 0x0036
#define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff) #define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2: TX antenna control
*/
#define BBP_R2_TX_ANTENNA FIELD8(0x03)
#define BBP_R2_TX_IQ_FLIP FIELD8(0x04)
/*
* BBP_R14: RX antenna control
*/
#define BBP_R14_RX_ANTENNA FIELD8(0x03)
#define BBP_R14_RX_IQ_FLIP FIELD8(0x04)
/* /*
* DMA descriptor defines. * DMA descriptor defines.
*/ */
@ -693,11 +751,11 @@
#define RXD_W0_MULTICAST FIELD32(0x00000004) #define RXD_W0_MULTICAST FIELD32(0x00000004)
#define RXD_W0_BROADCAST FIELD32(0x00000008) #define RXD_W0_BROADCAST FIELD32(0x00000008)
#define RXD_W0_MY_BSS FIELD32(0x00000010) #define RXD_W0_MY_BSS FIELD32(0x00000010)
#define RXD_W0_CRC FIELD32(0x00000020) #define RXD_W0_CRC_ERROR FIELD32(0x00000020)
#define RXD_W0_OFDM FIELD32(0x00000040) #define RXD_W0_OFDM FIELD32(0x00000040)
#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080) #define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080)
#define RXD_W0_CIPHER FIELD32(0x00000100) #define RXD_W0_CIPHER FIELD32(0x00000100)
#define RXD_W0_CI_ERROR FIELD32(0x00000200) #define RXD_W0_CIPHER_ERROR FIELD32(0x00000200)
#define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) #define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000)
/* /*

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,205 @@
/*
Copyright (C) 2004 - 2007 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: rt2x00lib
Abstract: rt2x00 generic configuration routines.
*/
/*
* Set enviroment defines for rt2x00.h
*/
#define DRV_NAME "rt2x00lib"
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
/*
* The MAC and BSSID addressess are simple array of bytes,
* these arrays are little endian, so when sending the addressess
* to the drivers, copy the it into a endian-signed variable.
*
* Note that all devices (except rt2500usb) have 32 bits
* register word sizes. This means that whatever variable we
* pass _must_ be a multiple of 32 bits. Otherwise the device
* might not accept what we are sending to it.
* This will also make it easier for the driver to write
* the data to the device.
*
* Also note that when NULL is passed as address the
* we will send 00:00:00:00:00 to the device to clear the address.
* This will prevent the device being confused when it wants
* to ACK frames or consideres itself associated.
*/
void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac)
{
__le32 reg[2];
memset(&reg, 0, sizeof(reg));
if (mac)
memcpy(&reg, mac, ETH_ALEN);
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, &reg[0]);
}
void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
{
__le32 reg[2];
memset(&reg, 0, sizeof(reg));
if (bssid)
memcpy(&reg, bssid, ETH_ALEN);
rt2x00dev->ops->lib->config_bssid(rt2x00dev, &reg[0]);
}
void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
{
int tsf_sync;
switch (type) {
case IEEE80211_IF_TYPE_IBSS:
case IEEE80211_IF_TYPE_AP:
tsf_sync = TSF_SYNC_BEACON;
break;
case IEEE80211_IF_TYPE_STA:
tsf_sync = TSF_SYNC_INFRA;
break;
default:
tsf_sync = TSF_SYNC_NONE;
break;
}
rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
}
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config)
{
struct rt2x00lib_conf libconf;
struct ieee80211_hw_mode *mode;
struct ieee80211_rate *rate;
int flags = 0;
int short_slot_time;
/*
* In some situations we want to force all configurations
* to be reloaded (When resuming for instance).
*/
if (force_config) {
flags = CONFIG_UPDATE_ALL;
goto config;
}
/*
* Check which configuration options have been
* updated and should be send to the device.
*/
if (rt2x00dev->rx_status.phymode != conf->phymode)
flags |= CONFIG_UPDATE_PHYMODE;
if (rt2x00dev->rx_status.channel != conf->channel)
flags |= CONFIG_UPDATE_CHANNEL;
if (rt2x00dev->tx_power != conf->power_level)
flags |= CONFIG_UPDATE_TXPOWER;
if (rt2x00dev->rx_status.antenna == conf->antenna_sel_rx)
flags |= CONFIG_UPDATE_ANTENNA;
/*
* The following configuration options are never
* stored anywhere and will always be updated.
*/
flags |= CONFIG_UPDATE_SLOT_TIME;
flags |= CONFIG_UPDATE_BEACON_INT;
/*
* We have determined what options should be updated,
* now precalculate device configuration values depending
* on what configuration options need to be updated.
*/
config:
memset(&libconf, 0, sizeof(libconf));
if (flags & CONFIG_UPDATE_PHYMODE) {
switch (conf->phymode) {
case MODE_IEEE80211A:
libconf.phymode = HWMODE_A;
break;
case MODE_IEEE80211B:
libconf.phymode = HWMODE_B;
break;
case MODE_IEEE80211G:
libconf.phymode = HWMODE_G;
break;
default:
ERROR(rt2x00dev,
"Attempt to configure unsupported mode (%d)"
"Defaulting to 802.11b", conf->phymode);
libconf.phymode = HWMODE_B;
}
mode = &rt2x00dev->hwmodes[libconf.phymode];
rate = &mode->rates[mode->num_rates - 1];
libconf.basic_rates =
DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
}
if (flags & CONFIG_UPDATE_CHANNEL) {
memcpy(&libconf.rf,
&rt2x00dev->spec.channels[conf->channel_val],
sizeof(libconf.rf));
}
if (flags & CONFIG_UPDATE_SLOT_TIME) {
short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
libconf.slot_time =
short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
libconf.sifs = SIFS;
libconf.pifs = short_slot_time ? SHORT_PIFS : PIFS;
libconf.difs = short_slot_time ? SHORT_DIFS : DIFS;
libconf.eifs = EIFS;
}
libconf.conf = conf;
/*
* Start configuration.
*/
rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
/*
* Some configuration changes affect the link quality
* which means we need to reset the link tuner.
*/
if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
rt2x00lib_reset_link_tuner(rt2x00dev);
rt2x00dev->curr_hwmode = libconf.phymode;
rt2x00dev->rx_status.phymode = conf->phymode;
rt2x00dev->rx_status.freq = conf->freq;
rt2x00dev->rx_status.channel = conf->channel;
rt2x00dev->tx_power = conf->power_level;
rt2x00dev->rx_status.antenna = conf->antenna_sel_rx;
}

View File

@ -21,22 +21,22 @@
/* /*
Module: rt2x00lib Module: rt2x00lib
Abstract: rt2x00 debugfs specific routines. Abstract: rt2x00 debugfs specific routines.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/ */
#include <linux/debugfs.h> /*
* Set enviroment defines for rt2x00.h
*/
#define DRV_NAME "rt2x00lib"
#include <asm/uaccess.h> #include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00debug.h" #include "rt2x00lib.h"
#define PRINT_REG8_STR ( "0x%.2x\n" ) #define PRINT_LINE_LEN_MAX 32
#define PRINT_REG16_STR ( "0x%.4x\n" )
#define PRINT_REG32_STR ( "0x%.8x\n" )
#define PRINT_REG_LEN_MAX ( 16 )
#define PRINT_LINE_LEN_MAX ( 32 )
struct rt2x00debug_intf { struct rt2x00debug_intf {
/* /*
@ -57,19 +57,24 @@ struct rt2x00debug_intf {
* - driver folder * - driver folder
* - driver file * - driver file
* - chipset file * - chipset file
* - device flags file
* - register offset/value files * - register offset/value files
* - eeprom offset/value files * - eeprom offset/value files
* - bbp offset/value files * - bbp offset/value files
* - rf offset/value files
*/ */
struct dentry *driver_folder; struct dentry *driver_folder;
struct dentry *driver_entry; struct dentry *driver_entry;
struct dentry *chipset_entry; struct dentry *chipset_entry;
struct dentry *dev_flags;
struct dentry *csr_off_entry; struct dentry *csr_off_entry;
struct dentry *csr_val_entry; struct dentry *csr_val_entry;
struct dentry *eeprom_off_entry; struct dentry *eeprom_off_entry;
struct dentry *eeprom_val_entry; struct dentry *eeprom_val_entry;
struct dentry *bbp_off_entry; struct dentry *bbp_off_entry;
struct dentry *bbp_val_entry; struct dentry *bbp_val_entry;
struct dentry *rf_off_entry;
struct dentry *rf_val_entry;
/* /*
* Driver and chipset files will use a data buffer * Driver and chipset files will use a data buffer
@ -85,6 +90,7 @@ struct rt2x00debug_intf {
unsigned int offset_csr; unsigned int offset_csr;
unsigned int offset_eeprom; unsigned int offset_eeprom;
unsigned int offset_bbp; unsigned int offset_bbp;
unsigned int offset_rf;
}; };
static int rt2x00debug_file_open(struct inode *inode, struct file *file) static int rt2x00debug_file_open(struct inode *inode, struct file *file)
@ -108,127 +114,120 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static ssize_t rt2x00debug_file_read(void *device, char __user *buf, #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
loff_t *offset, unsigned int word, const struct rt2x00debug_reg *reg) static ssize_t rt2x00debug_read_##__name(struct file *file, \
{ char __user *buf, \
unsigned long value; size_t length, \
unsigned int size; loff_t *offset) \
char *line; { \
if (*offset)
return 0;
line = kzalloc(PRINT_REG_LEN_MAX, GFP_KERNEL);
if (!line)
return -ENOMEM;
reg->read(device, word, &value);
if (reg->word_size == sizeof(u8))
size = sprintf(line, PRINT_REG8_STR, (u8)value);
else if (reg->word_size == sizeof(u16))
size = sprintf(line, PRINT_REG16_STR, (u16)value);
else
size = sprintf(line, PRINT_REG32_STR, (u32)value);
if (copy_to_user(buf, line, size))
goto exit;
kfree(line);
*offset += size;
return size;
exit:
kfree(line);
return -EFAULT;
}
static ssize_t rt2x00debug_file_write(void *device, const char __user *buf,
loff_t *offset, unsigned int word, unsigned int length,
const struct rt2x00debug_reg *reg)
{
unsigned long value;
int size;
char *line;
line = kzalloc(length, GFP_KERNEL);
if (!line)
return -ENOMEM;
if (copy_from_user(line, buf, length))
goto exit;
size = strlen(line);
value = simple_strtoul(line, NULL, 0);
reg->write(device, word, &value);
kfree(line);
*offset += size;
return size;
exit:
kfree(line);
return -EFAULT;
}
#define RT2X00DEBUGFS_OPS_READ(__name) \
static ssize_t rt2x00debug_read_##__name(struct file *file, \
char __user *buf, size_t length, loff_t *offset) \
{ \
struct rt2x00debug_intf *intf = file->private_data; \ struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \ const struct rt2x00debug *debug = intf->debug; \
const struct rt2x00debug_reg *reg = &debug->reg_##__name;\ char line[16]; \
size_t size; \
__type value; \
\ \
if (intf->offset_##__name > reg->word_count) \ if (*offset) \
return 0; \
\
if (intf->offset_##__name >= debug->__name.word_count) \
return -EINVAL; \ return -EINVAL; \
\ \
return rt2x00debug_file_read(intf->rt2x00dev, buf, \ debug->__name.read(intf->rt2x00dev, \
offset, intf->offset_##__name, reg); \ intf->offset_##__name, &value); \
} \
size = sprintf(line, __format, value); \
\
if (copy_to_user(buf, line, size)) \
return -EFAULT; \
\
*offset += size; \
return size; \
}
RT2X00DEBUGFS_OPS_READ(csr); #define RT2X00DEBUGFS_OPS_WRITE(__name, __type) \
RT2X00DEBUGFS_OPS_READ(eeprom); static ssize_t rt2x00debug_write_##__name(struct file *file, \
RT2X00DEBUGFS_OPS_READ(bbp); const char __user *buf,\
size_t length, \
#define RT2X00DEBUGFS_OPS_WRITE(__name) \ loff_t *offset) \
static ssize_t rt2x00debug_write_##__name(struct file *file, \ { \
const char __user *buf, size_t length, loff_t *offset) \
{ \
struct rt2x00debug_intf *intf = file->private_data; \ struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \ const struct rt2x00debug *debug = intf->debug; \
const struct rt2x00debug_reg *reg = &debug->reg_##__name;\ char line[16]; \
size_t size; \
__type value; \
\ \
if (intf->offset_##__name > reg->word_count) \ if (*offset) \
return 0; \
\
if (!capable(CAP_NET_ADMIN)) \
return -EPERM; \
\
if (intf->offset_##__name >= debug->__name.word_count) \
return -EINVAL; \ return -EINVAL; \
\ \
return rt2x00debug_file_write(intf->rt2x00dev, buf, \ if (copy_from_user(line, buf, length)) \
offset, intf->offset_##__name, length, reg); \ return -EFAULT; \
} \
size = strlen(line); \
value = simple_strtoul(line, NULL, 0); \
\
debug->__name.write(intf->rt2x00dev, \
intf->offset_##__name, value); \
\
*offset += size; \
return size; \
}
RT2X00DEBUGFS_OPS_WRITE(csr); #define RT2X00DEBUGFS_OPS(__name, __format, __type) \
RT2X00DEBUGFS_OPS_WRITE(eeprom); RT2X00DEBUGFS_OPS_READ(__name, __format, __type); \
RT2X00DEBUGFS_OPS_WRITE(bbp); RT2X00DEBUGFS_OPS_WRITE(__name, __type); \
\
#define RT2X00DEBUGFS_OPS(__name) \ static const struct file_operations rt2x00debug_fop_##__name = {\
static const struct file_operations rt2x00debug_fop_##__name = {\
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.read = rt2x00debug_read_##__name, \ .read = rt2x00debug_read_##__name, \
.write = rt2x00debug_write_##__name, \ .write = rt2x00debug_write_##__name, \
.open = rt2x00debug_file_open, \ .open = rt2x00debug_file_open, \
.release = rt2x00debug_file_release, \ .release = rt2x00debug_file_release, \
}; };
RT2X00DEBUGFS_OPS(csr); RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
RT2X00DEBUGFS_OPS(eeprom); RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
RT2X00DEBUGFS_OPS(bbp); RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
static ssize_t rt2x00debug_read_dev_flags(struct file *file,
char __user *buf,
size_t length,
loff_t *offset)
{
struct rt2x00debug_intf *intf = file->private_data;
char line[16];
size_t size;
if (*offset)
return 0;
size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
if (copy_to_user(buf, line, size))
return -EFAULT;
*offset += size;
return size;
}
static const struct file_operations rt2x00debug_fop_dev_flags = {
.owner = THIS_MODULE,
.read = rt2x00debug_read_dev_flags,
.open = rt2x00debug_file_open,
.release = rt2x00debug_file_release,
};
static struct dentry *rt2x00debug_create_file_driver(const char *name, static struct dentry *rt2x00debug_create_file_driver(const char *name,
struct rt2x00debug_intf *intf, struct debugfs_blob_wrapper *blob) struct rt2x00debug_intf
*intf,
struct debugfs_blob_wrapper
*blob)
{ {
char *data; char *data;
@ -246,20 +245,24 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
} }
static struct dentry *rt2x00debug_create_file_chipset(const char *name, static struct dentry *rt2x00debug_create_file_chipset(const char *name,
struct rt2x00debug_intf *intf, struct debugfs_blob_wrapper *blob) struct rt2x00debug_intf
*intf,
struct
debugfs_blob_wrapper
*blob)
{ {
const struct rt2x00debug *debug = intf->debug; const struct rt2x00debug *debug = intf->debug;
char *data; char *data;
data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL); data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
if (!data) if (!data)
return NULL; return NULL;
blob->data = data; blob->data = data;
data += sprintf(data, "csr length: %d\n", debug->reg_csr.word_count); data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
data += sprintf(data, "eeprom length: %d\n", data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
debug->reg_eeprom.word_count); data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
data += sprintf(data, "bbp length: %d\n", debug->reg_bbp.word_count); data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
blob->size = strlen(blob->data); blob->size = strlen(blob->data);
return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob); return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
@ -280,53 +283,54 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf->rt2x00dev = rt2x00dev; intf->rt2x00dev = rt2x00dev;
rt2x00dev->debugfs_intf = intf; rt2x00dev->debugfs_intf = intf;
intf->driver_folder = debugfs_create_dir(intf->rt2x00dev->ops->name, intf->driver_folder =
debugfs_create_dir(intf->rt2x00dev->ops->name,
rt2x00dev->hw->wiphy->debugfsdir); rt2x00dev->hw->wiphy->debugfsdir);
if (IS_ERR(intf->driver_folder)) if (IS_ERR(intf->driver_folder))
goto exit; goto exit;
intf->driver_entry = rt2x00debug_create_file_driver("driver", intf->driver_entry =
intf, &intf->driver_blob); rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
if (IS_ERR(intf->driver_entry)) if (IS_ERR(intf->driver_entry))
goto exit; goto exit;
intf->chipset_entry = rt2x00debug_create_file_chipset("chipset", intf->chipset_entry =
rt2x00debug_create_file_chipset("chipset",
intf, &intf->chipset_blob); intf, &intf->chipset_blob);
if (IS_ERR(intf->chipset_entry)) if (IS_ERR(intf->chipset_entry))
goto exit; goto exit;
intf->csr_off_entry = debugfs_create_u32("csr_offset", intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO,
S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_csr); intf->driver_folder, intf,
if (IS_ERR(intf->csr_off_entry)) &rt2x00debug_fop_dev_flags);
if (IS_ERR(intf->dev_flags))
goto exit; goto exit;
intf->csr_val_entry = debugfs_create_file("csr_value", #define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name) \
S_IRUGO | S_IWUSR, intf->driver_folder, intf, ({ \
&rt2x00debug_fop_csr); (__intf)->__name##_off_entry = \
if (IS_ERR(intf->csr_val_entry)) debugfs_create_u32(__stringify(__name) "_offset", \
goto exit; S_IRUGO | S_IWUSR, \
(__intf)->driver_folder, \
&(__intf)->offset_##__name); \
if (IS_ERR((__intf)->__name##_off_entry)) \
goto exit; \
\
(__intf)->__name##_val_entry = \
debugfs_create_file(__stringify(__name) "_value", \
S_IRUGO | S_IWUSR, \
(__intf)->driver_folder, \
(__intf), &rt2x00debug_fop_##__name);\
if (IS_ERR((__intf)->__name##_val_entry)) \
goto exit; \
})
intf->eeprom_off_entry = debugfs_create_u32("eeprom_offset", RT2X00DEBUGFS_CREATE_ENTRY(intf, csr);
S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_eeprom); RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom);
if (IS_ERR(intf->eeprom_off_entry)) RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp);
goto exit; RT2X00DEBUGFS_CREATE_ENTRY(intf, rf);
intf->eeprom_val_entry = debugfs_create_file("eeprom_value", #undef RT2X00DEBUGFS_CREATE_ENTRY
S_IRUGO | S_IWUSR, intf->driver_folder, intf,
&rt2x00debug_fop_eeprom);
if (IS_ERR(intf->eeprom_val_entry))
goto exit;
intf->bbp_off_entry = debugfs_create_u32("bbp_offset",
S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_bbp);
if (IS_ERR(intf->bbp_off_entry))
goto exit;
intf->bbp_val_entry = debugfs_create_file("bbp_value",
S_IRUGO | S_IWUSR, intf->driver_folder, intf,
&rt2x00debug_fop_bbp);
if (IS_ERR(intf->bbp_val_entry))
goto exit;
return; return;
@ -344,12 +348,15 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
if (unlikely(!intf)) if (unlikely(!intf))
return; return;
debugfs_remove(intf->rf_val_entry);
debugfs_remove(intf->rf_off_entry);
debugfs_remove(intf->bbp_val_entry); debugfs_remove(intf->bbp_val_entry);
debugfs_remove(intf->bbp_off_entry); debugfs_remove(intf->bbp_off_entry);
debugfs_remove(intf->eeprom_val_entry); debugfs_remove(intf->eeprom_val_entry);
debugfs_remove(intf->eeprom_off_entry); debugfs_remove(intf->eeprom_off_entry);
debugfs_remove(intf->csr_val_entry); debugfs_remove(intf->csr_val_entry);
debugfs_remove(intf->csr_off_entry); debugfs_remove(intf->csr_off_entry);
debugfs_remove(intf->dev_flags);
debugfs_remove(intf->chipset_entry); debugfs_remove(intf->chipset_entry);
debugfs_remove(intf->driver_entry); debugfs_remove(intf->driver_entry);
debugfs_remove(intf->driver_folder); debugfs_remove(intf->driver_folder);

View File

@ -21,23 +21,23 @@
/* /*
Module: rt2x00debug Module: rt2x00debug
Abstract: Data structures for the rt2x00debug. Abstract: Data structures for the rt2x00debug.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/ */
#ifndef RT2X00DEBUG_H #ifndef RT2X00DEBUG_H
#define RT2X00DEBUG_H #define RT2X00DEBUG_H
typedef void (debug_access_t)(struct rt2x00_dev *rt2x00dev, struct rt2x00_dev;
const unsigned long word, void *data);
struct rt2x00debug_reg { #define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \
debug_access_t *read; struct reg##__name { \
debug_access_t *write; void (*read)(const struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type *data); \
unsigned int word_size; void (*write)(const struct rt2x00_dev *rt2x00dev, \
unsigned int word_count; const unsigned int word, __type data); \
}; \
unsigned int word_size; \
unsigned int word_count; \
} __name
struct rt2x00debug { struct rt2x00debug {
/* /*
@ -46,19 +46,12 @@ struct rt2x00debug {
struct module *owner; struct module *owner;
/* /*
* Register access information. * Register access entries.
*/ */
struct rt2x00debug_reg reg_csr; RT2X00DEBUGFS_REGISTER_ENTRY(csr, u32);
struct rt2x00debug_reg reg_eeprom; RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
struct rt2x00debug_reg reg_bbp; RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
}; };
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
#else /* CONFIG_RT2X00_LIB_DEBUGFS */
static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev){}
static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev){}
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
#endif /* RT2X00DEBUG_H */ #endif /* RT2X00DEBUG_H */

File diff suppressed because it is too large Load Diff

View File

@ -20,8 +20,7 @@
/* /*
Module: rt2x00lib Module: rt2x00lib
Abstract: rt2x00 firmware loading specific routines. Abstract: rt2x00 firmware loading routines.
Supported chipsets: rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/ */
/* /*
@ -29,24 +28,44 @@
*/ */
#define DRV_NAME "rt2x00lib" #define DRV_NAME "rt2x00lib"
#include <linux/delay.h>
#include <linux/crc-itu-t.h> #include <linux/crc-itu-t.h>
#include <linux/firmware.h> #include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00lib.h" #include "rt2x00lib.h"
#include "rt2x00firmware.h"
static void rt2x00lib_load_firmware_continued(const struct firmware *fw, static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
void *context)
{ {
struct rt2x00_dev *rt2x00dev = context; struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
const struct firmware *fw;
char *fw_name;
int retval;
u16 crc; u16 crc;
u16 tmp; u16 tmp;
/*
* Read correct firmware from harddisk.
*/
fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
if (!fw_name) {
ERROR(rt2x00dev,
"Invalid firmware filename.\n"
"Please file bug report to %s.\n", DRV_PROJECT);
return -EINVAL;
}
INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
retval = request_firmware(&fw, fw_name, device);
if (retval) {
ERROR(rt2x00dev, "Failed to request Firmware.\n");
return retval;
}
if (!fw || !fw->size || !fw->data) { if (!fw || !fw->size || !fw->data) {
ERROR(rt2x00dev, "Failed to read Firmware.\n"); ERROR(rt2x00dev, "Failed to read Firmware.\n");
goto exit_failed; return -ENOENT;
} }
/* /*
@ -57,75 +76,49 @@ static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
*/ */
tmp = 0; tmp = 0;
crc = crc_itu_t(0, fw->data, fw->size - 2); crc = crc_itu_t(0, fw->data, fw->size - 2);
crc = crc_itu_t(crc, (u8*)&tmp, 2); crc = crc_itu_t(crc, (u8 *)&tmp, 2);
if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) { if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
ERROR(rt2x00dev, "Firmware CRC error.\n"); ERROR(rt2x00dev, "Firmware CRC error.\n");
goto exit_failed; retval = -ENOENT;
goto exit;
}
INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
fw->data[fw->size - 4], fw->data[fw->size - 3]);
rt2x00dev->fw = fw;
return 0;
exit:
release_firmware(fw);
return retval;
}
int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
int retval;
if (!rt2x00dev->fw) {
retval = rt2x00lib_request_firmware(rt2x00dev);
if (retval)
return retval;
} }
/* /*
* Send firmware to the device. * Send firmware to the device.
*/ */
if (rt2x00dev->ops->lib->load_firmware(rt2x00dev, fw->data, fw->size)) retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
goto exit_failed; rt2x00dev->fw->data,
rt2x00dev->fw->size);
INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", return retval;
fw->data[fw->size - 4], fw->data[fw->size - 3]);
__set_bit(FIRMWARE_LOADED, &rt2x00dev->flags);
return;
exit_failed:
rt2x00debug_deregister(rt2x00dev);
__set_bit(FIRMWARE_FAILED, &rt2x00dev->flags);
} }
int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
{ {
char *fw_name; release_firmware(rt2x00dev->fw);
int status = -EINVAL; rt2x00dev->fw = NULL;
/*
* Read correct firmware from harddisk.
*/
fw_name = rt2x00dev->ops->lib->get_fw_name(rt2x00dev);
if (!fw_name) {
ERROR(rt2x00dev,
"Invalid firmware filename.\n"
"Please file bug report to %s.\n", DRV_PROJECT);
return -EINVAL;
}
INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
status = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
fw_name, wiphy_dev(rt2x00dev->hw->wiphy), rt2x00dev,
&rt2x00lib_load_firmware_continued);
if (status)
ERROR(rt2x00dev, "Failed to request Firmware.\n");
return status;
} }
int rt2x00lib_load_firmware_wait(struct rt2x00_dev *rt2x00dev)
{
unsigned int i;
if (!test_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags))
return 0;
for (i = 0; i < 150; i++) {
if (test_bit(FIRMWARE_FAILED, &rt2x00dev->flags))
return -EIO;
if (test_bit(FIRMWARE_LOADED, &rt2x00dev->flags))
return 0;
msleep(20);
}
ERROR(rt2x00dev, "Firmware loading timed out.\n");
return -ETIMEDOUT;
}

View File

@ -20,62 +20,100 @@
/* /*
Module: rt2x00lib Module: rt2x00lib
Abstract: Data structures for the rt2x00lib module. Abstract: Data structures and definitions for the rt2x00lib module.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/ */
#ifndef RT2X00LIB_H #ifndef RT2X00LIB_H
#define RT2X00LIB_H #define RT2X00LIB_H
/* /*
* Driver allocation handlers. * Interval defines
* Both the link tuner as the rfkill will be called once per second.
*/ */
int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev); #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) )
void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev); #define RFKILL_POLL_INTERVAL ( 1000 )
/* /*
* Driver status handlers. * Radio control handlers.
*/ */
int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state); int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev); void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state);
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev);
/* /*
* Interrupt context handlers. * Initialization handlers.
*/ */
void rt2x00lib_txdone(struct data_entry *entry, int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev);
const int status, const int retry); void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_rxdone(struct data_entry *entry, char *data,
const int size, const int signal, const int rssi, const int ofdm);
/* /*
* TX descriptor initializer * Configuration handlers.
*/ */
void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
struct data_entry *entry, struct data_desc *txd, void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
struct ieee80211_hdr *ieee80211hdr, unsigned int length, void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
struct ieee80211_tx_control *control); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config);
/* /*
* mac80211 handlers. * Firmware handlers.
*/ */
int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb, #ifdef CONFIG_RT2X00_LIB_FIRMWARE
struct ieee80211_tx_control *control); int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev);
int rt2x00lib_reset(struct ieee80211_hw *hw); void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev);
int rt2x00lib_add_interface(struct ieee80211_hw *hw, #else
struct ieee80211_if_init_conf *conf); static inline int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
void rt2x00lib_remove_interface(struct ieee80211_hw *hw, {
struct ieee80211_if_init_conf *conf); return 0;
int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); }
int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id, static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
struct ieee80211_if_conf *conf); {
void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw, }
unsigned short flags, int mc_count); #endif /* CONFIG_RT2X00_LIB_FIRMWARE */
int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats);
int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params);
#include "rt2x00debug.h" /*
* Debugfs handlers.
*/
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
#else
static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
{
}
static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
{
}
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
* RFkill handlers.
*/
#ifdef CONFIG_RT2X00_LIB_RFKILL
int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
#else
static inline int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
return 0;
}
static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
}
static inline int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
{
return 0;
}
static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{
}
#endif /* CONFIG_RT2X00_LIB_RFKILL */
#endif /* RT2X00LIB_H */ #endif /* RT2X00LIB_H */

View File

@ -19,10 +19,8 @@
*/ */
/* /*
Module: rt2x00lib Module: rt2x00mac
Abstract: rt2x00 generic mac80211 routines. Abstract: rt2x00 generic mac80211 routines.
Supported chipsets: RT2460, RT2560, RT2570,
rt2561, rt2561s, rt2661, rt2571W & rt2671.
*/ */
/* /*
@ -30,14 +28,15 @@
*/ */
#define DRV_NAME "rt2x00lib" #define DRV_NAME "rt2x00lib"
#include <linux/netdevice.h> #include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00lib.h" #include "rt2x00lib.h"
#include "rt2x00dev.h"
static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev, static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *frag_skb, struct data_ring *ring,
struct sk_buff *frag_skb,
struct ieee80211_tx_control *control) struct ieee80211_tx_control *control)
{ {
struct sk_buff *skb; struct sk_buff *skb;
@ -58,13 +57,13 @@ static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
skb_put(skb, size); skb_put(skb, size);
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
ieee80211_ctstoself_get(rt2x00dev->hw, ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
frag_skb->data, frag_skb->len, control, frag_skb->data, frag_skb->len, control,
(struct ieee80211_cts*)(skb->data)); (struct ieee80211_cts *)(skb->data));
else else
ieee80211_rts_get(rt2x00dev->hw, ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
frag_skb->data, frag_skb->len, control, frag_skb->data, frag_skb->len, control,
(struct ieee80211_rts*)(skb->data)); (struct ieee80211_rts *)(skb->data));
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) { if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
@ -74,18 +73,29 @@ static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb, int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control) struct ieee80211_tx_control *control)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data; struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_ring *ring; struct data_ring *ring;
u16 frame_control; u16 frame_control;
/*
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
* Note that we can only stop the TX queues inside the TX path
* due to possible race conditions in mac80211.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
ieee80211_stop_queues(hw);
return 0;
}
/* /*
* Determine which ring to put packet on. * Determine which ring to put packet on.
*/ */
ring = rt2x00_get_ring(rt2x00dev, control->queue); ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
if (unlikely(!ring)) { if (unlikely(!ring)) {
ERROR(rt2x00dev, ERROR(rt2x00dev,
"Attempt to send packet over invalid queue %d.\n" "Attempt to send packet over invalid queue %d.\n"
@ -102,12 +112,13 @@ int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
* frame as well as the data frame. * frame as well as the data frame.
*/ */
frame_control = le16_to_cpu(ieee80211hdr->frame_control); frame_control = le16_to_cpu(ieee80211hdr->frame_control);
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS && if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
!is_cts_frame(frame_control) && !is_rts_frame(frame_control)) { (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
IEEE80211_TXCTL_USE_CTS_PROTECT))) {
if (rt2x00_ring_free(ring) <= 1) if (rt2x00_ring_free(ring) <= 1)
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
if (rt2x00_tx_rts_cts(rt2x00dev, ring, skb, control)) if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
@ -119,64 +130,26 @@ int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
EXPORT_SYMBOL_GPL(rt2x00lib_tx); EXPORT_SYMBOL_GPL(rt2x00mac_tx);
int rt2x00lib_reset(struct ieee80211_hw *hw) int rt2x00mac_start(struct ieee80211_hw *hw)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
rt2x00lib_disable_radio(rt2x00dev);
return rt2x00lib_enable_radio(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00lib_reset);
int rt2x00lib_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
int status; int status;
/* if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
* We only support 1 non-monitor interface. test_bit(DEVICE_STARTED, &rt2x00dev->flags))
*/ return 0;
if (conf->type != IEEE80211_IF_TYPE_MNTR &&
is_interface_present(intf))
return -ENOBUFS;
/* /*
* We support muliple monitor mode interfaces. * If this is the first interface which is added,
* All we need to do is increase the monitor_count. * we should load the firmware now.
*/ */
if (conf->type == IEEE80211_IF_TYPE_MNTR) { if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
intf->monitor_count++; status = rt2x00lib_load_firmware(rt2x00dev);
} else {
intf->id = conf->if_id;
intf->type = conf->type;
if (conf->type == IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
intf->promisc = 0;
}
/*
* Initialize interface, and enable the radio when this
* is the first interface that is brought up.
*/
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
/*
* We must wait on the firmware before
* we can safely continue.
*/
status = rt2x00lib_load_firmware_wait(rt2x00dev);
if (status) if (status)
return status; return status;
}
/*
* Before initialization, the mac address should
* be configured.
*/
rt2x00dev->ops->lib->config_mac_addr(rt2x00dev,
conf->mac_addr);
/* /*
* Initialize the device. * Initialize the device.
@ -189,60 +162,116 @@ int rt2x00lib_add_interface(struct ieee80211_hw *hw,
* Enable radio. * Enable radio.
*/ */
status = rt2x00lib_enable_radio(rt2x00dev); status = rt2x00lib_enable_radio(rt2x00dev);
if (status) if (status) {
rt2x00lib_uninitialize(rt2x00dev);
return status; return status;
} }
__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2x00lib_add_interface); EXPORT_SYMBOL_GPL(rt2x00mac_start);
void rt2x00lib_remove_interface(struct ieee80211_hw *hw, void rt2x00mac_stop(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return;
/*
* Perhaps we can add something smarter here,
* but for now just disabling the radio should do.
*/
rt2x00lib_disable_radio(rt2x00dev);
__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface;
/* FIXME: Beaconing is broken in rt2x00. */
if (conf->type == IEEE80211_IF_TYPE_IBSS ||
conf->type == IEEE80211_IF_TYPE_AP) {
ERROR(rt2x00dev,
"rt2x00 does not support Adhoc or Master mode");
return -EOPNOTSUPP;
}
/*
* Don't allow interfaces to be added while
* either the device has disappeared or when
* another interface is already present.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
is_interface_present(intf))
return -ENOBUFS;
intf->id = conf->if_id;
intf->type = conf->type;
if (conf->type == IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
/*
* The MAC adddress must be configured after the device
* has been initialized. Otherwise the device can reset
* the MAC registers.
*/
rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
rt2x00lib_config_type(rt2x00dev, conf->type);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf) struct ieee80211_if_init_conf *conf)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
struct interface *intf = &rt2x00dev->interface; struct interface *intf = &rt2x00dev->interface;
/* /*
* We only support 1 non-monitor interface. * Don't allow interfaces to be remove while
* either the device has disappeared or when
* no interface is present.
*/ */
if (conf->type != IEEE80211_IF_TYPE_MNTR && if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
!is_interface_present(intf)) !is_interface_present(intf))
return; return;
/*
* When removing an monitor interface, decrease monitor_count.
* For non-monitor interfaces, all interface data needs to be reset.
*/
if (conf->type == IEEE80211_IF_TYPE_MNTR) {
intf->monitor_count--;
} else if (intf->type == conf->type) {
intf->id = 0; intf->id = 0;
intf->type = -EINVAL; intf->type = INVALID_INTERFACE;
memset(&intf->bssid, 0x00, ETH_ALEN); memset(&intf->bssid, 0x00, ETH_ALEN);
intf->promisc = 0; memset(&intf->mac, 0x00, ETH_ALEN);
}
/* /*
* If this was the last interface, * Make sure the bssid and mac address registers
* this is the time to disable the radio. * are cleared to prevent false ACKing of frames.
* If this is not the last interface, then we should
* check if we should switch completely to monitor
* mode or completely switch to the non-monitor mode.
*/ */
if (!is_monitor_present(intf) && !is_interface_present(intf)) rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
rt2x00lib_disable_radio(rt2x00dev); rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
else if (is_monitor_present(intf) ^ is_interface_present(intf)) rt2x00lib_config_type(rt2x00dev, intf->type);
rt2x00lib_config_type(rt2x00dev,
is_interface_present(intf) ?
intf->type : IEEE80211_IF_TYPE_MNTR);
} }
EXPORT_SYMBOL_GPL(rt2x00lib_remove_interface); EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
/*
* Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return 0;
/* /*
* Check if we need to disable the radio, * Check if we need to disable the radio,
* if this is not the case, at least the RX must be disabled. * if this is not the case, at least the RX must be disabled.
@ -251,32 +280,24 @@ int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
if (!conf->radio_enabled) if (!conf->radio_enabled)
rt2x00lib_disable_radio(rt2x00dev); rt2x00lib_disable_radio(rt2x00dev);
else else
rt2x00lib_toggle_rx(rt2x00dev, 0); rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
} }
rt2x00lib_config_phymode(rt2x00dev, conf->phymode); rt2x00lib_config(rt2x00dev, conf, 0);
rt2x00lib_config_channel(rt2x00dev, conf->channel_val,
conf->channel, conf->freq, conf->power_level);
rt2x00lib_config_txpower(rt2x00dev, conf->power_level);
rt2x00lib_config_antenna(rt2x00dev,
conf->antenna_sel_tx, conf->antenna_sel_rx);
rt2x00dev->ops->lib->config_duration(rt2x00dev,
(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME),
conf->beacon_int);
/* /*
* Reenable RX only if the radio should be on. * Reenable RX only if the radio should be on.
*/ */
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, 1); rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
else if (conf->radio_enabled) else if (conf->radio_enabled)
return rt2x00lib_enable_radio(rt2x00dev); return rt2x00lib_enable_radio(rt2x00dev);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2x00lib_config); EXPORT_SYMBOL_GPL(rt2x00mac_config);
int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id, int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
struct ieee80211_if_conf *conf) struct ieee80211_if_conf *conf)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
@ -284,13 +305,17 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
int status; int status;
/* /*
* Monitor mode does not need configuring. * Mac80211 might be calling this function while we are trying
* to remove the device or perhaps suspending it.
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return 0;
/*
* If the given type does not match the configured type, * If the given type does not match the configured type,
* there has been a problem. * there has been a problem.
*/ */
if (conf->type == IEEE80211_IF_TYPE_MNTR) if (conf->type != intf->type)
return 0;
else if (conf->type != intf->type)
return -EINVAL; return -EINVAL;
/* /*
@ -300,14 +325,7 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
*/ */
if (conf->type != IEEE80211_IF_TYPE_AP) if (conf->type != IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->bssid, ETH_ALEN); memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
/*
* Enable configuration.
* For Monitor mode, promisc mode will be forced on.
*/
rt2x00lib_config_type(rt2x00dev, conf->type);
rt2x00lib_config_promisc(rt2x00dev, rt2x00dev->interface.promisc);
rt2x00dev->ops->lib->config_bssid(rt2x00dev, intf->bssid);
/* /*
* We only need to initialize the beacon when master mode is enabled. * We only need to initialize the beacon when master mode is enabled.
@ -316,45 +334,32 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
return 0; return 0;
status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
conf->beacon, conf->beacon_control); conf->beacon,
conf->beacon_control);
if (status) if (status)
dev_kfree_skb(conf->beacon); dev_kfree_skb(conf->beacon);
return status; return status;
} }
EXPORT_SYMBOL_GPL(rt2x00lib_config_interface); EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw, int rt2x00mac_get_stats(struct ieee80211_hw *hw,
unsigned short flags, int mc_count) struct ieee80211_low_level_stats *stats)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
/* /*
* Promisc mode is forced on for Monitor interfaces. * The dot11ACKFailureCount, dot11RTSFailureCount and
* dot11RTSSuccessCount are updated in interrupt time.
* dot11FCSErrorCount is updated in the link tuner.
*/ */
if (is_monitor_present(&rt2x00dev->interface)) memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
return;
/* return 0;
* Check if the new state is different then the old state.
*/
if (test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags) ==
!!(flags & IFF_PROMISC))
return;
rt2x00dev->interface.promisc = !!(flags & IFF_PROMISC);
/*
* Schedule the link tuner if this does not run
* automatically. The link tuner will be automatically
* switched off when it is not required.
*/
if (!work_pending(&rt2x00dev->link.work.work))
queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work.work);
} }
EXPORT_SYMBOL_GPL(rt2x00lib_set_multicast_list); EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw, int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats) struct ieee80211_tx_queue_stats *stats)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
@ -366,15 +371,49 @@ int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2x00lib_get_tx_stats); EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);
int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue, void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
int cts_protection, int preamble)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
int short_preamble;
int ack_timeout;
int ack_consume_time;
int difs;
/*
* We only support changing preamble mode.
*/
if (!(changes & IEEE80211_ERP_CHANGE_PREAMBLE))
return;
short_preamble = !preamble;
preamble = !!(preamble) ? PREAMBLE : SHORT_PREAMBLE;
difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
SHORT_DIFS : DIFS;
ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
if (short_preamble)
__set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
else
__clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
ack_timeout, ack_consume_time);
}
EXPORT_SYMBOL_GPL(rt2x00mac_erp_ie_changed);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params) const struct ieee80211_tx_queue_params *params)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
struct data_ring *ring; struct data_ring *ring;
ring = rt2x00_get_ring(rt2x00dev, queue); ring = rt2x00lib_get_ring(rt2x00dev, queue);
if (unlikely(!ring)) if (unlikely(!ring))
return -EINVAL; return -EINVAL;
@ -404,4 +443,4 @@ int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rt2x00lib_conf_tx); EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);

View File

@ -21,7 +21,6 @@
/* /*
Module: rt2x00pci Module: rt2x00pci
Abstract: rt2x00 generic pci device routines. Abstract: rt2x00 generic pci device routines.
Supported chipsets: rt2460, rt2560, rt2561, rt2561s & rt2661.
*/ */
/* /*
@ -29,14 +28,12 @@
*/ */
#define DRV_NAME "rt2x00pci" #define DRV_NAME "rt2x00pci"
#include <linux/dma-mapping.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00lib.h"
#include "rt2x00pci.h" #include "rt2x00pci.h"
/* /*
@ -47,11 +44,11 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
struct data_ring *ring = struct data_ring *ring =
rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
struct data_entry *entry = rt2x00_get_data_entry(ring); struct data_entry *entry = rt2x00_get_data_entry(ring);
/* /*
* Just in case the ieee80211 doesn't set this, * Just in case mac80211 doesn't set this correctly,
* but we need this queue set for the descriptor * but we need this queue set for the descriptor
* initialization. * initialization.
*/ */
@ -61,8 +58,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
* Update the beacon entry. * Update the beacon entry.
*/ */
memcpy(entry->data_addr, skb->data, skb->len); memcpy(entry->data_addr, skb->data, skb->len);
rt2x00lib_write_tx_desc(rt2x00dev, entry, entry->priv, rt2x00lib_write_tx_desc(rt2x00dev, entry->priv,
(struct ieee80211_hdr*)skb->data, skb->len, control); (struct ieee80211_hdr *)skb->data,
skb->len, control);
/* /*
* Enable beacon generation. * Enable beacon generation.
@ -73,24 +71,6 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
} }
EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update); EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev, const int queue)
{
struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
struct data_entry *entry = rt2x00_get_data_entry(ring);
struct sk_buff *skb;
skb = ieee80211_beacon_get(rt2x00dev->hw,
rt2x00dev->interface.id, &entry->tx_status.control);
if (!skb)
return;
rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
&entry->tx_status.control);
dev_kfree_skb(skb);
}
EXPORT_SYMBOL_GPL(rt2x00pci_beacondone);
/* /*
* TX data handlers. * TX data handlers.
*/ */
@ -98,7 +78,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb, struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control) struct ieee80211_tx_control *control)
{ {
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data; struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_entry *entry = rt2x00_get_data_entry(ring); struct data_entry *entry = rt2x00_get_data_entry(ring);
struct data_desc *txd = entry->priv; struct data_desc *txd = entry->priv;
u32 word; u32 word;
@ -123,7 +103,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
entry->skb = skb; entry->skb = skb;
memcpy(&entry->tx_status.control, control, sizeof(*control)); memcpy(&entry->tx_status.control, control, sizeof(*control));
memcpy(entry->data_addr, skb->data, skb->len); memcpy(entry->data_addr, skb->data, skb->len);
rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr, rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
skb->len, control); skb->len, control);
rt2x00_ring_index_inc(ring); rt2x00_ring_index_inc(ring);
@ -143,35 +123,53 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
struct data_ring *ring = rt2x00dev->rx; struct data_ring *ring = rt2x00dev->rx;
struct data_entry *entry; struct data_entry *entry;
struct data_desc *rxd; struct data_desc *rxd;
u32 desc; struct sk_buff *skb;
int signal; struct ieee80211_hdr *hdr;
int rssi; struct rxdata_entry_desc desc;
int ofdm; int header_size;
int size; int align;
u32 word;
while (1) { while (1) {
entry = rt2x00_get_data_entry(ring); entry = rt2x00_get_data_entry(ring);
rxd = entry->priv; rxd = entry->priv;
rt2x00_desc_read(rxd, 0, &desc); rt2x00_desc_read(rxd, 0, &word);
if (rt2x00_get_field32(desc, RXD_ENTRY_OWNER_NIC)) if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
break; break;
size = rt2x00dev->ops->lib->fill_rxdone( memset(&desc, 0x00, sizeof(desc));
entry, &signal, &rssi, &ofdm); rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
if (size < 0)
goto skip_entry; hdr = (struct ieee80211_hdr *)entry->data_addr;
header_size =
ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
/* /*
* Send the packet to upper layer. * The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
*/ */
rt2x00lib_rxdone(entry, entry->data_addr, size, align = header_size % 4;
signal, rssi, ofdm);
/*
* Allocate the sk_buffer, initialize it and copy
* all data into it.
*/
skb = dev_alloc_skb(desc.size + align);
if (!skb)
return;
skb_reserve(skb, align);
memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
/*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, skb, &desc);
skip_entry:
if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
rt2x00_set_field32(&desc, RXD_ENTRY_OWNER_NIC, 1); rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
rt2x00_desc_write(rxd, 0, desc); rt2x00_desc_write(rxd, 0, word);
} }
rt2x00_ring_index_inc(ring); rt2x00_ring_index_inc(ring);
@ -189,19 +187,19 @@ EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
#define data_addr_offset(__ring, __i) \ #define data_addr_offset(__ring, __i) \
({ \ ({ \
(__ring)->data_addr \ (__ring)->data_addr + \
+ ((__ring)->stats.limit * (__ring)->desc_size) \ ((__ring)->stats.limit * (__ring)->desc_size) + \
+ ((__i) * (__ring)->data_size); \ ((__i) * (__ring)->data_size); \
}) })
#define data_dma_offset(__ring, __i) \ #define data_dma_offset(__ring, __i) \
({ \ ({ \
(__ring)->data_dma \ (__ring)->data_dma + \
+ ((__ring)->stats.limit * (__ring)->desc_size) \ ((__ring)->stats.limit * (__ring)->desc_size) + \
+ ((__i) * (__ring)->data_size); \ ((__i) * (__ring)->data_size); \
}) })
static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev, static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring) struct data_ring *ring)
{ {
unsigned int i; unsigned int i;
@ -210,7 +208,8 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
* Allocate DMA memory for descriptor and buffer. * Allocate DMA memory for descriptor and buffer.
*/ */
ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev), ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring), &ring->data_dma); rt2x00_get_ring_size(ring),
&ring->data_dma);
if (!ring->data_addr) if (!ring->data_addr)
return -ENOMEM; return -ENOMEM;
@ -227,6 +226,16 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
return 0; return 0;
} }
static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
if (ring->data_addr)
pci_free_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring),
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
}
int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
{ {
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
@ -237,7 +246,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA * Allocate DMA
*/ */
ring_for_each(rt2x00dev, ring) { ring_for_each(rt2x00dev, ring) {
status = rt2x00pci_alloc_ring(rt2x00dev, ring); status = rt2x00pci_alloc_dma(rt2x00dev, ring);
if (status) if (status)
goto exit; goto exit;
} }
@ -246,7 +255,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
* Register interrupt handler. * Register interrupt handler.
*/ */
status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler, status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler,
IRQF_SHARED, pci_dev->driver->name, rt2x00dev); IRQF_SHARED, pci_name(pci_dev), rt2x00dev);
if (status) { if (status) {
ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
pci_dev->irq, status); pci_dev->irq, status);
@ -274,43 +283,58 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
/* /*
* Free DMA * Free DMA
*/ */
ring_for_each(rt2x00dev, ring) { ring_for_each(rt2x00dev, ring)
if (ring->data_addr) rt2x00pci_free_dma(rt2x00dev, ring);
pci_free_consistent(rt2x00dev_pci(rt2x00dev),
rt2x00_get_ring_size(ring),
ring->data_addr, ring->data_dma);
ring->data_addr = NULL;
}
} }
EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
/* /*
* PCI driver handlers. * PCI driver handlers.
*/ */
static int rt2x00pci_alloc_csr(struct rt2x00_dev *rt2x00dev) static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
{ {
rt2x00dev->csr_addr = ioremap( kfree(rt2x00dev->rf);
pci_resource_start(rt2x00dev_pci(rt2x00dev), 0), rt2x00dev->rf = NULL;
pci_resource_len(rt2x00dev_pci(rt2x00dev), 0));
if (!rt2x00dev->csr_addr) {
ERROR(rt2x00dev, "Ioremap failed.\n");
return -ENOMEM;
}
return 0; kfree(rt2x00dev->eeprom);
} rt2x00dev->eeprom = NULL;
static void rt2x00pci_free_csr(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->csr_addr) { if (rt2x00dev->csr_addr) {
iounmap(rt2x00dev->csr_addr); iounmap(rt2x00dev->csr_addr);
rt2x00dev->csr_addr = NULL; rt2x00dev->csr_addr = NULL;
} }
} }
static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
{
struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
if (!rt2x00dev->csr_addr)
goto exit;
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
if (!rt2x00dev->eeprom)
goto exit;
rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
if (!rt2x00dev->rf)
goto exit;
return 0;
exit:
ERROR_PROBE("Failed to allocate registers.\n");
rt2x00pci_free_reg(rt2x00dev);
return -ENOMEM;
}
int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{ {
struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_data; struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev; struct rt2x00_dev *rt2x00dev;
int retval; int retval;
@ -353,18 +377,18 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
rt2x00dev->ops = ops; rt2x00dev->ops = ops;
rt2x00dev->hw = hw; rt2x00dev->hw = hw;
retval = rt2x00pci_alloc_csr(rt2x00dev); retval = rt2x00pci_alloc_reg(rt2x00dev);
if (retval) if (retval)
goto exit_free_device; goto exit_free_device;
retval = rt2x00lib_probe_dev(rt2x00dev); retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval) if (retval)
goto exit_free_csr; goto exit_free_reg;
return 0; return 0;
exit_free_csr: exit_free_reg:
rt2x00pci_free_csr(rt2x00dev); rt2x00pci_free_reg(rt2x00dev);
exit_free_device: exit_free_device:
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
@ -391,6 +415,7 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)
* Free all allocated data. * Free all allocated data.
*/ */
rt2x00lib_remove_dev(rt2x00dev); rt2x00lib_remove_dev(rt2x00dev);
rt2x00pci_free_reg(rt2x00dev);
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
/* /*
@ -413,7 +438,7 @@ int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
if (retval) if (retval)
return retval; return retval;
rt2x00pci_free_csr(rt2x00dev); rt2x00pci_free_reg(rt2x00dev);
pci_save_state(pci_dev); pci_save_state(pci_dev);
pci_disable_device(pci_dev); pci_disable_device(pci_dev);
@ -434,11 +459,20 @@ int rt2x00pci_resume(struct pci_dev *pci_dev)
return -EIO; return -EIO;
} }
retval = rt2x00pci_alloc_csr(rt2x00dev); retval = rt2x00pci_alloc_reg(rt2x00dev);
if (retval) if (retval)
return retval; return retval;
return rt2x00lib_resume(rt2x00dev); retval = rt2x00lib_resume(rt2x00dev);
if (retval)
goto exit_free_reg;
return 0;
exit_free_reg:
rt2x00pci_free_reg(rt2x00dev);
return retval;
} }
EXPORT_SYMBOL_GPL(rt2x00pci_resume); EXPORT_SYMBOL_GPL(rt2x00pci_resume);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */

View File

@ -21,12 +21,13 @@
/* /*
Module: rt2x00pci Module: rt2x00pci
Abstract: Data structures for the rt2x00pci module. Abstract: Data structures for the rt2x00pci module.
Supported chipsets: rt2460, rt2560, rt2561, rt2561s & rt2661.
*/ */
#ifndef RT2X00PCI_H #ifndef RT2X00PCI_H
#define RT2X00PCI_H #define RT2X00PCI_H
#include <linux/io.h>
/* /*
* This variable should be used with the * This variable should be used with the
* pci_driver structure initialization. * pci_driver structure initialization.
@ -35,9 +36,9 @@
/* /*
* Register defines. * Register defines.
* When register access attempts should be repeated * Some registers require multiple attempts before success,
* only REGISTER_BUSY_COUNT attempts with a delay * in those cases REGISTER_BUSY_COUNT attempts should be
* of REGISTER_BUSY_DELAY us should be taken. * taken with a REGISTER_BUSY_DELAY interval.
*/ */
#define REGISTER_BUSY_COUNT 5 #define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100 #define REGISTER_BUSY_DELAY 100
@ -46,6 +47,8 @@
* Descriptor availability flags. * Descriptor availability flags.
* All PCI device descriptors have these 2 flags * All PCI device descriptors have these 2 flags
* with the exact same definition. * with the exact same definition.
* By storing them here we can use them inside rt2x00pci
* for some simple entry availability checking.
*/ */
#define TXD_ENTRY_OWNER_NIC FIELD32(0x00000001) #define TXD_ENTRY_OWNER_NIC FIELD32(0x00000001)
#define TXD_ENTRY_VALID FIELD32(0x00000002) #define TXD_ENTRY_VALID FIELD32(0x00000002)
@ -55,27 +58,31 @@
* Register access. * Register access.
*/ */
static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev, static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, u32 *value) const unsigned long offset,
u32 *value)
{ {
*value = readl(rt2x00dev->csr_addr + offset); *value = readl(rt2x00dev->csr_addr + offset);
} }
static inline void rt2x00pci_register_multiread( static inline void
const struct rt2x00_dev *rt2x00dev, rt2x00pci_register_multiread(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, void *value, const u16 length) const unsigned long offset,
void *value, const u16 length)
{ {
memcpy_fromio(value, rt2x00dev->csr_addr + offset, length); memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
} }
static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev, static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, u32 value) const unsigned long offset,
u32 value)
{ {
writel(value, rt2x00dev->csr_addr + offset); writel(value, rt2x00dev->csr_addr + offset);
} }
static inline void rt2x00pci_register_multiwrite( static inline void
const struct rt2x00_dev *rt2x00dev, rt2x00pci_register_multiwrite(const struct rt2x00_dev *rt2x00dev,
const unsigned long offset, void *value, const u16 length) const unsigned long offset,
void *value, const u16 length)
{ {
memcpy_toio(rt2x00dev->csr_addr + offset, value, length); memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
} }
@ -85,7 +92,6 @@ static inline void rt2x00pci_register_multiwrite(
*/ */
int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control); struct ieee80211_tx_control *control);
void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev, const int queue);
/* /*
* TX data handlers. * TX data handlers.
@ -113,6 +119,9 @@ void rt2x00pci_remove(struct pci_dev *pci_dev);
#ifdef CONFIG_PM #ifdef CONFIG_PM
int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state); int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
int rt2x00pci_resume(struct pci_dev *pci_dev); int rt2x00pci_resume(struct pci_dev *pci_dev);
#else
#define rt2x00pci_suspend NULL
#define rt2x00pci_resume NULL
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
#endif /* RT2X00PCI_H */ #endif /* RT2X00PCI_H */

View File

@ -0,0 +1,292 @@
/*
Copyright (C) 2004 - 2007 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: rt2x00
Abstract: rt2x00 generic register information.
*/
#ifndef RT2X00REG_H
#define RT2X00REG_H
/*
* TX result flags.
*/
enum TX_STATUS {
TX_SUCCESS = 0,
TX_SUCCESS_RETRY = 1,
TX_FAIL_RETRY = 2,
TX_FAIL_INVALID = 3,
TX_FAIL_OTHER = 4,
};
/*
* Antenna values
*/
enum antenna {
ANTENNA_SW_DIVERSITY = 0,
ANTENNA_A = 1,
ANTENNA_B = 2,
ANTENNA_HW_DIVERSITY = 3,
};
/*
* Led mode values.
*/
enum led_mode {
LED_MODE_DEFAULT = 0,
LED_MODE_TXRX_ACTIVITY = 1,
LED_MODE_SIGNAL_STRENGTH = 2,
LED_MODE_ASUS = 3,
LED_MODE_ALPHA = 4,
};
/*
* TSF sync values
*/
enum tsf_sync {
TSF_SYNC_NONE = 0,
TSF_SYNC_INFRA = 1,
TSF_SYNC_BEACON = 2,
};
/*
* Device states
*/
enum dev_state {
STATE_DEEP_SLEEP = 0,
STATE_SLEEP = 1,
STATE_STANDBY = 2,
STATE_AWAKE = 3,
/*
* Additional device states, these values are
* not strict since they are not directly passed
* into the device.
*/
STATE_RADIO_ON,
STATE_RADIO_OFF,
STATE_RADIO_RX_ON,
STATE_RADIO_RX_OFF,
STATE_RADIO_IRQ_ON,
STATE_RADIO_IRQ_OFF,
};
/*
* IFS backoff values
*/
enum ifs {
IFS_BACKOFF = 0,
IFS_SIFS = 1,
IFS_NEW_BACKOFF = 2,
IFS_NONE = 3,
};
/*
* Cipher types for hardware encryption
*/
enum cipher {
CIPHER_NONE = 0,
CIPHER_WEP64 = 1,
CIPHER_WEP128 = 2,
CIPHER_TKIP = 3,
CIPHER_AES = 4,
/*
* The following fields were added by rt61pci and rt73usb.
*/
CIPHER_CKIP64 = 5,
CIPHER_CKIP128 = 6,
CIPHER_TKIP_NO_MIC = 7,
};
/*
* Register handlers.
* We store the position of a register field inside a field structure,
* This will simplify the process of setting and reading a certain field
* inside the register while making sure the process remains byte order safe.
*/
struct rt2x00_field8 {
u8 bit_offset;
u8 bit_mask;
};
struct rt2x00_field16 {
u16 bit_offset;
u16 bit_mask;
};
struct rt2x00_field32 {
u32 bit_offset;
u32 bit_mask;
};
/*
* Power of two check, this will check
* if the mask that has been given contains
* and contiguous set of bits.
*/
#define is_power_of_two(x) ( !((x) & ((x)-1)) )
#define low_bit_mask(x) ( ((x)-1) & ~(x) )
#define is_valid_mask(x) is_power_of_two(1 + (x) + low_bit_mask(x))
#define FIELD8(__mask) \
({ \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (u8)(__mask)); \
(struct rt2x00_field8) { \
__ffs(__mask), (__mask) \
}; \
})
#define FIELD16(__mask) \
({ \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (u16)(__mask));\
(struct rt2x00_field16) { \
__ffs(__mask), (__mask) \
}; \
})
#define FIELD32(__mask) \
({ \
BUILD_BUG_ON(!(__mask) || \
!is_valid_mask(__mask) || \
(__mask) != (u32)(__mask));\
(struct rt2x00_field32) { \
__ffs(__mask), (__mask) \
}; \
})
static inline void rt2x00_set_field32(u32 *reg,
const struct rt2x00_field32 field,
const u32 value)
{
*reg &= ~(field.bit_mask);
*reg |= (value << field.bit_offset) & field.bit_mask;
}
static inline u32 rt2x00_get_field32(const u32 reg,
const struct rt2x00_field32 field)
{
return (reg & field.bit_mask) >> field.bit_offset;
}
static inline void rt2x00_set_field16(u16 *reg,
const struct rt2x00_field16 field,
const u16 value)
{
*reg &= ~(field.bit_mask);
*reg |= (value << field.bit_offset) & field.bit_mask;
}
static inline u16 rt2x00_get_field16(const u16 reg,
const struct rt2x00_field16 field)
{
return (reg & field.bit_mask) >> field.bit_offset;
}
static inline void rt2x00_set_field8(u8 *reg,
const struct rt2x00_field8 field,
const u8 value)
{
*reg &= ~(field.bit_mask);
*reg |= (value << field.bit_offset) & field.bit_mask;
}
static inline u8 rt2x00_get_field8(const u8 reg,
const struct rt2x00_field8 field)
{
return (reg & field.bit_mask) >> field.bit_offset;
}
/*
* Device specific rate value.
* We will have to create the device specific rate value
* passed to the ieee80211 kernel. We need to make it a consist of
* multiple fields because we want to store more then 1 device specific
* values inside the value.
* 1 - rate, stored as 100 kbit/s.
* 2 - preamble, short_preamble enabled flag.
* 3 - MASK_RATE, which rates are enabled in this mode, this mask
* corresponds with the TX register format for the current device.
* 4 - plcp, 802.11b rates are device specific,
* 802.11g rates are set according to the ieee802.11a-1999 p.14.
* The bit to enable preamble is set in a seperate define.
*/
#define DEV_RATE FIELD32(0x000007ff)
#define DEV_PREAMBLE FIELD32(0x00000800)
#define DEV_RATEMASK FIELD32(0x00fff000)
#define DEV_PLCP FIELD32(0xff000000)
/*
* Bitfields
*/
#define DEV_RATEBIT_1MB ( 1 << 0 )
#define DEV_RATEBIT_2MB ( 1 << 1 )
#define DEV_RATEBIT_5_5MB ( 1 << 2 )
#define DEV_RATEBIT_11MB ( 1 << 3 )
#define DEV_RATEBIT_6MB ( 1 << 4 )
#define DEV_RATEBIT_9MB ( 1 << 5 )
#define DEV_RATEBIT_12MB ( 1 << 6 )
#define DEV_RATEBIT_18MB ( 1 << 7 )
#define DEV_RATEBIT_24MB ( 1 << 8 )
#define DEV_RATEBIT_36MB ( 1 << 9 )
#define DEV_RATEBIT_48MB ( 1 << 10 )
#define DEV_RATEBIT_54MB ( 1 << 11 )
/*
* Bitmasks for DEV_RATEMASK
*/
#define DEV_RATEMASK_1MB ( (DEV_RATEBIT_1MB << 1) -1 )
#define DEV_RATEMASK_2MB ( (DEV_RATEBIT_2MB << 1) -1 )
#define DEV_RATEMASK_5_5MB ( (DEV_RATEBIT_5_5MB << 1) -1 )
#define DEV_RATEMASK_11MB ( (DEV_RATEBIT_11MB << 1) -1 )
#define DEV_RATEMASK_6MB ( (DEV_RATEBIT_6MB << 1) -1 )
#define DEV_RATEMASK_9MB ( (DEV_RATEBIT_9MB << 1) -1 )
#define DEV_RATEMASK_12MB ( (DEV_RATEBIT_12MB << 1) -1 )
#define DEV_RATEMASK_18MB ( (DEV_RATEBIT_18MB << 1) -1 )
#define DEV_RATEMASK_24MB ( (DEV_RATEBIT_24MB << 1) -1 )
#define DEV_RATEMASK_36MB ( (DEV_RATEBIT_36MB << 1) -1 )
#define DEV_RATEMASK_48MB ( (DEV_RATEBIT_48MB << 1) -1 )
#define DEV_RATEMASK_54MB ( (DEV_RATEBIT_54MB << 1) -1 )
/*
* Bitmask groups of bitrates
*/
#define DEV_BASIC_RATEMASK \
( DEV_RATEMASK_11MB | \
DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB )
#define DEV_CCK_RATEMASK ( DEV_RATEMASK_11MB )
#define DEV_OFDM_RATEMASK ( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK )
/*
* Macro's to set and get specific fields from the device specific val and val2
* fields inside the ieee80211_rate entry.
*/
#define DEVICE_SET_RATE_FIELD(__value, __mask) \
(int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask )
#define DEVICE_GET_RATE_FIELD(__value, __mask) \
(int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset )
#endif /* RT2X00REG_H */

View File

@ -19,9 +19,8 @@
*/ */
/* /*
Module: rt2x00lib Module: rt2x00rfkill
Abstract: rt2x00 rfkill specific routines. Abstract: rt2x00 rfkill routines.
Supported chipsets: RT2460, RT2560, rt2561, rt2561s, rt2661.
*/ */
/* /*
@ -29,101 +28,119 @@
*/ */
#define DRV_NAME "rt2x00lib" #define DRV_NAME "rt2x00lib"
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rfkill.h> #include <linux/rfkill.h>
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00lib.h"
static int rt2x00lib_toggle_radio(void *data, enum rfkill_state state) static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state)
{ {
struct rt2x00_dev* rt2x00dev = data; struct rt2x00_dev *rt2x00dev = data;
int retval = 0; int retval = 0;
if (unlikely(!rt2x00dev)) if (unlikely(!rt2x00dev))
return 0; return 0;
/* /*
* Only continue if we have an active interface, * Only continue if there are enabled interfaces.
* either monitor or non-monitor should be present.
*/ */
if (!is_interface_present(&rt2x00dev->interface) && if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
!is_monitor_present(&rt2x00dev->interface))
return 0; return 0;
if (state == RFKILL_STATE_ON) { if (state == RFKILL_STATE_ON) {
INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n");
__set_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags); __clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
retval = rt2x00lib_enable_radio(rt2x00dev); retval = rt2x00lib_enable_radio(rt2x00dev);
} else if (state == RFKILL_STATE_OFF) { } else if (state == RFKILL_STATE_OFF) {
INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n");
__clear_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags); __set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
rt2x00lib_disable_radio(rt2x00dev); rt2x00lib_disable_radio(rt2x00dev);
} }
return retval; return retval;
} }
static void rt2x00lib_rfkill_poll(struct work_struct *work) static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev)
{ {
struct rt2x00_dev *rt2x00dev = struct rt2x00_dev *rt2x00dev = poll_dev->private;
container_of(work, struct rt2x00_dev, rfkill_work.work); int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
rfkill_switch_all(rt2x00dev->rfkill->type, if (rt2x00dev->rfkill->state != state)
rt2x00dev->ops->lib->rfkill_poll(rt2x00dev)); input_report_key(poll_dev->input, KEY_WLAN, 1);
queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work,
RFKILL_POLL_INTERVAL);
} }
int rt2x00lib_register_rfkill(struct rt2x00_dev *rt2x00dev) int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{ {
int status = rfkill_register(rt2x00dev->rfkill); int retval;
if (status) {
if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return 0;
retval = rfkill_register(rt2x00dev->rfkill);
if (retval) {
ERROR(rt2x00dev, "Failed to register rfkill handler.\n"); ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
return status; return retval;
} }
rt2x00lib_rfkill_poll(&rt2x00dev->rfkill_work.work); retval = input_register_polled_device(rt2x00dev->poll_dev);
if (retval) {
ERROR(rt2x00dev, "Failed to register polled device.\n");
rfkill_unregister(rt2x00dev->rfkill);
return retval;
}
return !schedule_delayed_work(&rt2x00dev->rfkill_work, return 0;
RFKILL_POLL_INTERVAL);
} }
void rt2x00lib_unregister_rfkill(struct rt2x00_dev *rt2x00dev) void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{ {
if (delayed_work_pending(&rt2x00dev->rfkill_work)) if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
cancel_rearming_delayed_workqueue( return;
rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work);
input_unregister_polled_device(rt2x00dev->poll_dev);
rfkill_unregister(rt2x00dev->rfkill); rfkill_unregister(rt2x00dev->rfkill);
} }
int rt2x00lib_allocate_rfkill(struct rt2x00_dev *rt2x00dev) int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
{ {
struct rfkill *rfkill; struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
if (!test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return 0; return 0;
rfkill = rfkill_allocate(rt2x00dev->device, RFKILL_TYPE_WLAN); rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
if (!rfkill) { if (!rt2x00dev->rfkill) {
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
return -ENOMEM; return -ENOMEM;
} }
rfkill->name = rt2x00dev->ops->name; rt2x00dev->rfkill->name = rt2x00dev->ops->name;
rfkill->data = rt2x00dev; rt2x00dev->rfkill->data = rt2x00dev;
rfkill->toggle_radio = rt2x00lib_toggle_radio; rt2x00dev->rfkill->state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
rt2x00dev->rfkill = rfkill; rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00lib_rfkill_poll); rt2x00dev->poll_dev = input_allocate_polled_device();
if (!rt2x00dev->poll_dev) {
ERROR(rt2x00dev, "Failed to allocate polled device.\n");
rfkill_free(rt2x00dev->rfkill);
return -ENOMEM;
}
rt2x00dev->poll_dev->private = rt2x00dev;
rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
return 0; return 0;
} }
void rt2x00lib_free_rfkill(struct rt2x00_dev *rt2x00dev) void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{ {
if (!test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
return; return;
input_free_polled_device(rt2x00dev->poll_dev);
rfkill_free(rt2x00dev->rfkill); rfkill_free(rt2x00dev->rfkill);
} }

View File

@ -0,0 +1,268 @@
/*
Copyright (C) 2004 - 2007 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: rt2x00
Abstract: rt2x00 ring datastructures and routines
*/
#ifndef RT2X00RING_H
#define RT2X00RING_H
/*
* data_desc
* Each data entry also contains a descriptor which is used by the
* device to determine what should be done with the packet and
* what the current status is.
* This structure is greatly simplified, but the descriptors
* are basically a list of little endian 32 bit values.
* Make the array by default 1 word big, this will allow us
* to use sizeof() correctly.
*/
struct data_desc {
__le32 word[1];
};
/*
* rxdata_entry_desc
* Summary of information that has been read from the
* RX frame descriptor.
*/
struct rxdata_entry_desc {
int signal;
int rssi;
int ofdm;
int size;
int flags;
};
/*
* txdata_entry_desc
* Summary of information that should be written into the
* descriptor for sending a TX frame.
*/
struct txdata_entry_desc {
unsigned long flags;
#define ENTRY_TXDONE 1
#define ENTRY_TXD_RTS_FRAME 2
#define ENTRY_TXD_OFDM_RATE 3
#define ENTRY_TXD_MORE_FRAG 4
#define ENTRY_TXD_REQ_TIMESTAMP 5
#define ENTRY_TXD_BURST 6
/*
* Queue ID. ID's 0-4 are data TX rings
*/
int queue;
#define QUEUE_MGMT 13
#define QUEUE_RX 14
#define QUEUE_OTHER 15
/*
* PLCP values.
*/
u16 length_high;
u16 length_low;
u16 signal;
u16 service;
/*
* Timing information
*/
int aifs;
int ifs;
int cw_min;
int cw_max;
};
/*
* data_entry
* The data ring is a list of data entries.
* Each entry holds a reference to the descriptor
* and the data buffer. For TX rings the reference to the
* sk_buff of the packet being transmitted is also stored here.
*/
struct data_entry {
/*
* Status flags
*/
unsigned long flags;
#define ENTRY_OWNER_NIC 1
/*
* Ring we belong to.
*/
struct data_ring *ring;
/*
* sk_buff for the packet which is being transmitted
* in this entry (Only used with TX related rings).
*/
struct sk_buff *skb;
/*
* Store a ieee80211_tx_status structure in each
* ring entry, this will optimize the txdone
* handler.
*/
struct ieee80211_tx_status tx_status;
/*
* private pointer specific to driver.
*/
void *priv;
/*
* Data address for this entry.
*/
void *data_addr;
dma_addr_t data_dma;
};
/*
* data_ring
* Data rings are used by the device to send and receive packets.
* The data_addr is the base address of the data memory.
* To determine at which point in the ring we are,
* have to use the rt2x00_ring_index_*() functions.
*/
struct data_ring {
/*
* Pointer to main rt2x00dev structure where this
* ring belongs to.
*/
struct rt2x00_dev *rt2x00dev;
/*
* Base address for the device specific data entries.
*/
struct data_entry *entry;
/*
* TX queue statistic info.
*/
struct ieee80211_tx_queue_stats_data stats;
/*
* TX Queue parameters.
*/
struct ieee80211_tx_queue_params tx_params;
/*
* Base address for data ring.
*/
dma_addr_t data_dma;
void *data_addr;
/*
* Index variables.
*/
u16 index;
u16 index_done;
/*
* Size of packet and descriptor in bytes.
*/
u16 data_size;
u16 desc_size;
};
/*
* Handlers to determine the address of the current device specific
* data entry, where either index or index_done points to.
*/
static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
{
return &ring->entry[ring->index];
}
static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
*ring)
{
return &ring->entry[ring->index_done];
}
/*
* Total ring memory
*/
static inline int rt2x00_get_ring_size(struct data_ring *ring)
{
return ring->stats.limit * (ring->desc_size + ring->data_size);
}
/*
* Ring index manipulation functions.
*/
static inline void rt2x00_ring_index_inc(struct data_ring *ring)
{
ring->index++;
if (ring->index >= ring->stats.limit)
ring->index = 0;
ring->stats.len++;
}
static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
{
ring->index_done++;
if (ring->index_done >= ring->stats.limit)
ring->index_done = 0;
ring->stats.len--;
ring->stats.count++;
}
static inline void rt2x00_ring_index_clear(struct data_ring *ring)
{
ring->index = 0;
ring->index_done = 0;
ring->stats.len = 0;
ring->stats.count = 0;
}
static inline int rt2x00_ring_empty(struct data_ring *ring)
{
return ring->stats.len == 0;
}
static inline int rt2x00_ring_full(struct data_ring *ring)
{
return ring->stats.len == ring->stats.limit;
}
static inline int rt2x00_ring_free(struct data_ring *ring)
{
return ring->stats.limit - ring->stats.len;
}
/*
* TX/RX Descriptor access functions.
*/
static inline void rt2x00_desc_read(struct data_desc *desc,
const u8 word, u32 *value)
{
*value = le32_to_cpu(desc->word[word]);
}
static inline void rt2x00_desc_write(struct data_desc *desc,
const u8 word, const u32 value)
{
desc->word[word] = cpu_to_le32(value);
}
#endif /* RT2X00RING_H */

View File

@ -21,7 +21,6 @@
/* /*
Module: rt2x00usb Module: rt2x00usb
Abstract: rt2x00 generic usb device routines. Abstract: rt2x00 generic usb device routines.
Supported chipsets: rt2570, rt2571W & rt2671.
*/ */
/* /*
@ -31,169 +30,87 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/usb.h> #include <linux/usb.h>
#include "rt2x00.h" #include "rt2x00.h"
#include "rt2x00lib.h"
#include "rt2x00usb.h" #include "rt2x00usb.h"
/* /*
* Interfacing with the HW. * Interfacing with the HW.
*/ */
int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 type, const u16 offset, const u8 request, const u8 requesttype,
u32 value, void *buffer, const u16 buffer_length, const u16 timeout) const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
const int timeout)
{ {
struct usb_device *usb_dev = interface_to_usbdev( struct usb_device *usb_dev =
rt2x00dev_usb(rt2x00dev)); interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
int status; int status;
unsigned int i; unsigned int i;
unsigned int pipe =
(requesttype == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
for (i = 0; i < REGISTER_BUSY_COUNT; i++) { for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
status = usb_control_msg( status = usb_control_msg(usb_dev, pipe, request, requesttype,
usb_dev, value, offset, buffer, buffer_length,
(type == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) :
usb_sndctrlpipe(usb_dev, 0),
request, type, value, offset, buffer, buffer_length,
timeout); timeout);
if (status >= 0) if (status >= 0)
return 0; return 0;
/*
* Check for errors
* -ENODEV: Device has disappeared, no point continuing.
* All other errors: Try again.
*/
else if (status == -ENODEV)
break;
} }
ERROR(rt2x00dev, "Vendor Request 0x%02x failed for offset 0x%04x" ERROR(rt2x00dev,
" with error %d.\n", request, offset, status); "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n",
request, offset, status);
return status; return status;
} }
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request); EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
/* int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
* Beacon handlers. const u8 request, const u8 requesttype,
*/ const u16 offset, void *buffer,
int rt2x00usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, const u16 buffer_length, const int timeout)
struct ieee80211_tx_control *control)
{ {
struct rt2x00_dev *rt2x00dev = hw->priv; int status;
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_ring *ring =
rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
struct data_entry *beacon;
struct data_entry *guardian;
int length;
/* /*
* Just in case the ieee80211 doesn't set this, * Check for Cache availability.
* but we need this queue set for the descriptor
* initialization.
*/ */
control->queue = IEEE80211_TX_QUEUE_BEACON; if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
ERROR(rt2x00dev, "CSR cache not available.\n");
/* return -ENOMEM;
* Obtain 2 entries, one for the guardian byte,
* the second for the actual beacon.
*/
guardian = rt2x00_get_data_entry(ring);
rt2x00_ring_index_inc(ring);
beacon = rt2x00_get_data_entry(ring);
/*
* First we create the beacon.
*/
skb_push(skb, ring->desc_size);
rt2x00lib_write_tx_desc(rt2x00dev, beacon,
(struct data_desc*)skb->data,
(struct ieee80211_hdr*)(skb->data + ring->desc_size),
skb->len - ring->desc_size,
control);
/*
* Length passed to usb_fill_urb cannot be an odd number,
* so add 1 byte to make it even.
*/
length = skb->len;
if (length % 2)
length++;
usb_fill_bulk_urb(
beacon->priv,
usb_dev,
usb_sndbulkpipe(usb_dev, 1),
skb->data,
length,
rt2x00usb_beacondone,
beacon);
beacon->skb = skb;
/*
* Second we need to create the guardian byte.
* We only need a single byte, so lets recycle
* the 'flags' field we are not using for beacons.
*/
guardian->flags = 0;
usb_fill_bulk_urb(
guardian->priv,
usb_dev,
usb_sndbulkpipe(usb_dev, 1),
&guardian->flags,
1,
rt2x00usb_beacondone,
guardian);
/*
* Send out the guardian byte.
*/
usb_submit_urb(guardian->priv, GFP_ATOMIC);
/*
* Enable beacon generation.
*/
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_beacon_update);
void rt2x00usb_beacondone(struct urb *urb)
{
struct data_entry *entry = (struct data_entry*)urb->context;
struct data_ring *ring = entry->ring;
if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
return;
/*
* Check if this was the guardian beacon,
* if that was the case we need to send the real beacon now.
* Otherwise we should free the sk_buffer, the device
* should be doing the rest of the work now.
*/
if (ring->index == 1) {
rt2x00_ring_index_done_inc(ring);
entry = rt2x00_get_data_entry(ring);
usb_submit_urb(entry->priv, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
} else if (ring->index_done == 1) {
entry = rt2x00_get_data_entry_done(ring);
if (entry->skb) {
dev_kfree_skb(entry->skb);
entry->skb = NULL;
}
rt2x00_ring_index_done_inc(ring);
} }
if (requesttype == USB_VENDOR_REQUEST_OUT)
memcpy(rt2x00dev->csr_cache, buffer, buffer_length);
status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
offset, 0, rt2x00dev->csr_cache,
buffer_length, timeout);
if (!status && requesttype == USB_VENDOR_REQUEST_IN)
memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
return status;
} }
EXPORT_SYMBOL_GPL(rt2x00usb_beacondone); EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
/* /*
* TX data handlers. * TX data handlers.
*/ */
static void rt2x00usb_interrupt_txdone(struct urb *urb) static void rt2x00usb_interrupt_txdone(struct urb *urb)
{ {
struct data_entry *entry = (struct data_entry*)urb->context; struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring; struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct data_desc *txd = (struct data_desc *)entry->skb->data; struct data_desc *txd = (struct data_desc *)entry->skb->data;
@ -240,10 +157,9 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
{ {
struct usb_device *usb_dev = struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_entry *entry = rt2x00_get_data_entry(ring); struct data_entry *entry = rt2x00_get_data_entry(ring);
struct data_desc *txd; int pipe = usb_sndbulkpipe(usb_dev, 1);
u32 length = skb->len; u32 length;
if (rt2x00_ring_full(ring)) { if (rt2x00_ring_full(ring)) {
ieee80211_stop_queue(rt2x00dev->hw, control->queue); ieee80211_stop_queue(rt2x00dev->hw, control->queue);
@ -255,34 +171,36 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n" "Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n", "Please file bug report to %s.\n",
control->queue, DRV_PROJECT); control->queue, DRV_PROJECT);
ieee80211_stop_queue( rt2x00dev->hw, control->queue); ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL; return -EINVAL;
} }
skb_push(skb, rt2x00dev->hw->extra_tx_headroom); /*
txd = (struct data_desc*)skb->data; * Add the descriptor in front of the skb.
rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr, */
length, control); skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
(struct ieee80211_hdr *)(skb->data +
ring->desc_size),
skb->len - ring->desc_size, control);
memcpy(&entry->tx_status.control, control, sizeof(*control)); memcpy(&entry->tx_status.control, control, sizeof(*control));
entry->skb = skb; entry->skb = skb;
/* /*
* Length passed to usb_fill_urb cannot be an odd number, * USB devices cannot blindly pass the skb->len as the
* so add 1 byte to make it even. * length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/ */
length += rt2x00dev->hw->extra_tx_headroom; length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb);
if (length % 2)
length++;
/*
* Initialize URB and send the frame to the device.
*/
__set_bit(ENTRY_OWNER_NIC, &entry->flags); __set_bit(ENTRY_OWNER_NIC, &entry->flags);
usb_fill_bulk_urb( usb_fill_bulk_urb(entry->priv, usb_dev, pipe,
entry->priv, skb->data, length, rt2x00usb_interrupt_txdone, entry);
usb_dev,
usb_sndbulkpipe(usb_dev, 1),
skb->data,
length,
rt2x00usb_interrupt_txdone,
entry);
usb_submit_urb(entry->priv, GFP_ATOMIC); usb_submit_urb(entry->priv, GFP_ATOMIC);
rt2x00_ring_index_inc(ring); rt2x00_ring_index_inc(ring);
@ -299,13 +217,14 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
*/ */
static void rt2x00usb_interrupt_rxdone(struct urb *urb) static void rt2x00usb_interrupt_rxdone(struct urb *urb)
{ {
struct data_entry *entry = (struct data_entry*)urb->context; struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring; struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
int signal; struct sk_buff *skb;
int rssi; struct ieee80211_hdr *hdr;
int ofdm; struct rxdata_entry_desc desc;
int size; int header_size;
int frame_size;
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
!test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags)) !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
@ -319,21 +238,56 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
if (urb->actual_length < entry->ring->desc_size || urb->status) if (urb->actual_length < entry->ring->desc_size || urb->status)
goto skip_entry; goto skip_entry;
size = rt2x00dev->ops->lib->fill_rxdone(entry, &signal, &rssi, &ofdm); memset(&desc, 0x00, sizeof(desc));
if (size < 0) rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
/*
* Allocate a new sk buffer to replace the current one.
* If allocation fails, we should drop the current frame
* so we can recycle the existing sk buffer for the new frame.
* As alignment we use 2 and not NET_IP_ALIGN because we need
* to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
* can be 0 on some hardware). We use these 2 bytes for frame
* alignment later, we assume that the chance that
* header_size % 4 == 2 is bigger then header_size % 2 == 0
* and thus optimize alignment by reserving the 2 bytes in
* advance.
*/
frame_size = entry->ring->data_size + entry->ring->desc_size;
skb = dev_alloc_skb(frame_size + 2);
if (!skb)
goto skip_entry; goto skip_entry;
/* skb_reserve(skb, 2);
* Trim the skb_buffer to only contain the valid skb_put(skb, frame_size);
* frame data (so ignore the device's descriptor).
*/
skb_trim(entry->skb, size);
/* /*
* Send the packet to upper layer, and update urb. * The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
* After that trim the entire buffer down to only
* contain the valid frame data excluding the device
* descriptor.
*/ */
rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size, hdr = (struct ieee80211_hdr *)entry->skb->data;
signal, rssi, ofdm); header_size =
ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
if (header_size % 4 == 0) {
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
}
skb_trim(entry->skb, desc.size);
/*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, entry->skb, &desc);
/*
* Replace current entry's skb with the newly allocated one,
* and reinitialize the urb.
*/
entry->skb = skb;
urb->transfer_buffer = entry->skb->data; urb->transfer_buffer = entry->skb->data;
urb->transfer_buffer_length = entry->skb->len; urb->transfer_buffer_length = entry->skb->len;
@ -375,14 +329,10 @@ void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
entry = &rt2x00dev->rx->entry[i]; entry = &rt2x00dev->rx->entry[i];
usb_fill_bulk_urb( usb_fill_bulk_urb(entry->priv, usb_dev,
entry->priv,
usb_dev,
usb_rcvbulkpipe(usb_dev, 1), usb_rcvbulkpipe(usb_dev, 1),
entry->skb->data, entry->skb->data, entry->skb->len,
entry->skb->len, rt2x00usb_interrupt_rxdone, entry);
rt2x00usb_interrupt_rxdone,
entry);
__set_bit(ENTRY_OWNER_NIC, &entry->flags); __set_bit(ENTRY_OWNER_NIC, &entry->flags);
usb_submit_urb(entry->priv, GFP_ATOMIC); usb_submit_urb(entry->priv, GFP_ATOMIC);
@ -395,8 +345,8 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
struct data_ring *ring; struct data_ring *ring;
unsigned int i; unsigned int i;
rt2x00usb_vendor_request(rt2x00dev, USB_RX_CONTROL, rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0, REGISTER_TIMEOUT); REGISTER_TIMEOUT);
/* /*
* Cancel all rings. * Cancel all rings.
@ -411,7 +361,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
/* /*
* Device initialization handlers. * Device initialization handlers.
*/ */
static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev, static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring) struct data_ring *ring)
{ {
unsigned int i; unsigned int i;
@ -428,6 +378,22 @@ static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev,
return 0; return 0;
} }
static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
unsigned int i;
if (!ring->entry)
return;
for (i = 0; i < ring->stats.limit; i++) {
usb_kill_urb(ring->entry[i].priv);
usb_free_urb(ring->entry[i].priv);
if (ring->entry[i].skb)
kfree_skb(ring->entry[i].skb);
}
}
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
{ {
struct data_ring *ring; struct data_ring *ring;
@ -440,7 +406,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA * Allocate DMA
*/ */
ring_for_each(rt2x00dev, ring) { ring_for_each(rt2x00dev, ring) {
status = rt2x00usb_alloc_ring(rt2x00dev, ring); status = rt2x00usb_alloc_urb(rt2x00dev, ring);
if (status) if (status)
goto exit; goto exit;
} }
@ -448,7 +414,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
/* /*
* For the RX ring, skb's should be allocated. * For the RX ring, skb's should be allocated.
*/ */
entry_size = ring->data_size + ring->desc_size; entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size;
for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
skb = dev_alloc_skb(NET_IP_ALIGN + entry_size); skb = dev_alloc_skb(NET_IP_ALIGN + entry_size);
if (!skb) if (!skb)
@ -472,30 +438,56 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
{ {
struct data_ring *ring; struct data_ring *ring;
unsigned int i;
ring_for_each(rt2x00dev, ring) { ring_for_each(rt2x00dev, ring)
if (!ring->entry) rt2x00usb_free_urb(rt2x00dev, ring);
continue;
for (i = 0; i < ring->stats.limit; i++) {
usb_kill_urb(ring->entry[i].priv);
usb_free_urb(ring->entry[i].priv);
if (ring->entry[i].skb)
kfree_skb(ring->entry[i].skb);
}
}
} }
EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
/* /*
* USB driver handlers. * USB driver handlers.
*/ */
static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
{
kfree(rt2x00dev->rf);
rt2x00dev->rf = NULL;
kfree(rt2x00dev->eeprom);
rt2x00dev->eeprom = NULL;
kfree(rt2x00dev->csr_cache);
rt2x00dev->csr_cache = NULL;
}
static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
{
rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
if (!rt2x00dev->csr_cache)
goto exit;
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
if (!rt2x00dev->eeprom)
goto exit;
rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
if (!rt2x00dev->rf)
goto exit;
return 0;
exit:
ERROR_PROBE("Failed to allocate registers.\n");
rt2x00usb_free_reg(rt2x00dev);
return -ENOMEM;
}
int rt2x00usb_probe(struct usb_interface *usb_intf, int rt2x00usb_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *usb_dev = interface_to_usbdev(usb_intf); struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_info; struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev; struct rt2x00_dev *rt2x00dev;
int retval; int retval;
@ -516,12 +508,24 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
rt2x00dev->ops = ops; rt2x00dev->ops = ops;
rt2x00dev->hw = hw; rt2x00dev->hw = hw;
retval = rt2x00lib_probe_dev(rt2x00dev); rt2x00dev->usb_maxpacket =
usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
if (!rt2x00dev->usb_maxpacket)
rt2x00dev->usb_maxpacket = 1;
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval) if (retval)
goto exit_free_device; goto exit_free_device;
retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval)
goto exit_free_reg;
return 0; return 0;
exit_free_reg:
rt2x00usb_free_reg(rt2x00dev);
exit_free_device: exit_free_device:
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
@ -543,6 +547,7 @@ void rt2x00usb_disconnect(struct usb_interface *usb_intf)
* Free all allocated data. * Free all allocated data.
*/ */
rt2x00lib_remove_dev(rt2x00dev); rt2x00lib_remove_dev(rt2x00dev);
rt2x00usb_free_reg(rt2x00dev);
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
/* /*
@ -564,6 +569,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
if (retval) if (retval)
return retval; return retval;
rt2x00usb_free_reg(rt2x00dev);
/* /*
* Decrease usbdev refcount. * Decrease usbdev refcount.
*/ */
@ -577,10 +584,24 @@ int rt2x00usb_resume(struct usb_interface *usb_intf)
{ {
struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_dev *rt2x00dev = hw->priv;
int retval;
usb_get_dev(interface_to_usbdev(usb_intf)); usb_get_dev(interface_to_usbdev(usb_intf));
return rt2x00lib_resume(rt2x00dev); retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
return retval;
retval = rt2x00lib_resume(rt2x00dev);
if (retval)
goto exit_free_reg;
return 0;
exit_free_reg:
rt2x00usb_free_reg(rt2x00dev);
return retval;
} }
EXPORT_SYMBOL_GPL(rt2x00usb_resume); EXPORT_SYMBOL_GPL(rt2x00usb_resume);
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */

View File

@ -21,7 +21,6 @@
/* /*
Module: rt2x00usb Module: rt2x00usb
Abstract: Data structures for the rt2x00usb module. Abstract: Data structures for the rt2x00usb module.
Supported chipsets: rt2570, rt2571W & rt2671.
*/ */
#ifndef RT2X00USB_H #ifndef RT2X00USB_H
@ -35,19 +34,25 @@
/* /*
* Register defines. * Register defines.
* When register access attempts should be repeated * Some registers require multiple attempts before success,
* only REGISTER_BUSY_COUNT attempts with a delay * in those cases REGISTER_BUSY_COUNT attempts should be
* of REGISTER_BUSY_DELAY us should be taken. * taken with a REGISTER_BUSY_DELAY interval.
* For USB vendor requests we need to pass a timeout * For USB vendor requests we need to pass a timeout
* time in ms, for this we use the REGISTER_TIMEOUT, * time in ms, for this we use the REGISTER_TIMEOUT,
* however when loading firmware a higher value is * however when loading firmware a higher value is
* required. For that we use the REGISTER_TIMEOUT_FIRMWARE. * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE.
*/ */
#define REGISTER_BUSY_COUNT 5 #define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100 #define REGISTER_BUSY_DELAY 100
#define REGISTER_TIMEOUT 20 #define REGISTER_TIMEOUT 500
#define REGISTER_TIMEOUT_FIRMWARE 1000 #define REGISTER_TIMEOUT_FIRMWARE 1000
/*
* Cache size
*/
#define CSR_CACHE_SIZE 8
#define CSR_CACHE_SIZE_FIRMWARE 64
/* /*
* USB request types. * USB request types.
*/ */
@ -80,17 +85,64 @@
#define USB_MODE_WAKEUP 0x09 /* RT73USB */ #define USB_MODE_WAKEUP 0x09 /* RT73USB */
/* /*
* USB devices need an additional Beacon (guardian beacon) to be generated. * Used to read/write from/to the device.
*/ * This is the main function to communicate with the device,
#undef BEACON_ENTRIES * the buffer argument _must_ either be NULL or point to
#define BEACON_ENTRIES 2 * a buffer allocated by kmalloc. Failure to do so can lead
* to unexpected behavior depending on the architecture.
/*
* Interfacing with the HW.
*/ */
int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev, int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 type, const u16 offset, const u8 request, const u8 requesttype,
u32 value, void *buffer, const u16 buffer_length, const u16 timeout); const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
const int timeout);
/*
* Used to read/write from/to the device.
* This function will use a previously with kmalloc allocated cache
* to communicate with the device. The contents of the buffer pointer
* will be copied to this cache when writing, or read from the cache
* when reading.
* Buffers send to rt2x00usb_vendor_request _must_ be allocated with
* kmalloc. Hence the reason for using a previously allocated cache
* which has been allocated properly.
*/
int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout);
/*
* Simple wrapper around rt2x00usb_vendor_request to write a single
* command to the device. Since we don't use the buffer argument we
* don't have to worry about kmalloc here.
*/
static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev
*rt2x00dev,
const u8 request,
const u16 offset,
const u16 value,
const int timeout)
{
return rt2x00usb_vendor_request(rt2x00dev, request,
USB_VENDOR_REQUEST_OUT, offset,
value, NULL, 0, timeout);
}
/*
* Simple wrapper around rt2x00usb_vendor_request to read the eeprom
* from the device. Note that the eeprom argument _must_ be allocated using
* kmalloc for correct handling inside the kernel USB layer.
*/
static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev,
__le16 *eeprom, const u16 lenght)
{
int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
USB_VENDOR_REQUEST_IN, 0x0000,
0x0000, eeprom, lenght, timeout);
}
/* /*
* Radio handlers * Radio handlers
@ -98,13 +150,6 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
/*
* Beacon handlers.
*/
int rt2x00usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control);
void rt2x00usb_beacondone(struct urb *urb);
/* /*
* TX data handlers. * TX data handlers.
*/ */
@ -127,6 +172,9 @@ void rt2x00usb_disconnect(struct usb_interface *usb_intf);
#ifdef CONFIG_PM #ifdef CONFIG_PM
int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state); int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
int rt2x00usb_resume(struct usb_interface *usb_intf); int rt2x00usb_resume(struct usb_interface *usb_intf);
#else
#define rt2x00usb_suspend NULL
#define rt2x00usb_resume NULL
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
#endif /* RT2X00USB_H */ #endif /* RT2X00USB_H */

File diff suppressed because it is too large Load Diff

View File

@ -37,9 +37,10 @@
/* /*
* Signal information. * Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/ */
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1 #define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 120 #define DEFAULT_RSSI_OFFSET 120
/* /*
@ -50,6 +51,7 @@
#define EEPROM_BASE 0x0000 #define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100 #define EEPROM_SIZE 0x0100
#define BBP_SIZE 0x0080 #define BBP_SIZE 0x0080
#define RF_SIZE 0x0014
/* /*
* PCI registers. * PCI registers.
@ -260,7 +262,7 @@ struct hw_pairwise_ta_entry {
* MAC_CSR6: Maximum frame length register. * MAC_CSR6: Maximum frame length register.
*/ */
#define MAC_CSR6 0x3018 #define MAC_CSR6 0x3018
#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x000007ff) #define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x00000fff)
/* /*
* MAC_CSR7: Reserved * MAC_CSR7: Reserved
@ -330,6 +332,11 @@ struct hw_pairwise_ta_entry {
#define MAC_CSR13_BIT5 FIELD32(0x00000020) #define MAC_CSR13_BIT5 FIELD32(0x00000020)
#define MAC_CSR13_BIT6 FIELD32(0x00000040) #define MAC_CSR13_BIT6 FIELD32(0x00000040)
#define MAC_CSR13_BIT7 FIELD32(0x00000080) #define MAC_CSR13_BIT7 FIELD32(0x00000080)
#define MAC_CSR13_BIT8 FIELD32(0x00000100)
#define MAC_CSR13_BIT9 FIELD32(0x00000200)
#define MAC_CSR13_BIT10 FIELD32(0x00000400)
#define MAC_CSR13_BIT11 FIELD32(0x00000800)
#define MAC_CSR13_BIT12 FIELD32(0x00001000)
/* /*
* MAC_CSR14: LED control register. * MAC_CSR14: LED control register.
@ -392,16 +399,40 @@ struct hw_pairwise_ta_entry {
* TXRX_CSR1 * TXRX_CSR1
*/ */
#define TXRX_CSR1 0x3044 #define TXRX_CSR1 0x3044
#define TXRX_CSR1_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR1_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR1_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR1_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR1_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR1_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR1_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR1_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXRX_CSR2 * TXRX_CSR2
*/ */
#define TXRX_CSR2 0x3048 #define TXRX_CSR2 0x3048
#define TXRX_CSR2_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR2_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR2_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR2_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR2_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR2_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR2_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR2_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXRX_CSR3 * TXRX_CSR3
*/ */
#define TXRX_CSR3 0x304c #define TXRX_CSR3 0x304c
#define TXRX_CSR3_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR3_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR3_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR3_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR3_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR3_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR3_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR3_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXRX_CSR4: Auto-Responder/Tx-retry register. * TXRX_CSR4: Auto-Responder/Tx-retry register.
@ -428,11 +459,27 @@ struct hw_pairwise_ta_entry {
#define TXRX_CSR5 0x3054 #define TXRX_CSR5 0x3054
/* /*
* ACK/CTS payload consumed time registers. * TXRX_CSR6: ACK/CTS payload consumed time
*/ */
#define TXRX_CSR6 0x3058 #define TXRX_CSR6 0x3058
/*
* TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
*/
#define TXRX_CSR7 0x305c #define TXRX_CSR7 0x305c
#define TXRX_CSR7_ACK_CTS_6MBS FIELD32(0x000000ff)
#define TXRX_CSR7_ACK_CTS_9MBS FIELD32(0x0000ff00)
#define TXRX_CSR7_ACK_CTS_12MBS FIELD32(0x00ff0000)
#define TXRX_CSR7_ACK_CTS_18MBS FIELD32(0xff000000)
/*
* TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define TXRX_CSR8 0x3060 #define TXRX_CSR8 0x3060
#define TXRX_CSR8_ACK_CTS_24MBS FIELD32(0x000000ff)
#define TXRX_CSR8_ACK_CTS_36MBS FIELD32(0x0000ff00)
#define TXRX_CSR8_ACK_CTS_48MBS FIELD32(0x00ff0000)
#define TXRX_CSR8_ACK_CTS_54MBS FIELD32(0xff000000)
/* /*
* TXRX_CSR9: Synchronization control register. * TXRX_CSR9: Synchronization control register.
@ -481,7 +528,6 @@ struct hw_pairwise_ta_entry {
*/ */
#define TXRX_CSR15 0x307c #define TXRX_CSR15 0x307c
/* /*
* PHY control registers. * PHY control registers.
* Some values are set in TU, whereas 1 TU == 1024 us. * Some values are set in TU, whereas 1 TU == 1024 us.
@ -536,11 +582,13 @@ struct hw_pairwise_ta_entry {
* PHY_CSR5: RX to TX signal switch timing control. * PHY_CSR5: RX to TX signal switch timing control.
*/ */
#define PHY_CSR5 0x3094 #define PHY_CSR5 0x3094
#define PHY_CSR5_IQ_FLIP FIELD32(0x00000004)
/* /*
* PHY_CSR6: TX to RX signal timing control. * PHY_CSR6: TX to RX signal timing control.
*/ */
#define PHY_CSR6 0x3098 #define PHY_CSR6 0x3098
#define PHY_CSR6_IQ_FLIP FIELD32(0x00000004)
/* /*
* PHY_CSR7: TX DAC switching timing control. * PHY_CSR7: TX DAC switching timing control.
@ -555,6 +603,22 @@ struct hw_pairwise_ta_entry {
* SEC_CSR0: Shared key table control. * SEC_CSR0: Shared key table control.
*/ */
#define SEC_CSR0 0x30a0 #define SEC_CSR0 0x30a0
#define SEC_CSR0_BSS0_KEY0_VALID FIELD32(0x00000001)
#define SEC_CSR0_BSS0_KEY1_VALID FIELD32(0x00000002)
#define SEC_CSR0_BSS0_KEY2_VALID FIELD32(0x00000004)
#define SEC_CSR0_BSS0_KEY3_VALID FIELD32(0x00000008)
#define SEC_CSR0_BSS1_KEY0_VALID FIELD32(0x00000010)
#define SEC_CSR0_BSS1_KEY1_VALID FIELD32(0x00000020)
#define SEC_CSR0_BSS1_KEY2_VALID FIELD32(0x00000040)
#define SEC_CSR0_BSS1_KEY3_VALID FIELD32(0x00000080)
#define SEC_CSR0_BSS2_KEY0_VALID FIELD32(0x00000100)
#define SEC_CSR0_BSS2_KEY1_VALID FIELD32(0x00000200)
#define SEC_CSR0_BSS2_KEY2_VALID FIELD32(0x00000400)
#define SEC_CSR0_BSS2_KEY3_VALID FIELD32(0x00000800)
#define SEC_CSR0_BSS3_KEY0_VALID FIELD32(0x00001000)
#define SEC_CSR0_BSS3_KEY1_VALID FIELD32(0x00002000)
#define SEC_CSR0_BSS3_KEY2_VALID FIELD32(0x00004000)
#define SEC_CSR0_BSS3_KEY3_VALID FIELD32(0x00008000)
/* /*
* SEC_CSR1: Shared key table security mode register. * SEC_CSR1: Shared key table security mode register.
@ -768,9 +832,15 @@ struct hw_pairwise_ta_entry {
#define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000) #define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000)
/* /*
* TX_DMA_DST_CSR * TX_DMA_DST_CSR: TX DMA destination
* 0: TX ring0, 1: TX ring1, 2: TX ring2 3: invalid
*/ */
#define TX_DMA_DST_CSR 0x342c #define TX_DMA_DST_CSR 0x342c
#define TX_DMA_DST_CSR_DEST_AC0 FIELD32(0x00000003)
#define TX_DMA_DST_CSR_DEST_AC1 FIELD32(0x0000000c)
#define TX_DMA_DST_CSR_DEST_AC2 FIELD32(0x00000030)
#define TX_DMA_DST_CSR_DEST_AC3 FIELD32(0x000000c0)
#define TX_DMA_DST_CSR_DEST_MGMT FIELD32(0x00000300)
/* /*
* TX_CNTL_CSR: KICK/Abort TX. * TX_CNTL_CSR: KICK/Abort TX.
@ -796,9 +866,14 @@ struct hw_pairwise_ta_entry {
#define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000) #define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000)
/* /*
* LOAD_TX_RING_CSR * LOAD_TX_RING_CSR: Load RX de
*/ */
#define LOAD_TX_RING_CSR 0x3434 #define LOAD_TX_RING_CSR 0x3434
#define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001)
#define LOAD_TX_RING_CSR_LOAD_TXD_AC1 FIELD32(0x00000002)
#define LOAD_TX_RING_CSR_LOAD_TXD_AC2 FIELD32(0x00000004)
#define LOAD_TX_RING_CSR_LOAD_TXD_AC3 FIELD32(0x00000008)
#define LOAD_TX_RING_CSR_LOAD_TXD_MGMT FIELD32(0x00000010)
/* /*
* Several read-only registers, for debugging. * Several read-only registers, for debugging.
@ -828,6 +903,8 @@ struct hw_pairwise_ta_entry {
* RX_CNTL_CSR * RX_CNTL_CSR
*/ */
#define RX_CNTL_CSR 0x3458 #define RX_CNTL_CSR 0x3458
#define RX_CNTL_CSR_ENABLE_RX_DMA FIELD32(0x00000001)
#define RX_CNTL_CSR_LOAD_RXD FIELD32(0x00000002)
/* /*
* RXPTR_CSR: Read-only, for debugging. * RXPTR_CSR: Read-only, for debugging.
@ -981,10 +1058,45 @@ struct hw_pairwise_ta_entry {
#define FIRMWARE_RT2661 "rt2661.bin" #define FIRMWARE_RT2661 "rt2661.bin"
#define FIRMWARE_IMAGE_BASE 0x4000 #define FIRMWARE_IMAGE_BASE 0x4000
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x20)
/*
* R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/* /*
* RF registers * RF registers
*/ */
/*
* RF 3
*/
#define RF3_TXPOWER FIELD32(0x00003e00) #define RF3_TXPOWER FIELD32(0x00003e00)
/*
* RF 4
*/
#define RF4_FREQ_OFFSET FIELD32(0x0003f000) #define RF4_FREQ_OFFSET FIELD32(0x0003f000)
/* /*
@ -1117,34 +1229,6 @@ struct hw_pairwise_ta_entry {
#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff) #define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff)
#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00) #define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* BBP_R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* BBP_R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x10)
#define BBP_R4_RX_BG_MODE FIELD8(0x20)
/*
* BBP_R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/* /*
* MCU mailbox commands. * MCU mailbox commands.
*/ */
@ -1290,7 +1374,7 @@ struct hw_pairwise_ta_entry {
#define RXD_W0_MULTICAST FIELD32(0x00000008) #define RXD_W0_MULTICAST FIELD32(0x00000008)
#define RXD_W0_BROADCAST FIELD32(0x00000010) #define RXD_W0_BROADCAST FIELD32(0x00000010)
#define RXD_W0_MY_BSS FIELD32(0x00000020) #define RXD_W0_MY_BSS FIELD32(0x00000020)
#define RXD_W0_CRC FIELD32(0x00000040) #define RXD_W0_CRC_ERROR FIELD32(0x00000040)
#define RXD_W0_OFDM FIELD32(0x00000080) #define RXD_W0_OFDM FIELD32(0x00000080)
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000300) #define RXD_W0_CIPHER_ERROR FIELD32(0x00000300)
#define RXD_W0_KEY_INDEX FIELD32(0x0000fc00) #define RXD_W0_KEY_INDEX FIELD32(0x0000fc00)

File diff suppressed because it is too large Load Diff

View File

@ -37,9 +37,10 @@
/* /*
* Signal information. * Signal information.
* Defaul offset is required for RSSI <-> dBm conversion.
*/ */
#define MAX_SIGNAL 100
#define MAX_RX_SSI -1 #define MAX_RX_SSI -1
#define MAX_RX_NOISE -110
#define DEFAULT_RSSI_OFFSET 120 #define DEFAULT_RSSI_OFFSET 120
/* /*
@ -50,6 +51,7 @@
#define EEPROM_BASE 0x0000 #define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100 #define EEPROM_SIZE 0x0100
#define BBP_SIZE 0x0080 #define BBP_SIZE 0x0080
#define RF_SIZE 0x0014
/* /*
* USB registers. * USB registers.
@ -172,7 +174,7 @@ struct hw_pairwise_ta_entry {
* MAC_CSR6: Maximum frame length register. * MAC_CSR6: Maximum frame length register.
*/ */
#define MAC_CSR6 0x3018 #define MAC_CSR6 0x3018
#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x000007ff) #define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x00000fff)
/* /*
* MAC_CSR7: Reserved * MAC_CSR7: Reserved
@ -288,7 +290,7 @@ struct hw_pairwise_ta_entry {
#define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000)
#define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000)
#define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000)
#define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000) #define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000)
#define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000)
#define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000)
@ -296,16 +298,40 @@ struct hw_pairwise_ta_entry {
* TXRX_CSR1 * TXRX_CSR1
*/ */
#define TXRX_CSR1 0x3044 #define TXRX_CSR1 0x3044
#define TXRX_CSR1_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR1_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR1_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR1_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR1_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR1_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR1_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR1_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXRX_CSR2 * TXRX_CSR2
*/ */
#define TXRX_CSR2 0x3048 #define TXRX_CSR2 0x3048
#define TXRX_CSR2_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR2_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR2_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR2_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR2_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR2_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR2_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR2_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXRX_CSR3 * TXRX_CSR3
*/ */
#define TXRX_CSR3 0x304c #define TXRX_CSR3 0x304c
#define TXRX_CSR3_BBP_ID0 FIELD32(0x0000007f)
#define TXRX_CSR3_BBP_ID0_VALID FIELD32(0x00000080)
#define TXRX_CSR3_BBP_ID1 FIELD32(0x00007f00)
#define TXRX_CSR3_BBP_ID1_VALID FIELD32(0x00008000)
#define TXRX_CSR3_BBP_ID2 FIELD32(0x007f0000)
#define TXRX_CSR3_BBP_ID2_VALID FIELD32(0x00800000)
#define TXRX_CSR3_BBP_ID3 FIELD32(0x7f000000)
#define TXRX_CSR3_BBP_ID3_VALID FIELD32(0x80000000)
/* /*
* TXRX_CSR4: Auto-Responder/Tx-retry register. * TXRX_CSR4: Auto-Responder/Tx-retry register.
@ -332,11 +358,27 @@ struct hw_pairwise_ta_entry {
#define TXRX_CSR5 0x3054 #define TXRX_CSR5 0x3054
/* /*
* ACK/CTS payload consumed time registers. * TXRX_CSR6: ACK/CTS payload consumed time
*/ */
#define TXRX_CSR6 0x3058 #define TXRX_CSR6 0x3058
/*
* TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
*/
#define TXRX_CSR7 0x305c #define TXRX_CSR7 0x305c
#define TXRX_CSR7_ACK_CTS_6MBS FIELD32(0x000000ff)
#define TXRX_CSR7_ACK_CTS_9MBS FIELD32(0x0000ff00)
#define TXRX_CSR7_ACK_CTS_12MBS FIELD32(0x00ff0000)
#define TXRX_CSR7_ACK_CTS_18MBS FIELD32(0xff000000)
/*
* TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
*/
#define TXRX_CSR8 0x3060 #define TXRX_CSR8 0x3060
#define TXRX_CSR8_ACK_CTS_24MBS FIELD32(0x000000ff)
#define TXRX_CSR8_ACK_CTS_36MBS FIELD32(0x0000ff00)
#define TXRX_CSR8_ACK_CTS_48MBS FIELD32(0x00ff0000)
#define TXRX_CSR8_ACK_CTS_54MBS FIELD32(0xff000000)
/* /*
* TXRX_CSR9: Synchronization control register. * TXRX_CSR9: Synchronization control register.
@ -403,7 +445,6 @@ struct hw_pairwise_ta_entry {
#define PHY_CSR1 0x3084 #define PHY_CSR1 0x3084
#define PHY_CSR1_RF_RPI FIELD32(0x00010000) #define PHY_CSR1_RF_RPI FIELD32(0x00010000)
/* /*
* PHY_CSR2: Pre-TX BBP control. * PHY_CSR2: Pre-TX BBP control.
*/ */
@ -441,11 +482,13 @@ struct hw_pairwise_ta_entry {
* PHY_CSR5: RX to TX signal switch timing control. * PHY_CSR5: RX to TX signal switch timing control.
*/ */
#define PHY_CSR5 0x3094 #define PHY_CSR5 0x3094
#define PHY_CSR5_IQ_FLIP FIELD32(0x00000004)
/* /*
* PHY_CSR6: TX to RX signal timing control. * PHY_CSR6: TX to RX signal timing control.
*/ */
#define PHY_CSR6 0x3098 #define PHY_CSR6 0x3098
#define PHY_CSR6_IQ_FLIP FIELD32(0x00000004)
/* /*
* PHY_CSR7: TX DAC switching timing control. * PHY_CSR7: TX DAC switching timing control.
@ -460,6 +503,22 @@ struct hw_pairwise_ta_entry {
* SEC_CSR0: Shared key table control. * SEC_CSR0: Shared key table control.
*/ */
#define SEC_CSR0 0x30a0 #define SEC_CSR0 0x30a0
#define SEC_CSR0_BSS0_KEY0_VALID FIELD32(0x00000001)
#define SEC_CSR0_BSS0_KEY1_VALID FIELD32(0x00000002)
#define SEC_CSR0_BSS0_KEY2_VALID FIELD32(0x00000004)
#define SEC_CSR0_BSS0_KEY3_VALID FIELD32(0x00000008)
#define SEC_CSR0_BSS1_KEY0_VALID FIELD32(0x00000010)
#define SEC_CSR0_BSS1_KEY1_VALID FIELD32(0x00000020)
#define SEC_CSR0_BSS1_KEY2_VALID FIELD32(0x00000040)
#define SEC_CSR0_BSS1_KEY3_VALID FIELD32(0x00000080)
#define SEC_CSR0_BSS2_KEY0_VALID FIELD32(0x00000100)
#define SEC_CSR0_BSS2_KEY1_VALID FIELD32(0x00000200)
#define SEC_CSR0_BSS2_KEY2_VALID FIELD32(0x00000400)
#define SEC_CSR0_BSS2_KEY3_VALID FIELD32(0x00000800)
#define SEC_CSR0_BSS3_KEY0_VALID FIELD32(0x00001000)
#define SEC_CSR0_BSS3_KEY1_VALID FIELD32(0x00002000)
#define SEC_CSR0_BSS3_KEY2_VALID FIELD32(0x00004000)
#define SEC_CSR0_BSS3_KEY3_VALID FIELD32(0x00008000)
/* /*
* SEC_CSR1: Shared key table security mode register. * SEC_CSR1: Shared key table security mode register.
@ -635,10 +694,45 @@ struct hw_pairwise_ta_entry {
#define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) #define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff)
#define AC_TXOP_CSR1_AC3_TX_OP FIELD32(0xffff0000) #define AC_TXOP_CSR1_AC3_TX_OP FIELD32(0xffff0000)
/*
* BBP registers.
* The wordsize of the BBP is 8 bits.
*/
/*
* R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x20)
/*
* R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/* /*
* RF registers * RF registers
*/ */
/*
* RF 3
*/
#define RF3_TXPOWER FIELD32(0x00003e00) #define RF3_TXPOWER FIELD32(0x00003e00)
/*
* RF 4
*/
#define RF4_FREQ_OFFSET FIELD32(0x0003f000) #define RF4_FREQ_OFFSET FIELD32(0x0003f000)
/* /*
@ -763,34 +857,6 @@ struct hw_pairwise_ta_entry {
#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff) #define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff)
#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00) #define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00)
/*
* BBP content.
* The wordsize of the BBP is 8 bits.
*/
/*
* BBP_R2
*/
#define BBP_R2_BG_MODE FIELD8(0x20)
/*
* BBP_R3
*/
#define BBP_R3_SMART_MODE FIELD8(0x01)
/*
* BBP_R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
#define BBP_R4_RX_ANTENNA FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x10)
#define BBP_R4_RX_BG_MODE FIELD8(0x20)
/*
* BBP_R77
*/
#define BBP_R77_PAIR FIELD8(0x03)
/* /*
* DMA descriptor defines. * DMA descriptor defines.
*/ */
@ -888,7 +954,7 @@ struct hw_pairwise_ta_entry {
#define RXD_W0_MULTICAST FIELD32(0x00000008) #define RXD_W0_MULTICAST FIELD32(0x00000008)
#define RXD_W0_BROADCAST FIELD32(0x00000010) #define RXD_W0_BROADCAST FIELD32(0x00000010)
#define RXD_W0_MY_BSS FIELD32(0x00000020) #define RXD_W0_MY_BSS FIELD32(0x00000020)
#define RXD_W0_CRC FIELD32(0x00000040) #define RXD_W0_CRC_ERROR FIELD32(0x00000040)
#define RXD_W0_OFDM FIELD32(0x00000080) #define RXD_W0_OFDM FIELD32(0x00000080)
#define RXD_W0_CIPHER_ERROR FIELD32(0x00000300) #define RXD_W0_CIPHER_ERROR FIELD32(0x00000300)
#define RXD_W0_KEY_INDEX FIELD32(0x0000fc00) #define RXD_W0_KEY_INDEX FIELD32(0x0000fc00)